import { useRef, useState, type FormEvent } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Trash2, Upload } from 'lucide-react'
import { ShellTopbar } from '@/components/layout/ShellTopbar'
import { AppFooter } from '@/components/layout/AppFooter'
import { Avatar } from '@/components/ui/Avatar'
import { Select } from '@/components/ui/Select'
import { useToast } from '@/components/ui/ToastProvider'
import { useAuth } from '@/auth/useAuth'
import { changePassword, deleteMyAvatar, listTeams, updateMe, uploadMyAvatar } from '@/api/users'
import { MyBackgroundsSection } from '@/components/background/MyBackgroundsSection'
import { usePublicSettings } from '@/hooks/usePublicSettings'
import { ApiError, errorDetail } from '@/api/client'
import '@/styles/lobby.css'
import '@/styles/profile.css'

/** Разрешённые типы файла аватара — те же ограничения, что и на backend. */
const ALLOWED_AVATAR_TYPES = ['image/jpeg', 'image/png', 'image/webp']
const MAX_AVATAR_BYTES = 2 * 1024 * 1024

/**
 * Страница профиля. Своя (текущий пользователь):
 * ФИО и команда редактируются, email — только чтение, аватар — загрузка с
 * клиентской предпроверкой типа/размера (дублирует лимиты backend — 413/415
 * обрабатываются и на случай, если предпроверка почему-то разошлась с
 * реальным лимитом сервера).
 *
 * Справочник команд — аутентифицированный `GET /api/v1/teams` (не зависит
 * от тумблера «разрешить выбор команды при регистрации», в отличие от
 * `GET /auth/registration-options`, который для этого экрана не подходит).
 */
export function ProfilePage() {
  const { user, refreshUser } = useAuth()
  const toast = useToast()
  const queryClient = useQueryClient()
  const fileInputRef = useRef<HTMLInputElement>(null)

  const [name, setName] = useState(user?.name_user ?? '')
  const [teamId, setTeamId] = useState(user?.team_id ?? '')
  const [avatarError, setAvatarError] = useState<string | null>(null)

  const { data: teams } = useQuery({ queryKey: ['teams'], queryFn: listTeams })
  // Раздел «Свои фоны» есть, только пока модуль включён в админке — иначе
  // картинкам, которые никак не применить, в профиле не место (то же правило,
  // что и с кнопкой «Фон» в комнате: выключенный модуль не оставляет мёртвых
  // элементов интерфейса).
  const { data: publicSettings } = usePublicSettings()
  const teamOptions = [{ value: '', label: 'Без команды' }, ...((teams ?? []).map((t) => ({ value: t.id, label: t.name })))]

  async function afterProfileChange() {
    await refreshUser()
    queryClient.invalidateQueries({ queryKey: ['conferences'] })
  }

  const saveMutation = useMutation({
    mutationFn: () => updateMe({ name_user: name.trim(), team_id: teamId === '' ? null : teamId }),
    onSuccess: async () => {
      await afterProfileChange()
      toast.show('Профиль сохранён', 'success')
    },
    onError: () => toast.show('Не удалось сохранить профиль', 'error'),
  })

  const avatarMutation = useMutation({
    mutationFn: (file: File) => uploadMyAvatar(file),
    onSuccess: async () => {
      await afterProfileChange()
      toast.show('Аватар обновлён', 'success')
    },
    onError: (err: unknown) => {
      if (err instanceof ApiError && err.status === 413) {
        toast.show('Файл слишком большой — максимум 2 МБ', 'error')
      } else if (err instanceof ApiError && err.status === 415) {
        toast.show('Недопустимый формат — только JPEG, PNG или WEBP', 'error')
      } else {
        toast.show('Не удалось загрузить аватар', 'error')
      }
    },
  })

  const deleteAvatarMutation = useMutation({
    mutationFn: () => deleteMyAvatar(),
    onSuccess: async () => {
      await afterProfileChange()
      toast.show('Аватар удалён', 'success')
    },
    onError: () => toast.show('Не удалось удалить аватар', 'error'),
  })

  const [currentPassword, setCurrentPassword] = useState('')
  const [newPassword, setNewPassword] = useState('')
  const [confirmPassword, setConfirmPassword] = useState('')
  const [passwordError, setPasswordError] = useState<string | null>(null)

  const passwordMutation = useMutation({
    mutationFn: () => changePassword({ current_password: currentPassword, new_password: newPassword }),
    onSuccess: () => {
      toast.show('Пароль изменён', 'success')
      setCurrentPassword('')
      setNewPassword('')
      setConfirmPassword('')
    },
    onError: (err: unknown) => {
      if (err instanceof ApiError && err.status === 400 && errorDetail(err) === 'invalid_current_password') {
        setPasswordError('Неверный текущий пароль')
      } else {
        toast.show('Не удалось сменить пароль', 'error')
      }
    },
  })

  function handlePasswordSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setPasswordError(null)
    if (newPassword.length < 8) {
      setPasswordError('Новый пароль должен быть не короче 8 символов')
      return
    }
    if (newPassword !== confirmPassword) {
      setPasswordError('Пароли не совпадают')
      return
    }
    passwordMutation.mutate()
  }

  function handleFileChange(file: File | null) {
    setAvatarError(null)
    if (!file) return
    if (!ALLOWED_AVATAR_TYPES.includes(file.type)) {
      setAvatarError('Недопустимый формат — только JPEG, PNG или WEBP')
      return
    }
    if (file.size > MAX_AVATAR_BYTES) {
      setAvatarError('Файл слишком большой — максимум 2 МБ')
      return
    }
    avatarMutation.mutate(file)
  }

  if (!user) return null

  return (
    <div className="page-shell">
      <ShellTopbar />
      <main className="page-main">
        <div className="page-head">
          <div>
            <h1>Профиль</h1>
            <p>Личные данные, команда и фото — видны другим участникам в составе конференций.</p>
          </div>
        </div>

        <section className="profile-card">
          <div className="profile-avatar-block">
            <Avatar name={user.name_user} avatarUrl={user.avatar_url} size={88} />
            <div className="profile-avatar-actions">
              <button
                type="button"
                className="btn btn-secondary"
                onClick={() => fileInputRef.current?.click()}
                disabled={avatarMutation.isPending}
              >
                <Upload style={{ width: 16, height: 16 }} aria-hidden="true" />
                {avatarMutation.isPending ? 'Загружаем…' : 'Загрузить фото'}
              </button>
              {user.avatar_url && (
                <button
                  type="button"
                  className="icon-btn"
                  aria-label="Удалить аватар"
                  onClick={() => deleteAvatarMutation.mutate()}
                  disabled={deleteAvatarMutation.isPending}
                >
                  <Trash2 style={{ width: 16, height: 16 }} aria-hidden="true" />
                </button>
              )}
              <input
                ref={fileInputRef}
                type="file"
                accept="image/jpeg,image/png,image/webp"
                style={{ display: 'none' }}
                onChange={(e) => {
                  handleFileChange(e.target.files?.[0] ?? null)
                  e.target.value = ''
                }}
              />
            </div>
            {avatarError && <p className="field-hint" style={{ color: 'var(--color-danger)' }}>{avatarError}</p>}
          </div>

          <form
            onSubmit={(e) => {
              e.preventDefault()
              saveMutation.mutate()
            }}
          >
            <div className="field">
              <label htmlFor="profile-name">ФИО</label>
              <input id="profile-name" type="text" value={name} onChange={(e) => setName(e.target.value)} maxLength={255} />
            </div>

            <div className="field">
              <label htmlFor="profile-email">Email</label>
              <input id="profile-email" type="email" value={user.email} disabled readOnly />
            </div>

            <div className="field">
              <label id="profile-team-label" htmlFor="profile-team">
                Команда
              </label>
              <Select
                id="profile-team"
                aria-labelledby="profile-team-label"
                value={teamId ?? ''}
                onChange={setTeamId}
                options={teamOptions}
              />
            </div>

            <button type="submit" className="btn btn-primary" disabled={saveMutation.isPending || !name.trim()}>
              {saveMutation.isPending ? 'Сохраняем…' : 'Сохранить изменения'}
            </button>
          </form>
        </section>

        {publicSettings?.virtual_background_enabled && <MyBackgroundsSection />}

        <section className="profile-card">
          <h2>Смена пароля</h2>
          <form onSubmit={handlePasswordSubmit}>
            <div className="field">
              <label htmlFor="profile-current-password">Текущий пароль</label>
              <input
                id="profile-current-password"
                type="password"
                autoComplete="current-password"
                required
                value={currentPassword}
                onChange={(e) => setCurrentPassword(e.target.value)}
              />
            </div>

            <div className="field">
              <label htmlFor="profile-new-password">Новый пароль</label>
              <input
                id="profile-new-password"
                type="password"
                autoComplete="new-password"
                required
                minLength={8}
                placeholder="Минимум 8 символов"
                value={newPassword}
                onChange={(e) => setNewPassword(e.target.value)}
              />
            </div>

            <div className={`field${passwordError ? ' has-error' : ''}`}>
              <label htmlFor="profile-confirm-password">Подтверждение пароля</label>
              <input
                id="profile-confirm-password"
                type="password"
                autoComplete="new-password"
                required
                value={confirmPassword}
                onChange={(e) => setConfirmPassword(e.target.value)}
              />
              {passwordError && (
                <p className="field-hint" style={{ color: 'var(--color-danger)' }}>
                  {passwordError}
                </p>
              )}
            </div>

            <button
              type="submit"
              className="btn btn-primary"
              disabled={passwordMutation.isPending || !currentPassword || !newPassword || !confirmPassword}
            >
              {passwordMutation.isPending ? 'Сохраняем…' : 'Сменить пароль'}
            </button>
          </form>
        </section>
      </main>
      <AppFooter />
    </div>
  )
}
