import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import { GripVertical, Play, Trash2, Upload } from 'lucide-react'
import { useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { deleteCollection } from '@/features/admin/collections/api'
import { useUploadStore } from '@/features/admin/media/upload-store'
import { deleteShow, renameShow } from '@/features/admin/shows/api'
import { qk } from '@/shared/api/query-keys'
import type { InterstitialDto } from '@/shared/api/types'
import { useApiError } from '@/shared/lib/use-api-error'
import { Badge } from '@/shared/ui/badge'
import { Button } from '@/shared/ui/button'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/shared/ui/dialog'
import { HlsVideo } from '@/shared/ui/hls-video'
import { Input } from '@/shared/ui/input'
import { BlockBuilder } from './BlockBuilder'
import { ClipGroupPanel } from './ClipGroupPanel'
import { mediaPreviewUrl } from '@/features/admin/media/api'
import { listInterstitialBlocks, listInterstitials } from './api'
import { setDragItem } from './dnd'
import { formatClock } from './format'

/**
 * Экран роликов (см. 6.7). Под капотом это `Show(Kind = Interstitial)` и коллекции, но сценарий
 * другой: массовая загрузка, длительности вместо метаданных и сборка блока перетаскиванием.
 */
export function InterstitialsPanel() {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const enqueue = useUploadStore((s) => s.enqueue)
  const fileInput = useRef<HTMLInputElement>(null)
  const [query, setQuery] = useState('')
  const [preview, setPreview] = useState<InterstitialDto | null>(null)
  const [renaming, setRenaming] = useState<{ id: string; name: string } | null>(null)

  const { data: clips, isLoading } = useQuery({
    queryKey: qk.interstitials.all,
    queryFn: listInterstitials,
  })
  const { data: blocks } = useQuery({
    queryKey: qk.interstitials.blocks,
    queryFn: listInterstitialBlocks,
  })

  const invalidate = () => {
    void queryClient.invalidateQueries({ queryKey: qk.interstitials.all })
  }
  const onError = useApiError()

  const renameMutation = useMutation({
    mutationFn: ({ id, name }: Readonly<{ id: string; name: string }>) => renameShow(id, name),
    onSuccess: () => {
      setRenaming(null)
      invalidate()
    },
    onError,
  })
  const deleteClipMutation = useMutation({
    mutationFn: (id: string) => deleteShow(id),
    onSuccess: invalidate,
    onError,
  })
  const deleteBlockMutation = useMutation({
    mutationFn: deleteCollection,
    onSuccess: invalidate,
    onError,
  })

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase()
    const all = clips ?? []
    return q ? all.filter((c) => c.name.toLowerCase().includes(q)) : all
  }, [clips, query])

  const pickFiles = (files: FileList | null) => {
    if (!files || files.length === 0) return
    void enqueue(Array.from(files), { interstitial: true })
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <h2 className="crt-glow text-xl font-semibold">{t('admin.interstitials.title')}</h2>
        <Button size="sm" onClick={() => fileInput.current?.click()}>
          <Upload className="h-4 w-4" /> {t('admin.interstitials.upload')}
        </Button>
        <input
          ref={fileInput}
          type="file"
          multiple
          className="hidden"
          onChange={(e) => {
            pickFiles(e.target.files)
            e.target.value = ''
          }}
        />
      </div>

      <p className="text-xs text-muted-foreground">{t('admin.interstitials.hint')}</p>

      <div className="grid gap-4 lg:grid-cols-[1fr_340px]">
        <div className="flex flex-col gap-4">
          <Input
            className="max-w-xs"
            placeholder={t('common.search')}
            value={query}
            onChange={(e) => setQuery(e.target.value)}
          />

          <div className="crt-panel overflow-x-auto rounded-md">
            <table className="w-full text-sm">
              <thead className="border-b border-border text-left text-muted-foreground">
                <tr>
                  <th className="px-4 py-2 font-medium">{t('admin.interstitials.name')}</th>
                  <th className="px-4 py-2 font-medium">{t('admin.interstitials.duration')}</th>
                  <th className="px-4 py-2 font-medium">{t('admin.media.status')}</th>
                  <th className="px-4 py-2 font-medium">{t('common.actions')}</th>
                </tr>
              </thead>
              <tbody>
                {isLoading && (
                  <tr>
                    <td className="px-4 py-3 text-muted-foreground" colSpan={4}>
                      {t('common.loading')}
                    </td>
                  </tr>
                )}
                {!isLoading && filtered.length === 0 && (
                  <tr>
                    <td className="px-4 py-3 text-muted-foreground" colSpan={4}>
                      {t('admin.interstitials.empty')}
                    </td>
                  </tr>
                )}
                {filtered.map((clip) => (
                  <tr
                    key={clip.id}
                    draggable
                    onDragStart={(e) =>
                      setDragItem(e, {
                        kind: 'clip',
                        id: clip.id,
                        name: clip.name,
                        seconds: clip.durationSeconds ?? 0,
                      })
                    }
                    className="border-b border-border last:border-0"
                  >
                    <td className="px-4 py-2">
                      <div className="flex items-center gap-2">
                        <GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground" />
                        {renaming?.id === clip.id ? (
                          <Input
                            autoFocus
                            className="h-8"
                            value={renaming.name}
                            maxLength={256}
                            onChange={(e) => setRenaming({ id: clip.id, name: e.target.value })}
                            onBlur={() =>
                              renaming.name.trim() && renaming.name !== clip.name
                                ? renameMutation.mutate({ id: clip.id, name: renaming.name.trim() })
                                : setRenaming(null)
                            }
                            onKeyDown={(e) => {
                              if (e.key === 'Enter') e.currentTarget.blur()
                              if (e.key === 'Escape') setRenaming(null)
                            }}
                          />
                        ) : (
                          <button
                            type="button"
                            className="min-w-0 truncate text-left hover:underline"
                            onClick={() => setRenaming({ id: clip.id, name: clip.name })}
                          >
                            {clip.name}
                          </button>
                        )}
                      </div>
                    </td>
                    <td className="px-4 py-2 tabular-nums text-muted-foreground">
                      {formatClock(clip.durationSeconds)}
                    </td>
                    <td className="px-4 py-2">
                      <Badge variant="muted">
                        {clip.assetStatus
                          ? t(`admin.media.statuses.${clip.assetStatus}`)
                          : t('admin.interstitials.noAsset')}
                      </Badge>
                    </td>
                    <td className="px-4 py-2">
                      <div className="flex items-center gap-1">
                        <Button
                          size="sm"
                          variant="ghost"
                          disabled={clip.assetStatus !== 'Ready'}
                          onClick={() => setPreview(clip)}
                        >
                          <Play className="h-4 w-4" />
                        </Button>
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => deleteClipMutation.mutate(clip.id)}
                        >
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="flex flex-col gap-2">
            <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              {t('admin.interstitials.blocks')}
            </h3>
            <div className="crt-panel rounded-md">
              {(blocks ?? []).length === 0 ? (
                <p className="px-4 py-3 text-sm text-muted-foreground">
                  {t('admin.interstitials.noBlocks')}
                </p>
              ) : (
                <ul className="divide-y divide-border text-sm">
                  {(blocks ?? []).map((block) => (
                    <li
                      key={block.id}
                      draggable
                      onDragStart={(e) =>
                        setDragItem(e, {
                          kind: 'block',
                          id: block.id,
                          name: block.name,
                          seconds: block.durationSeconds,
                        })
                      }
                      className="flex items-center gap-2 px-4 py-2"
                    >
                      <GripVertical className="h-4 w-4 shrink-0 cursor-grab text-muted-foreground" />
                      <Link
                        to="/admin/collections/$collectionId"
                        params={{ collectionId: block.id }}
                        className="min-w-0 flex-1 truncate text-primary hover:underline"
                      >
                        {block.name}
                      </Link>
                      <span className="shrink-0 text-muted-foreground">
                        {t('admin.interstitials.clipsCount', { count: block.itemCount })}
                      </span>
                      <span className="shrink-0 tabular-nums text-muted-foreground">
                        {formatClock(block.durationSeconds)}
                      </span>
                      <Button
                        size="sm"
                        variant="ghost"
                        onClick={() => deleteBlockMutation.mutate(block.id)}
                      >
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </li>
                  ))}
                </ul>
              )}
            </div>
          </div>
        </div>

        <div className="flex flex-col gap-6">
          <BlockBuilder onSaved={invalidate} onError={onError} />
          <ClipGroupPanel onError={onError} />
        </div>
      </div>

      <Dialog open={preview !== null} onOpenChange={(open) => !open && setPreview(null)}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>{preview?.name}</DialogTitle>
          </DialogHeader>
          {/* Кнопка в списке — это «плей», а не «открыть карточку»: жать ещё раз внутри окна
              незачем, ролик на тридцать секунд. */}
          {preview?.mediaAssetId && (
            <HlsVideo src={mediaPreviewUrl(preview.mediaAssetId)} autoPlay />
          )}
        </DialogContent>
      </Dialog>
    </div>
  )
}
