import { Link, router } from '@inertiajs/react'
import { DatabaseIcon, DownloadIcon, TriangleAlertIcon } from 'lucide-react'
import type { FormEvent } from 'react'
import { useState } from 'react'

import { BatchProgress } from '@/components/BatchProgress'
import { DataTimestamp } from '@/components/DataTimestamp'
import { EmptyState } from '@/components/EmptyState'
import { FormDialog } from '@/components/FormDialog'
import { SectionCard } from '@/components/SectionCard'
import { Button } from '@/components/ui/button'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { useBatchPolling } from '@/hooks/useBatchPolling'
import { AppLayout } from '@/layouts/AppLayout'
import { t } from '@/lib/i18n'
import { route } from '@/lib/routes'
import { ModuleStatusBadge } from '@/pages/Seo/status'
import { RunRow } from '@/pages/Seo/runs'
import type { Overview, RunProps, SiteProps } from '@/pages/Seo/types'

interface Props {
  domain: SiteProps | null
  overview?: Overview
  history?: RunProps[]
  history_total?: number
  months?: number[]
  can_import?: boolean
  imported?: boolean
  /** La segunda importación de quien administra borra y repuebla. */
  destructive?: boolean
}

/**
 * La conexión del módulo: si puede trabajar, traer historia, y qué se trajo.
 *
 * Las tres cosas juntas y no en pantallas separadas. Quien entra acá viene a
 * resolver que el módulo tenga datos, y el historial es cómo se comprueba que
 * quedó resuelto: una vista de corridas aparte sería una entrada más de menú
 * para algo que casi nunca se mira.
 */
export default function Connection({
  domain,
  overview,
  history = [],
  history_total = 0,
  months = [],
  can_import = false,
  imported = false,
  destructive = false,
}: Props) {
  const [pending, setPending] = useState(false)
  const [selected, setSelected] = useState(String(months.at(-1) ?? 12))

  if (domain == null || overview == null) {
    return (
      <AppLayout title={t('seo.connection.title')} description={t('seo.connection.description')}>
        <EmptyState
          icon={DatabaseIcon}
          title={t('seo.noSite.title')}
          description={t('seo.noSite.description')}
        />
      </AppLayout>
    )
  }

  function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    router.post(
      route('seo.backfill'),
      { months: selected },
      { onStart: () => setPending(true), onFinish: () => setPending(false) }
    )
  }

  // La pantalla se actualiza sola mientras haya una corrida abierta, por el
  // único mecanismo del producto. Sin esto se quedaría clavada en lo que había
  // al cargar: la importación corre por detrás, así que su avance llega después
  // de que la página ya se dibujó. Corta sola al terminar.
  const running = useBatchPolling({
    states: [overview.last_run?.state],
    only: ['overview', 'history', 'history_total', 'can_import', 'imported', 'destructive'],
  })

  return (
    <AppLayout title={t('seo.connection.title')} description={t('seo.connection.description')}>
      <SectionCard
        title={{ text: t('seo.connection.state.title') }}
        description={t('seo.connection.state.description')}
        actions={<ModuleStatusBadge status={overview.status} code={overview.error_code} />}
        footer={
          can_import ? (
            <Button asChild variant={destructive ? 'destructive' : 'default'}>
              <Link href="?import" preserveScroll>
                {destructive ? (
                  <TriangleAlertIcon aria-hidden />
                ) : (
                  <DownloadIcon aria-hidden />
                )}
                {destructive ? t('seo.import.again') : t('seo.import.action')}
              </Link>
            </Button>
          ) : undefined
        }
      >
        <dl className="grid gap-4 sm:grid-cols-3">
          <Pair
            label={t('seo.overview.upTo')}
            value={overview.last_closed_date ?? t('seo.overview.none')}
          />
          <Pair
            label={t('seo.overview.since')}
            value={overview.coverage_start ?? t('seo.overview.none')}
          />
          <Pair
            label={t('seo.overview.lastSync')}
            value={
              <DataTimestamp
                value={overview.last_sync_at}
                emptyLabel={t('seo.overview.none')}
              />
            }
          />
        </dl>

        {/*
          El avance sale por la misma pieza que usa la otra herramienta: la
          corrida publica `state`, `total_items` y `processed_items` con esos
          nombres justamente para poder reusarla sin tocarla.
        */}
        {running && overview.last_run ? (
          <BatchProgress
            state={overview.last_run.state}
            total={overview.last_run.total_items}
            processed={overview.last_run.processed_items}
            failed={overview.last_run.failed_items}
          />
        ) : null}
      </SectionCard>

      <SectionCard
        title={{ text: t('seo.runs.title') }}
        description={
          history_total > history.length
            ? t('seo.runs.truncated', { shown: history.length, total: history_total })
            : t('seo.runs.description')
        }
      >
        {history.length === 0 ? (
          <EmptyState
            icon={DatabaseIcon}
            title={t('seo.runs.empty.title')}
            description={t('seo.runs.empty.description')}
            className="border-0"
          />
        ) : (
          <ul className="divide-border divide-y">
            {history.map((run) => (
              <RunRow key={run.id} run={run} />
            ))}
          </ul>
        )}
      </SectionCard>

      <FormDialog
        param="import"
        title={destructive ? t('seo.import.again') : t('seo.import.action')}
        description={
          destructive ? t('seo.import.destructiveWarning') : t('seo.import.description')
        }
        submitLabel={destructive ? t('seo.import.confirmAgain') : t('seo.import.confirm')}
        pendingLabel={t('seo.import.pending')}
        pending={pending}
        onSubmit={submit}
      >
        <Select value={selected} onValueChange={setSelected}>
          <SelectTrigger>
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {months.map((month) => (
              <SelectItem key={month} value={String(month)}>
                {t('seo.import.months', { count: month })}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
        <p className="text-muted-foreground text-sm">
          {imported ? t('seo.import.replaceHelp') : t('seo.import.firstHelp')}
        </p>
      </FormDialog>
    </AppLayout>
  )
}

function Pair({ label, value }: { label: string; value: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-1">
      <dt className="text-muted-foreground text-xs">{label}</dt>
      <dd className="font-medium tabular-nums">{value}</dd>
    </div>
  )
}
