import { useQuery } from '@tanstack/react-query'
import { Upload } from 'lucide-react'
import { useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { qk } from '@/shared/api/query-keys'
import { Badge } from '@/shared/ui/badge'
import { Button } from '@/shared/ui/button'
import { DialogFooter } from '@/shared/ui/dialog'
import { listShows } from '@/features/admin/shows/api'
import { ShowPicker } from '@/features/admin/shows/ShowPicker'
import { compareParsed, formatSeasonEpisode, isValidRegex, parseEpisodeName } from './episode-parse'
import { EpisodeParseFields } from './EpisodeParseFields'
import { matchShowByName } from './match-show'
import { useUploadStore } from './upload-store'

/**
 * Загрузка выбранных файлов в шоу: сезон и номера серий разбираются здесь же, а сама заливка идёт
 * очередью с прогрессом. Файлы выбираются в самой вкладке — окно открывается кнопкой «Импорт»,
 * и требовать выбрать файлы **до** него значило бы прятать способ за проводником.
 */
export function UploadToShowPanel({ onClose }: Readonly<{ onClose: () => void }>) {
  const { t } = useTranslation()
  const enqueue = useUploadStore((s) => s.enqueue)
  const [files, setFiles] = useState<File[]>([])
  const fileInput = useRef<HTMLInputElement>(null)
  const [seasonStr, setSeasonStr] = useState('')
  const [regexStr, setRegexStr] = useState('')
  // Ручные правки привязки: имя файла → id шоу ('' — явно в библиотеку). Иначе берётся автоопределение.
  const [overrides, setOverrides] = useState<Record<string, string>>({})

  const { data: shows } = useQuery({ queryKey: qk.shows.all, queryFn: () => listShows() })

  const regexOk = isValidRegex(regexStr)
  const seasonOverride = seasonStr.trim() ? Number(seasonStr) : null

  // Автоопределение шоу по имени файла: id распознанного шоу для каждого файла (или undefined).
  const matchedByName = useMemo(() => {
    const map = new Map<string, string | undefined>()
    if (shows) for (const file of files) map.set(file.name, matchShowByName(file.name, shows))
    return map
  }, [files, shows])

  /** Итоговая привязка файла: ручная правка (если есть) либо автоопределение, иначе '' (в библиотеку). */
  const assignment = (name: string): string =>
    name in overrides ? overrides[name] : (matchedByName.get(name) ?? '')

  /** Проставить одно шоу (или «в библиотеку») всем файлам разом. */
  const applyToAll = (showId: string) =>
    setOverrides(Object.fromEntries(files.map((f) => [f.name, showId])))

  // Предпросмотр: что распарсим для каждого файла при текущих настройках, в порядке добавления.
  const previews = useMemo(() => {
    const opts = {
      seasonOverride:
        seasonOverride != null && Number.isFinite(seasonOverride) ? seasonOverride : null,
      episodeRegex: regexOk ? regexStr : null,
    }
    return files
      .map((file) => ({ file, name: file.name, parsed: parseEpisodeName(file.name, opts) }))
      .sort(compareParsed)
  }, [files, seasonOverride, regexStr, regexOk])

  const matchedCount = previews.filter((p) => assignment(p.name)).length

  const confirm = () => {
    void enqueue(
      previews.map((p) => p.file),
      { resolveShowId: (file) => assignment(file.name) || undefined },
    )
    onClose()
  }

  return (
    <>
      <p className="text-sm text-muted-foreground">{t('admin.media.autoDetectHint')}</p>

      <div className="flex flex-wrap items-center gap-2 text-sm">
        <input
          ref={fileInput}
          type="file"
          multiple
          accept="video/*,.mkv,.avi,.ts"
          className="hidden"
          onChange={(e) => {
            setFiles([...(e.target.files ?? [])])
            setOverrides({})
            e.target.value = ''
          }}
        />
        <Button size="sm" variant="outline" onClick={() => fileInput.current?.click()}>
          <Upload className="h-4 w-4" />
          {t('admin.media.toShowPick')}
        </Button>
        <span className="text-xs text-muted-foreground">
          {files.length === 0
            ? t('admin.media.toShowEmpty')
            : t('admin.media.toShowPicked', { count: files.length })}
        </span>
      </div>

      <div className="flex min-h-0 flex-1 flex-col gap-4">
        <div className="grid gap-3 sm:grid-cols-2">
          <EpisodeParseFields
            season={seasonStr}
            onSeason={setSeasonStr}
            regex={regexStr}
            onRegex={setRegexStr}
            regexOk={regexOk}
          />
        </div>
        <p className="text-xs text-muted-foreground">
          {t('admin.media.toShowHint')}
          {!regexOk && (
            <span className="ml-2 text-red-500">{t('admin.media.toShowRegexInvalid')}</span>
          )}
        </p>

        <div className="flex flex-wrap items-center justify-between gap-2 text-sm">
          <span className="font-medium">{t('admin.media.toShowPreview')}</span>
          <div className="flex items-center gap-2">
            <span className="text-muted-foreground">
              {t('admin.media.toShowMatched', { matched: matchedCount, total: files.length })}
            </span>
            {/* Значение не храним: выбор здесь — это действие «проставить всем», а не состояние,
                  поэтому на кнопке всегда её собственная подпись. */}
            <ShowPicker
              value=""
              shows={shows}
              noneLabel={t('admin.media.toShowLibrary')}
              placeholder={t('admin.media.applyToAll')}
              className="h-8 w-52"
              onChange={applyToAll}
            />
          </div>
        </div>
        <ul className="crt-panel min-h-0 flex-1 divide-y divide-border overflow-y-auto rounded-md text-sm">
          {previews.map((p) => {
            const label = formatSeasonEpisode(p.parsed)
            const current = assignment(p.name)
            return (
              <li key={p.name} className="flex items-center gap-2 px-3 py-1.5">
                {label ? (
                  <Badge>{label}</Badge>
                ) : (
                  <Badge variant="muted">{t('admin.media.toShowUnknown')}</Badge>
                )}
                <span className="min-w-0 flex-1 truncate" title={p.name}>
                  {p.name}
                </span>
                <ShowPicker
                  value={current}
                  shows={shows}
                  noneLabel={t('admin.media.toShowLibrary')}
                  className="h-8 w-56 shrink-0"
                  onChange={(showId) => setOverrides((o) => ({ ...o, [p.name]: showId }))}
                />
              </li>
            )
          })}
        </ul>
      </div>

      <DialogFooter>
        <Button variant="outline" size="sm" onClick={onClose}>
          {t('common.cancel')}
        </Button>
        <Button size="sm" disabled={files.length === 0} onClick={confirm}>
          {t('admin.media.toShowConfirm')}
        </Button>
      </DialogFooter>
    </>
  )
}
