import { useCallback, useEffect, useState } from 'react'
import Alert from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Chip from '@mui/material/Chip'
import Stack from '@mui/material/Stack'
import TextField from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
import { useMutation } from '@tanstack/react-query'
import { useUnit } from 'effector-react'
import { useForm } from 'react-hook-form'
import { useSearchParams } from 'react-router-dom'
import { getErrorMessage } from '@/shared/lib/get-error-message'
import { isSyntheticEmail } from '@/shared/lib/is-synthetic-email'
import {
  $user,
  changePasswordFx,
  fetchAuthMethodsFx,
  requestEmailChangeFx,
  setPasswordFx,
  unlinkOAuthFx,
  type AuthMethod,
} from '@/shared/model/auth'

const METHOD_LABELS: Record<string, string> = { password: 'Пароль', vk: 'ВКонтакте', yandex: 'Яндекс' }

export function AuthMethodsSection() {
  const user = useUnit($user)

  const [authMethods, setAuthMethods] = useState<AuthMethod[]>([])
  const [showSetPassword, setShowSetPassword] = useState(false)
  const [fetchError, setFetchError] = useState<string | null>(null)
  const passwordForm = useForm<{ password: string; passwordConfirm: string }>({
    defaultValues: { password: '', passwordConfirm: '' },
  })

  useEffect(() => {
    fetchAuthMethodsFx()
      .then(setAuthMethods)
      .catch((err) => {
        setAuthMethods([])
        setFetchError(err?.message || 'Не удалось загрузить методы авторизации')
      })
  }, [])

  const setPasswordMutation = useMutation({
    mutationFn: async (pw: string) => {
      await setPasswordFx(pw)
      const methods = await fetchAuthMethodsFx()
      setAuthMethods(methods)
      setShowSetPassword(false)
    },
    onError: () => {},
  })

  const unlinkMutation = useMutation({
    mutationFn: async (provider: 'vk' | 'yandex') => {
      await unlinkOAuthFx(provider)
      const methods = await fetchAuthMethodsFx()
      setAuthMethods(methods)
    },
    onError: () => {},
  })

  const [showChangePassword, setShowChangePassword] = useState(false)
  const changePasswordForm = useForm<{ oldPassword: string; newPassword: string; confirmPassword: string }>({
    defaultValues: { oldPassword: '', newPassword: '', confirmPassword: '' },
  })

  const changePasswordMutation = useMutation({
    mutationFn: async (params: { oldPassword: string; newPassword: string }) => {
      await changePasswordFx(params)
    },
    onSuccess: () => {
      setShowChangePassword(false)
      changePasswordForm.reset()
    },
  })

  const linkedCount = useCallback(() => {
    return authMethods.filter((m) => m.active).length
  }, [authMethods])

  const [searchParams] = useSearchParams()
  const emailVerified = searchParams.get('emailVerified')

  const emailForm = useForm<{ email: string }>({
    defaultValues: { email: '' },
  })
  const [emailChangeError, setEmailChangeError] = useState<string | null>(null)
  const [verificationUrl, setVerificationUrl] = useState<string | null>(null)

  const emailChangeMutation = useMutation({
    mutationFn: async (email: string) => {
      setEmailChangeError(null)
      const url = await requestEmailChangeFx(email)
      return url
    },
    onSuccess: (url) => setVerificationUrl(url),
    onError: (err) => setEmailChangeError(getErrorMessage(err, 'Не удалось сменить email')),
  })

  if (!user) return null

  return (
    <Box>
      <Typography variant="h6" gutterBottom>
        Почта
      </Typography>

      {emailVerified === '1' && (
        <Alert severity="success" sx={{ mb: 2 }}>
          Почта успешно подтверждена
        </Alert>
      )}

      <Typography sx={{ mb: 2 }} color="text.secondary">
        {user.email}
      </Typography>

      {isSyntheticEmail(user.email) && (
        <Alert severity="info" sx={{ mb: 2 }}>
          Ваша почта сгенерирована автоматически. Без указания реальной почты вы не сможете получать уведомления о
          заказах.
        </Alert>
      )}

      {!verificationUrl && (
        <Stack direction="row" spacing={1} sx={{ mb: 2 }}>
          <TextField
            label="Новая почта"
            type="email"
            size="small"
            {...emailForm.register('email')}
            error={Boolean(emailChangeError)}
            helperText={emailChangeError}
          />
          <Button
            variant="outlined"
            disabled={!emailForm.watch('email') || emailChangeMutation.isPending}
            onClick={() => {
              const email = emailForm.getValues('email')
              if (email) emailChangeMutation.mutate(email)
            }}
          >
            Сменить
          </Button>
        </Stack>
      )}

      {verificationUrl && (
        <Alert severity="info" sx={{ mb: 2 }}>
          <Stack spacing={1} direction="row" sx={{ alignItems: 'center' }}>
            <span>Ссылка подтверждения готова.</span>
            <Button size="small" variant="contained" href={verificationUrl}>
              Подтвердить email
            </Button>
          </Stack>
        </Alert>
      )}

      <Typography variant="h6" gutterBottom sx={{ mt: 3 }}>
        Методы входа
      </Typography>
      {fetchError && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {fetchError}
        </Alert>
      )}
      <Stack spacing={1}>
        {authMethods.map((m) => (
          <Stack key={m.type} direction="row" spacing={2} sx={{ alignItems: 'center' }}>
            <Typography sx={{ minWidth: 120 }}>{METHOD_LABELS[m.type] || m.type}</Typography>
            <Chip label={m.active ? 'Привязан' : 'Не привязан'} color={m.active ? 'success' : 'default'} size="small" />
            {m.active && m.type !== 'password' && (
              <Button
                size="small"
                variant="outlined"
                color="error"
                disabled={linkedCount() <= 1}
                onClick={() => unlinkMutation.mutate(m.type as 'vk' | 'yandex')}
              >
                Отвязать
              </Button>
            )}
            {m.active && m.type === 'password' && (
              <Button size="small" variant="outlined" onClick={() => setShowChangePassword(true)}>
                Сменить пароль
              </Button>
            )}
            {!m.active && m.type === 'password' && (
              <Button size="small" variant="outlined" onClick={() => setShowSetPassword(true)}>
                Установить пароль
              </Button>
            )}
            {!m.active && m.type !== 'password' && (
              <Button
                size="small"
                variant="outlined"
                component="a"
                href={`/api/auth/oauth/${m.type}/link?token=${localStorage.getItem('craftshop_auth_token') || ''}`}
              >
                Привязать
              </Button>
            )}
          </Stack>
        ))}
      </Stack>

      {showSetPassword && (
        <Stack spacing={2} sx={{ mt: 2, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
          <TextField label="Пароль" type="password" {...passwordForm.register('password')} fullWidth />
          <TextField
            label="Подтверждение пароля"
            type="password"
            {...passwordForm.register('passwordConfirm')}
            fullWidth
            error={
              Boolean(passwordForm.watch('passwordConfirm')) &&
              passwordForm.watch('password') !== passwordForm.watch('passwordConfirm')
            }
            helperText={
              passwordForm.watch('passwordConfirm') &&
              passwordForm.watch('password') !== passwordForm.watch('passwordConfirm')
                ? 'Пароли не совпадают'
                : null
            }
          />
          <Stack direction="row" spacing={1}>
            <Button
              variant="contained"
              disabled={
                !passwordForm.watch('password') ||
                passwordForm.watch('password').length < 8 ||
                passwordForm.watch('password') !== passwordForm.watch('passwordConfirm') ||
                setPasswordMutation.isPending
              }
              onClick={() => setPasswordMutation.mutate(passwordForm.getValues('password'))}
            >
              Сохранить
            </Button>
            <Button variant="text" onClick={() => setShowSetPassword(false)}>
              Отмена
            </Button>
          </Stack>
        </Stack>
      )}

      {showChangePassword && (
        <Stack spacing={2} sx={{ mt: 2, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
          <TextField label="Текущий пароль" type="password" {...changePasswordForm.register('oldPassword')} fullWidth />
          <TextField label="Новый пароль" type="password" {...changePasswordForm.register('newPassword')} fullWidth />
          <TextField
            label="Подтверждение пароля"
            type="password"
            {...changePasswordForm.register('confirmPassword')}
            fullWidth
            error={
              Boolean(changePasswordForm.watch('confirmPassword')) &&
              changePasswordForm.watch('newPassword') !== changePasswordForm.watch('confirmPassword')
            }
            helperText={
              changePasswordForm.watch('confirmPassword') &&
              changePasswordForm.watch('newPassword') !== changePasswordForm.watch('confirmPassword')
                ? 'Пароли не совпадают'
                : null
            }
          />
          <Stack direction="row" spacing={1}>
            <Button
              variant="contained"
              disabled={
                !changePasswordForm.watch('oldPassword') ||
                !changePasswordForm.watch('newPassword') ||
                changePasswordForm.watch('newPassword').length < 8 ||
                changePasswordForm.watch('newPassword') !== changePasswordForm.watch('confirmPassword') ||
                changePasswordMutation.isPending
              }
              onClick={() =>
                changePasswordMutation.mutate({
                  oldPassword: changePasswordForm.getValues('oldPassword'),
                  newPassword: changePasswordForm.getValues('newPassword'),
                })
              }
            >
              Сохранить
            </Button>
            <Button variant="text" onClick={() => setShowChangePassword(false)}>
              Отмена
            </Button>
          </Stack>
        </Stack>
      )}
    </Box>
  )
}
