import { useRef, useState } from 'react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { Trash2, Upload } from 'lucide-react'
import { deleteMyBackground, uploadMyBackground } from '@/api/users'
import { ApiError } from '@/api/client'
import { useToast } from '@/components/ui/ToastProvider'
import { MY_BACKGROUNDS_QUERY_KEY, useMyBackgrounds } from '@/hooks/useMyBackgrounds'
import { ImageDecodeError, resizeImageForBackground } from '@/lib/imageResize'
import { isDesktopDevice } from '@/lib/isDesktopDevice'
import '@/styles/virtual-background.css'

/** Что вообще можно выбрать в диалоге файлов — совпадает с проверкой на сервере. */
const ACCEPTED_TYPES = 'image/jpeg,image/png,image/webp'

/**
 * Секция профиля «Свои фоны» — загрузка и удаление картинок для замены фона
 * видео («личный кабинет» из задачи).
 *
 * Загрузка идёт с предварительным СЖАТИЕМ в браузере (`lib/imageResize.ts`):
 * «ужимать до приемлемого размера, чтобы не грузили БД» — требование задачи.
 * Сервер картинку не пережимает, но полноценно валидирует.
 *
 * Лимит на число картинок приходит с сервера (`limit` в ответе списка) — он
 * там же и проверяется; здесь кнопка просто гаснет заранее, чтобы не отправлять
 * запрос, заведомо обречённый на 409.
 *
 * Удаление применённого сейчас фона отдельно обрабатывать не нужно: выбор
 * хранится ключом `custom:<id>`, и как только записи с таким id не стало,
 * `useVirtualBackground` сам сбрасывает фон на «без фона».
 */
export function MyBackgroundsSection() {
  const toast = useToast()
  const queryClient = useQueryClient()
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [error, setError] = useState<string | null>(null)
  const { items, limit } = useMyBackgrounds(true)
  // Раздел показывается на любом устройстве (загрузить картинки заранее с
  // телефона — нормальный сценарий), но на не-десктопе честно предупреждаем,
  // что применить фон получится только на компьютере: см. `isDesktopDevice`.
  const [desktop] = useState(isDesktopDevice)

  const invalidate = () => queryClient.invalidateQueries({ queryKey: MY_BACKGROUNDS_QUERY_KEY })

  const uploadMutation = useMutation({
    mutationFn: async (file: File) => uploadMyBackground(await resizeImageForBackground(file)),
    onSuccess: async () => {
      await invalidate()
      toast.show('Фон добавлен', 'success')
    },
    onError: (err: unknown) => {
      if (err instanceof ImageDecodeError) {
        setError('Не удалось прочитать картинку — возможно, файл повреждён')
      } else if (err instanceof ApiError && err.status === 409) {
        setError(`Больше ${limit} картинок хранить нельзя — удалите ненужную`)
      } else if (err instanceof ApiError && err.status === 413) {
        setError('Файл слишком большой даже после сжатия')
      } else if (err instanceof ApiError && err.status === 415) {
        setError('Недопустимый формат — только JPEG, PNG или WEBP')
      } else {
        toast.show('Не удалось загрузить фон', 'error')
      }
    },
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => deleteMyBackground(id),
    onSuccess: async () => {
      await invalidate()
      toast.show('Фон удалён', 'success')
    },
    onError: () => toast.show('Не удалось удалить фон', 'error'),
  })

  const limitReached = limit > 0 && items.length >= limit
  const busy = uploadMutation.isPending || deleteMutation.isPending

  return (
    <section className="profile-card">
      <h2>Свои фоны</h2>
      <p className="field-hint" style={{ margin: 0 }}>
        Картинки для замены фона видео в конференции. Не больше {limit || 10} штук; перед
        отправкой картинка автоматически уменьшается.
        {!desktop && ' Сама замена фона работает только на компьютере — на телефоне она' +
          ' отключена, чтобы не нагружать устройство.'}
      </p>

      {items.length > 0 && (
        <div className="bg-manage-grid">
          {items.map((item, index) => (
            <div key={item.id} className="bg-manage-tile">
              <img src={item.url} alt={`Свой фон ${index + 1}`} loading="lazy" />
              <button
                type="button"
                className="bg-tile-delete"
                aria-label={`Удалить свой фон ${index + 1}`}
                disabled={busy}
                onClick={() => {
                  setError(null)
                  deleteMutation.mutate(item.id)
                }}
              >
                <Trash2 className="lucide" aria-hidden="true" />
              </button>
            </div>
          ))}
        </div>
      )}

      <div className="profile-avatar-actions">
        <button
          type="button"
          className="btn btn-secondary"
          disabled={busy || limitReached}
          onClick={() => fileInputRef.current?.click()}
        >
          <Upload style={{ width: 16, height: 16 }} aria-hidden="true" />
          {uploadMutation.isPending ? 'Загружаем…' : 'Добавить фон'}
        </button>
        <span className="field-hint">
          {items.length} из {limit || 10}
        </span>
        <input
          ref={fileInputRef}
          type="file"
          accept={ACCEPTED_TYPES}
          style={{ display: 'none' }}
          onChange={(e) => {
            const file = e.target.files?.[0] ?? null
            e.target.value = ''
            setError(null)
            if (file) uploadMutation.mutate(file)
          }}
        />
      </div>

      {error && (
        <p className="field-hint" style={{ color: 'var(--color-danger)', margin: 0 }}>
          {error}
        </p>
      )}
    </section>
  )
}
