import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import { Bug, ChevronLeft, Send, Undo2 } from 'lucide-react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { listAllMedia } from '@/features/admin/media/api'
import { qk } from '@/shared/api/query-keys'
import type { ApplyResultDto } from '@/shared/api/types'
import { cn } from '@/shared/lib/cn'
import { useApiError } from '@/shared/lib/use-api-error'
import { Badge } from '@/shared/ui/badge'
import { Button } from '@/shared/ui/button'
import { Card, CardContent } from '@/shared/ui/card'
import { toast } from '@/shared/ui/toast-store'
import {
  applyChannelTemplate,
  exportChannelDebug,
  getChannel,
  getChannelTemplate,
  restoreChannelTemplate,
} from './api'
import { AirSchedule } from './components/AirSchedule'
import { ApplyDialog } from './components/ApplyDialog'
import { ApplyReportDialog } from './components/ApplyReportDialog'
import { EntryTraceDialog } from './components/EntryTraceDialog'
import { GridTab } from './components/GridTab'
import { JunctionsCard } from './components/JunctionsCard'
import { RulesCard } from './components/RulesCard'
import { SettingsCard } from './components/SettingsCard'
import { ViewerCard } from './components/ViewerCard'

/** Вкладки экрана канала: настройки первыми — с них канал и начинается. */
const TABS = ['settings', 'grid', 'rules', 'junctions', 'viewer', 'air'] as const
type ChannelTab = (typeof TABS)[number]

export function ChannelDetail({ channelId }: Readonly<{ channelId: string }>) {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const [applyOpen, setApplyOpen] = useState(false)
  const [applyReport, setApplyReport] = useState<ApplyResultDto | null>(null)
  const [traceEntryId, setTraceEntryId] = useState<string | null>(null)
  const [tab, setTab] = useState<ChannelTab>('settings')

  const { data: channel, isLoading } = useQuery({
    queryKey: qk.channels.detail(channelId),
    queryFn: () => getChannel(channelId),
  })
  const { data: template, error: templateError } = useQuery({
    queryKey: qk.channels.template(channelId),
    queryFn: () => getChannelTemplate(channelId),
  })
  const { data: ready } = useQuery({
    queryKey: qk.media.ready,
    queryFn: () => listAllMedia({ statuses: ['Ready'] }),
  })
  const invalidate = () => {
    void queryClient.invalidateQueries({ queryKey: qk.channels.detail(channelId) })
    // Применение пересобирает хвост ленты — открытые сутки эфира надо перечитать, иначе на
    // вкладке останется то, что уже заменено.
    void queryClient.invalidateQueries({ queryKey: qk.channels.schedule(channelId) })
  }
  const onError = useApiError()

  const debugMutation = useMutation({
    mutationFn: () => exportChannelDebug(channelId),
    onSuccess: (fileName) => toast.success(fileName),
    onError,
  })

  const applyMutation = useMutation({
    mutationFn: () => applyChannelTemplate(channelId),
    onSuccess: (result) => {
      setApplyOpen(false)
      // Предупреждений бывают десятки — тостом на каждое экран превращается в стену. Есть
      // предупреждения — открываем отчёт, нет — хватает одной строки об успехе.
      if (result.warnings.length > 0) setApplyReport(result)
      else toast.success(t('admin.channels.applied', { count: result.added }))
      invalidate()
    },
    onError,
  })

  const restoreMutation = useMutation({
    mutationFn: () => restoreChannelTemplate(channelId),
    onSuccess: (result) => {
      toast.success(t('admin.channels.restored', { count: result.slots }))
      // Ссылка на удалённую группу или стык вернуться не может — говорим об этом прямо.
      if (result.droppedRefs > 0)
        toast.error(t('admin.channels.restoreDropped', { count: result.droppedRefs }))
      invalidate()
    },
    onError,
  })

  if (isLoading || !channel) return <p className="text-muted-foreground">{t('common.loading')}</p>

  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <Button asChild size="sm" variant="ghost">
          <Link to="/admin/channels">
            <ChevronLeft className="h-4 w-4" />
            {t('admin.channels.title')}
          </Link>
        </Button>

        <div className="flex flex-wrap items-center gap-2">
          <h2 className="crt-glow text-xl font-semibold">{channel.name}</h2>
          {channel.number !== null && <Badge variant="muted">№ {channel.number}</Badge>}
          {!channel.isEnabled && <Badge variant="muted">{t('admin.channels.disabled')}</Badge>}
          {/* Дамп для разбора «почему сетка построилась так»: архив уезжает в браузер, а копия
              остаётся на сервере, если каталог настроен. */}
          <Button
            size="sm"
            variant="outline"
            title={t('admin.channels.debugExportHint')}
            disabled={debugMutation.isPending}
            onClick={() => debugMutation.mutate()}
          >
            <Bug className="h-4 w-4" /> {t('admin.channels.debugExport')}
          </Button>
        </div>
      </div>

      {/* Правка правил эфира не двигает — применение отдельной кнопкой. Рядом откат: правки
          сетки правятся на месте, и без этой кнопки вернуть «как в эфире» было бы нечем. */}
      {template?.hasPendingChanges && (
        <div className="flex flex-wrap items-center justify-between gap-3 rounded-md border border-amber-500/50 bg-amber-500/10 px-4 py-2 text-sm">
          <span>{t('admin.channels.pendingChanges')}</span>
          <div className="flex flex-wrap items-center gap-2">
            {/* Кнопки отката нет, пока сетку ни разу не применяли: возвращаться некуда. */}
            {template.canRestore && (
              <Button
                size="sm"
                variant="outline"
                disabled={restoreMutation.isPending}
                onClick={() => {
                  // Откат необратим — он стирает всё, сделанное с последнего применения.
                  if (!window.confirm(t('admin.channels.restoreConfirm'))) return
                  restoreMutation.mutate()
                }}
              >
                <Undo2 className="h-4 w-4" /> {t('admin.channels.restore')}
              </Button>
            )}
            <Button size="sm" disabled={applyMutation.isPending} onClick={() => setApplyOpen(true)}>
              <Send className="h-4 w-4" /> {t('admin.channels.apply')}
            </Button>
          </div>
        </div>
      )}

      {/* Вкладки вместо колонки карточек: экран канала перестал помещаться в один свиток. */}
      <nav className="flex flex-wrap gap-4 border-b border-border text-xs uppercase tracking-wide">
        {TABS.map((value) => (
          <button
            key={value}
            type="button"
            onClick={() => setTab(value)}
            className={cn(
              'pb-2 text-muted-foreground hover:text-foreground',
              tab === value && 'border-b-2 border-primary text-primary',
            )}
          >
            {t(`admin.channels.tabs.${value}`)}
          </button>
        ))}
      </nav>

      {tab === 'settings' && (
        <SettingsCard
          channel={channel}
          readyAssets={ready?.items ?? []}
          bare
          onSaved={invalidate}
          onError={onError}
        />
      )}

      {tab === 'grid' && (
        <GridTab
          channelId={channelId}
          channelName={channel.name}
          template={template}
          templateError={templateError}
          onChanged={invalidate}
          onError={onError}
        />
      )}

      {tab === 'rules' &&
        (template ? (
          <RulesCard template={template} bare onChanged={invalidate} onError={onError} />
        ) : (
          <p className="text-sm text-muted-foreground">{t('admin.channels.noTemplate')}</p>
        ))}

      {tab === 'junctions' && (
        <JunctionsCard template={template} bare onChanged={invalidate} onError={onError} />
      )}

      {tab === 'viewer' && (
        <ViewerCard channel={channel} bare onSaved={invalidate} onError={onError} />
      )}

      {tab === 'air' && (
        <Card>
          <CardContent>
            <AirSchedule
              channelId={channelId}
              utcOffsetMinutes={channel.utcOffsetMinutes}
              dayStartTime={channel.dayStartTime}
              onShowTrace={setTraceEntryId}
            />
          </CardContent>
        </Card>
      )}

      {applyOpen && (
        <ApplyDialog
          channelId={channelId}
          utcOffsetMinutes={channel.utcOffsetMinutes}
          pending={applyMutation.isPending}
          onApply={() => applyMutation.mutate()}
          onClose={() => setApplyOpen(false)}
        />
      )}

      {applyReport && (
        <ApplyReportDialog result={applyReport} onClose={() => setApplyReport(null)} />
      )}

      {traceEntryId && (
        <EntryTraceDialog
          entryId={traceEntryId}
          utcOffsetMinutes={channel.utcOffsetMinutes}
          onClose={() => setTraceEntryId(null)}
        />
      )}
    </div>
  )
}
