'use client'

import { useRef, useState } from 'react'
import {
  Plus,
  Pencil,
  Trash2,
  Upload,
  Download,
  Sparkles,
  ArrowRight,
  GitBranch,
  Check,
  X,
  Link2,
} from 'lucide-react'
import { toast } from 'sonner'
import {
  fetchRedirectOverview,
  fetchRedirectRules,
  fetchRedirectChains,
  fetchRedirectSuggestions,
  deleteRedirectRule,
  flattenRedirectChain,
  generate404RecoverySuggestions,
  acceptRedirectSuggestion,
  dismissRedirectSuggestion,
  exportRedirectsCsv,
  importRedirectsCsv,
  type RedirectRule,
} from '../../lib/seo-service.js'
import {
  SectionCard,
  SeoLoading,
  SeoEmptyState,
  SeoErrorState,
  SeoStatusBadge,
  btnPrimary,
  btnSecondary,
  btnGhostIcon,
} from '../../components/seo/primitives.js'
import { RedirectEditorDrawer } from '../../components/seo/RedirectEditorDrawer.js'
import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js'
import { useSeoResource } from './useSeoResource.js'

function OverviewCards({ onRefetchKey }: { onRefetchKey: number }) {
  const { data, loading, error, refetch } = useSeoResource(fetchRedirectOverview, [onRefetchKey])
  if (loading) return <SeoLoading label="Loading redirect overview…" />
  if (error) return <SeoErrorState message={error} onRetry={refetch} />
  if (!data) return null
  const cards = [
    { label: 'Active redirects', value: data.activeRedirects },
    { label: 'Stale redirects', value: data.staleRedirects },
    { label: '404s tracked', value: data.notFoundCount },
    { label: 'Chains & loops', value: data.chainsAndLoops },
  ]
  return (
    <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
      {cards.map((c) => (
        <div key={c.label} className="border-border bg-card rounded-lg border p-4">
          <p className="text-muted-foreground text-sm">{c.label}</p>
          <p className="text-foreground mt-1 text-2xl font-medium tabular-nums">{c.value}</p>
        </div>
      ))}
    </div>
  )
}

function Ai404RecoveryCard({ onApplied }: { onApplied: () => void }) {
  const { data, loading, error, refetch } = useSeoResource(fetchRedirectSuggestions, [])
  const [generating, setGenerating] = useState(false)

  async function handleGenerate() {
    setGenerating(true)
    const res = await generate404RecoverySuggestions()
    setGenerating(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Generated 404 recovery suggestions.')
    refetch()
  }

  async function handleAccept(id: string) {
    const res = await acceptRedirectSuggestion(id)
    if (res.error) return toast.error(res.error)
    toast.success('Redirect created from suggestion.')
    refetch()
    onApplied()
  }

  async function handleDismiss(id: string) {
    const res = await dismissRedirectSuggestion(id)
    if (res.error) return toast.error(res.error)
    refetch()
  }

  return (
    <SectionCard
      title="AI 404 Recovery"
      description="Suggested redirects for paths returning 404s"
      action={
        <button className={btnSecondary} onClick={handleGenerate} disabled={generating}>
          <Sparkles className={`h-4 w-4 ${generating ? 'animate-pulse' : ''}`} aria-hidden />
          {generating ? 'Analyzing…' : 'Generate suggestions'}
        </button>
      }
    >
      {loading ? (
        <SeoLoading />
      ) : error ? (
        <SeoErrorState message={error} onRetry={refetch} />
      ) : (data ?? []).length === 0 ? (
        <SeoEmptyState
          icon={<Sparkles size={24} />}
          title="No suggestions"
          description="Generate suggestions to recover traffic from broken URLs."
        />
      ) : (
        <ul className="divide-border divide-y">
          {data!.map((s) => (
            <li key={s.id} className="flex items-center justify-between gap-3 py-3 first:pt-0">
              <div className="min-w-0">
                <p className="text-foreground flex items-center gap-2 text-sm">
                  <span className="truncate font-medium">{s.fromPath}</span>
                  <ArrowRight className="text-muted-foreground h-3.5 w-3.5 shrink-0" aria-hidden />
                  <span className="text-muted-foreground truncate">{s.toPath}</span>
                </p>
                {s.reason && <p className="text-muted-foreground mt-0.5 text-sm">{s.reason}</p>}
              </div>
              <div className="flex shrink-0 items-center gap-2">
                <SeoStatusBadge
                  label={`${Math.round(s.confidence * 100)}%`}
                  tone={s.confidence >= 0.7 ? 'good' : s.confidence >= 0.4 ? 'fair' : 'poor'}
                />
                <button
                  onClick={() => handleAccept(s.id)}
                  className="text-success hover:bg-accent focus-visible:ring-ring rounded-md p-1.5 focus-visible:ring-2 focus-visible:outline-none"
                  aria-label={`Accept redirect from ${s.fromPath}`}
                >
                  <Check className="h-4 w-4" aria-hidden />
                </button>
                <button
                  onClick={() => handleDismiss(s.id)}
                  className="text-muted-foreground hover:bg-accent focus-visible:ring-ring rounded-md p-1.5 focus-visible:ring-2 focus-visible:outline-none"
                  aria-label={`Dismiss suggestion for ${s.fromPath}`}
                >
                  <X className="h-4 w-4" aria-hidden />
                </button>
              </div>
            </li>
          ))}
        </ul>
      )}
    </SectionCard>
  )
}

function ChainMapCard({ onFlattened }: { onFlattened: () => void }) {
  const { data, loading, error, refetch } = useSeoResource(fetchRedirectChains, [])

  async function handleFlatten(id: string) {
    const res = await flattenRedirectChain(id)
    if (res.error) return toast.error(res.error)
    toast.success('Chain flattened.')
    refetch()
    onFlattened()
  }

  if (loading) return null
  if (error) return null
  if (!data || data.length === 0) return null

  return (
    <SectionCard
      title="Redirect Chains & Loops"
      description="Multi-hop redirects slow crawlers and lose link equity"
    >
      <ul className="space-y-3">
        {data.map((chain) => (
          <li
            key={chain.id}
            className="border-border flex items-center justify-between gap-3 rounded-md border p-3"
          >
            <div className="min-w-0">
              <div className="mb-1 flex items-center gap-2">
                <GitBranch className="text-muted-foreground h-4 w-4" aria-hidden />
                <SeoStatusBadge
                  label={chain.kind === 'loop' ? 'Loop' : 'Chain'}
                  tone={chain.kind === 'loop' ? 'critical' : 'fair'}
                />
              </div>
              <p className="text-foreground flex flex-wrap items-center gap-1 text-sm">
                {chain.hops.map((hop, i) => (
                  <span key={i} className="flex items-center gap-1">
                    <span className="truncate">{hop}</span>
                    {i < chain.hops.length - 1 && (
                      <ArrowRight className="text-muted-foreground h-3 w-3" aria-hidden />
                    )}
                  </span>
                ))}
              </p>
            </div>
            {chain.kind === 'chain' && (
              <button className={btnSecondary} onClick={() => handleFlatten(chain.id)}>
                Flatten
              </button>
            )}
          </li>
        ))}
      </ul>
    </SectionCard>
  )
}

export function RedirectsTab() {
  const [refetchKey, setRefetchKey] = useState(0)
  const { data, loading, error, refetch } = useSeoResource(fetchRedirectRules, [refetchKey])
  const [editor, setEditor] = useState<{ rule: RedirectRule | null } | null>(null)
  const [confirmDelete, setConfirmDelete] = useState<RedirectRule | null>(null)
  const fileRef = useRef<HTMLInputElement>(null)

  const bump = () => setRefetchKey((k) => k + 1)
  const refetchAll = () => {
    refetch()
    bump()
  }

  async function handleDelete(rule: RedirectRule) {
    const res = await deleteRedirectRule(rule.id)
    if (res.error) return toast.error(res.error)
    toast.success('Redirect deleted.')
    refetchAll()
  }

  async function handleExport() {
    const res = await exportRedirectsCsv()
    if (res.error || !res.csv) return toast.error(res.error ?? 'Export failed.')
    const blob = new Blob([res.csv], { type: 'text/csv' })
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = 'redirects.csv'
    // Firefox requires the anchor to be in the document for programmatic clicks.
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    // Defer revocation so the browser has a chance to start the download —
    // revoking synchronously can cancel it before it begins.
    setTimeout(() => URL.revokeObjectURL(url), 0)
  }

  async function handleImportFile(file: File) {
    const csv = await file.text()
    const res = await importRedirectsCsv(csv)
    if (res.error) return toast.error(res.error)
    if (res.errors && res.errors.length > 0) {
      toast.error(`Imported ${res.imported ?? 0}, ${res.errors.length} row(s) skipped.`)
    } else {
      toast.success(`Imported ${res.imported ?? 0} redirect(s).`)
    }
    refetchAll()
  }

  return (
    <div className="space-y-4">
      <OverviewCards onRefetchKey={refetchKey} />

      <div className="grid grid-cols-1 gap-4 xl:grid-cols-2">
        <Ai404RecoveryCard onApplied={refetchAll} />
        <ChainMapCard onFlattened={refetchAll} />
      </div>

      <SectionCard
        title="Redirect Rules"
        action={
          <div className="flex flex-wrap gap-2">
            <input
              ref={fileRef}
              type="file"
              accept=".csv,text/csv"
              className="sr-only"
              aria-hidden
              tabIndex={-1}
              onChange={(e) => {
                const f = e.target.files?.[0]
                if (f) handleImportFile(f)
                e.target.value = ''
              }}
            />
            <button className={btnSecondary} onClick={() => fileRef.current?.click()}>
              <Upload className="h-4 w-4" aria-hidden /> Import
            </button>
            <button className={btnSecondary} onClick={handleExport}>
              <Download className="h-4 w-4" aria-hidden /> Export
            </button>
            <button className={btnPrimary} onClick={() => setEditor({ rule: null })}>
              <Plus className="h-4 w-4" aria-hidden /> New redirect
            </button>
          </div>
        }
      >
        {loading ? (
          <SeoLoading label="Loading redirects…" />
        ) : error ? (
          <SeoErrorState message={error} onRetry={refetch} />
        ) : (data ?? []).length === 0 ? (
          <SeoEmptyState
            icon={<Link2 size={24} />}
            title="No redirects yet"
            description="Create a redirect or import a CSV to get started."
            action={
              <button className={btnPrimary} onClick={() => setEditor({ rule: null })}>
                <Plus className="h-4 w-4" aria-hidden /> New redirect
              </button>
            }
          />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm" aria-label="Redirect rules">
              <thead>
                <tr className="text-muted-foreground border-border border-b text-left">
                  <th className="py-2 pr-4 font-medium">Source</th>
                  <th className="py-2 pr-4 font-medium">Destination</th>
                  <th className="py-2 pr-4 font-medium">Type</th>
                  <th className="py-2 pr-4 text-right font-medium">Hits</th>
                  <th className="py-2 pr-4 font-medium">Status</th>
                  <th className="py-2 text-right font-medium">
                    <span className="sr-only">Actions</span>
                  </th>
                </tr>
              </thead>
              <tbody className="divide-border divide-y">
                {data!.map((r) => (
                  <tr key={r.id} className="hover:bg-accent/40">
                    <td className="text-foreground py-2.5 pr-4 font-mono">{r.fromPath}</td>
                    <td className="text-muted-foreground py-2.5 pr-4 font-mono">
                      {r.type === 410 ? <span className="italic">— (gone)</span> : r.toPath}
                    </td>
                    <td className="text-foreground py-2.5 pr-4 tabular-nums">{r.type}</td>
                    <td className="text-foreground py-2.5 pr-4 text-right tabular-nums">
                      {r.hits}
                    </td>
                    <td className="py-2.5 pr-4">
                      <span className="flex flex-wrap gap-1.5">
                        <SeoStatusBadge
                          label={r.enabled ? 'Enabled' : 'Disabled'}
                          tone={r.enabled ? 'good' : 'neutral'}
                        />
                        {r.stale && <SeoStatusBadge label="Stale" tone="fair" />}
                      </span>
                    </td>
                    <td className="py-2.5 text-right">
                      <div className="flex justify-end gap-1">
                        <button
                          className={btnGhostIcon}
                          onClick={() => setEditor({ rule: r })}
                          aria-label={`Edit redirect ${r.fromPath}`}
                        >
                          <Pencil className="h-4 w-4" aria-hidden />
                        </button>
                        <button
                          className={btnGhostIcon}
                          onClick={() => setConfirmDelete(r)}
                          aria-label={`Delete redirect ${r.fromPath}`}
                        >
                          <Trash2 className="h-4 w-4" aria-hidden />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </SectionCard>

      <RedirectEditorDrawer
        open={editor !== null}
        onOpenChange={(o) => !o && setEditor(null)}
        rule={editor?.rule ?? null}
        onSaved={refetchAll}
      />

      <ConfirmDialog
        open={confirmDelete !== null}
        onClose={() => setConfirmDelete(null)}
        onConfirm={() => confirmDelete && handleDelete(confirmDelete)}
        title="Delete redirect"
        description={`Delete the redirect from "${confirmDelete?.fromPath}"? This cannot be undone.`}
        confirmLabel="Delete"
        destructive
      />
    </div>
  )
}
