import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Pencil, Plus, Trash2 } from 'lucide-react'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import { z } from 'zod'
import { qk } from '@/shared/api/query-keys'
import type { GenreDto } 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, DialogFooter, DialogHeader, DialogTitle } from '@/shared/ui/dialog'
import { Input } from '@/shared/ui/input'
import { Label } from '@/shared/ui/label'
import { sortRows, useTableSort } from '@/shared/lib/table-sort'
import { Pager } from '@/shared/ui/pager'
import { SortHeader } from '@/shared/ui/sortable'
import { createGenre, deleteGenre, listGenres, updateGenre } from './api'

const createSchema = z.object({
  name: z.string().min(1).max(128),
  slug: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z0-9-]+$/),
  aliases: z.string().max(1024).optional(),
})

const editSchema = z.object({
  name: z.string().min(1).max(128),
  sortOrder: z.number().int().min(0),
  aliases: z.string().max(1024).optional(),
})

type CreateValues = z.infer<typeof createSchema>
type EditValues = z.infer<typeof editSchema>

/**
 * Жанров бывает под сотню (базовый набор плюс заведённые руками), и все они грузятся одним
 * запросом — список нужен целиком селектам жанра по всей админке. Поэтому страницы режутся здесь,
 * а не на сервере: таблица остаётся читаемой, а пикеры продолжают получать полный справочник.
 */
const PAGE_SIZE = 20

/** Псевдонимы вводятся одной строкой через запятую — их редко больше десятка. */
function parseAliases(value: string | undefined): string[] {
  return (value ?? '')
    .split(',')
    .map((item) => item.trim())
    .filter((item) => item.length > 0)
}

export function GenresPanel() {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const { data: genres, isLoading } = useQuery({
    queryKey: qk.genres.all,
    queryFn: listGenres,
  })
  const { sort, toggle } = useTableSort('sortOrder', false)
  const [page, setPage] = useState(1)

  const sortedGenres = sortRows(genres ?? [], sort, {
    sortOrder: (g) => g.sortOrder,
    name: (g) => g.name.toLowerCase(),
    slug: (g) => g.slug,
    showCount: (g) => g.showCount,
  })

  // Страница может уехать за конец списка после удаления — тогда показываем последнюю.
  const totalPages = Math.max(1, Math.ceil(sortedGenres.length / PAGE_SIZE))
  const current = Math.min(page, totalPages)
  const visible = sortedGenres.slice((current - 1) * PAGE_SIZE, current * PAGE_SIZE)

  const sortColumn = (key: string) => {
    setPage(1)
    toggle(key)
  }

  const invalidate = () => queryClient.invalidateQueries({ queryKey: qk.genres.all })
  const reportError = useApiError()

  const createMutation = useMutation({ mutationFn: createGenre, onSuccess: invalidate })
  const updateMutation = useMutation({
    mutationFn: ({
      id,
      ...body
    }: Readonly<{
      id: string
      name: string
      sortOrder: number
      aliases: string[]
    }>) => updateGenre(id, body),
    onSuccess: invalidate,
  })
  const deleteMutation = useMutation({
    mutationFn: deleteGenre,
    onSuccess: invalidate,
    onError: reportError,
  })

  const [createOpen, setCreateOpen] = useState(false)
  const [editing, setEditing] = useState<GenreDto | null>(null)

  const createForm = useForm<CreateValues>({ resolver: zodResolver(createSchema) })
  const editForm = useForm<EditValues>({ resolver: zodResolver(editSchema) })

  const openEdit = (genre: GenreDto) => {
    setEditing(genre)
    editForm.reset({
      name: genre.name,
      sortOrder: genre.sortOrder,
      aliases: genre.aliases.join(', '),
    })
  }

  const onCreate = async (values: CreateValues) => {
    try {
      await createMutation.mutateAsync({
        name: values.name,
        slug: values.slug,
        aliases: parseAliases(values.aliases),
      })
      createForm.reset()
      setCreateOpen(false)
    } catch (error) {
      reportError(error)
    }
  }

  const onEdit = async (values: EditValues) => {
    if (!editing) return
    try {
      await updateMutation.mutateAsync({
        id: editing.id,
        name: values.name,
        sortOrder: values.sortOrder,
        aliases: parseAliases(values.aliases),
      })
      setEditing(null)
    } catch (error) {
      reportError(error)
    }
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-between gap-4">
        <div className="flex flex-col gap-1">
          <h2 className="crt-glow text-xl font-semibold">{t('admin.genres.title')}</h2>
          <p className="text-sm text-muted-foreground">{t('admin.genres.hint')}</p>
        </div>
        <Button size="sm" onClick={() => setCreateOpen(true)}>
          <Plus className="h-4 w-4" /> {t('admin.genres.create')}
        </Button>
      </div>

      <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>
              <SortHeader
                label={t('admin.genres.order')}
                sortKey="sortOrder"
                sort={sort}
                onToggle={sortColumn}
              />
              <SortHeader
                label={t('admin.genres.name')}
                sortKey="name"
                sort={sort}
                onToggle={sortColumn}
              />
              <SortHeader
                label={t('admin.genres.slug')}
                sortKey="slug"
                sort={sort}
                onToggle={sortColumn}
              />
              <th className="px-4 py-2 font-medium">{t('admin.genres.aliases')}</th>
              <SortHeader
                label={t('admin.genres.usage')}
                sortKey="showCount"
                sort={sort}
                onToggle={sortColumn}
              />
              <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={6}>
                  {t('common.loading')}
                </td>
              </tr>
            )}
            {visible.map((genre) => (
              <tr key={genre.id} className="border-b border-border last:border-0">
                <td className="px-4 py-2 text-muted-foreground">{genre.sortOrder}</td>
                <td className="px-4 py-2">
                  <div className="flex items-center gap-2">
                    {genre.name}
                    {genre.isSystem && <Badge variant="muted">{t('admin.genres.system')}</Badge>}
                  </div>
                </td>
                <td className="px-4 py-2 font-mono text-xs text-muted-foreground">{genre.slug}</td>
                <td className="max-w-md px-4 py-2 text-xs text-muted-foreground">
                  {genre.aliases.join(', ')}
                </td>
                <td className="px-4 py-2">{genre.showCount}</td>
                <td className="px-4 py-2">
                  <div className="flex gap-2">
                    <Button size="sm" variant="outline" onClick={() => openEdit(genre)}>
                      <Pencil className="h-4 w-4" />
                    </Button>
                    <Button
                      size="sm"
                      variant="destructive"
                      disabled={genre.isSystem || genre.showCount > 0}
                      onClick={() => deleteMutation.mutate(genre.id)}
                    >
                      <Trash2 className="h-4 w-4" />
                    </Button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <Pager page={current} totalPages={totalPages} onChange={setPage} />

      <Dialog open={createOpen} onOpenChange={setCreateOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t('admin.genres.create')}</DialogTitle>
          </DialogHeader>
          <form className="flex flex-col gap-4" onSubmit={createForm.handleSubmit(onCreate)}>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="genreName">{t('admin.genres.name')}</Label>
              <Input id="genreName" {...createForm.register('name')} />
            </div>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="genreSlug">{t('admin.genres.slug')}</Label>
              <Input id="genreSlug" placeholder="action" {...createForm.register('slug')} />
              <p className="text-xs text-muted-foreground">{t('admin.genres.slugHint')}</p>
            </div>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="genreAliases">{t('admin.genres.aliases')}</Label>
              <Input
                id="genreAliases"
                placeholder="tmdb:28, action"
                {...createForm.register('aliases')}
              />
              <p className="text-xs text-muted-foreground">{t('admin.genres.aliasesHint')}</p>
            </div>
            <DialogFooter>
              <Button type="submit" disabled={createMutation.isPending}>
                {t('common.create')}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={editing !== null} onOpenChange={(open) => !open && setEditing(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t('admin.genres.edit')}</DialogTitle>
          </DialogHeader>
          <form className="flex flex-col gap-4" onSubmit={editForm.handleSubmit(onEdit)}>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="editGenreName">{t('admin.genres.name')}</Label>
              <Input id="editGenreName" {...editForm.register('name')} />
            </div>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="editGenreOrder">{t('admin.genres.order')}</Label>
              <Input
                id="editGenreOrder"
                type="number"
                {...editForm.register('sortOrder', { valueAsNumber: true })}
              />
            </div>
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="editGenreAliases">{t('admin.genres.aliases')}</Label>
              <Input id="editGenreAliases" {...editForm.register('aliases')} />
              <p className="text-xs text-muted-foreground">{t('admin.genres.aliasesHint')}</p>
            </div>
            <DialogFooter>
              <Button type="submit" disabled={updateMutation.isPending}>
                {t('common.save')}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>
    </div>
  )
}
