'use client'

/**
 * Links tab — internal / external link tracking with AI-powered suggestions
 * (orphan recovery, under-linked coverage). Backed by `/seo/links/*` APIs.
 */
import { useCallback, useMemo, useState } from 'react'
import {
  Link2,
  Sparkles,
  AlertTriangle,
  CheckCircle2,
  Loader2,
  RefreshCw,
  ExternalLink,
  Bot,
} from 'lucide-react'
import { toast } from 'sonner'
import {
  fetchLinkGraphSnapshot,
  fetchLinkHealthIssues,
  fetchLinkSuggestions,
  runLinkAiIndex,
  type LinkGraphEntityRef,
  type LinkSuggestion,
} from '../../lib/seo-service.js'
import { editPathForDoc } from '../../lib/collection-routes.js'
import {
  SectionCard,
  SeoLoading,
  SeoErrorState,
  SeoEmptyState,
  btnPrimary,
  btnSecondary,
  gradeMeta,
} from '../../components/seo/primitives.js'
import { useSeoResource } from './useSeoResource.js'

function scoreFromCoverage(coverage: number, orphanCount: number, broken: number): number {
  let score = coverage
  score -= Math.min(30, orphanCount * 0.5)
  score -= Math.min(20, broken * 2)
  return Math.max(0, Math.min(100, Math.round(score)))
}

function ActionCard({
  icon: Icon,
  title,
  description,
  impact,
  actionLabel,
  onAction,
  busy,
  disabled,
}: {
  icon: typeof Link2
  title: string
  description: string
  impact: 'High' | 'Medium' | 'Low'
  actionLabel: string
  onAction: () => void
  busy?: boolean
  disabled?: boolean
}) {
  const impactTone = impact === 'High' ? 'text-destructive' : 'text-warning'
  return (
    <div className="border-border bg-card flex flex-col gap-4 rounded-xl border p-5 shadow-sm sm:flex-row sm:items-center sm:justify-between">
      <div className="flex min-w-0 gap-4">
        <div className="bg-primary/10 text-primary flex h-11 w-11 shrink-0 items-center justify-center rounded-lg">
          <Icon className="h-5 w-5" aria-hidden />
        </div>
        <div className="min-w-0">
          <h3 className="text-foreground text-sm font-medium">{title}</h3>
          <p className="text-muted-foreground mt-1 text-sm">{description}</p>
          <div className="mt-2 flex flex-wrap items-center gap-2">
            <span className={`text-xs font-medium ${impactTone}`}>Impact: {impact}</span>
          </div>
        </div>
      </div>
      <button type="button" className={btnPrimary} onClick={onAction} disabled={disabled || busy}>
        {busy ? <Loader2 className="h-4 w-4 animate-spin" aria-hidden /> : null}
        {actionLabel}
      </button>
    </div>
  )
}

function SuggestionList({
  suggestions,
  loading,
}: {
  suggestions: LinkSuggestion[]
  loading: boolean
}) {
  if (loading) {
    return (
      <p className="text-muted-foreground flex items-center gap-2 text-sm">
        <Loader2 className="h-4 w-4 animate-spin" aria-hidden />
        Finding AI link opportunities…
      </p>
    )
  }
  if (suggestions.length === 0) {
    return (
      <p className="text-muted-foreground text-sm">
        No suggestions yet. Run AI indexing first, or add more published content.
      </p>
    )
  }
  return (
    <ul className="divide-border divide-y rounded-lg border">
      {suggestions.map((s) => (
        <li key={`${s.sourceEntityId}-${s.anchorText}`} className="px-4 py-3">
          <p className="text-foreground text-sm font-medium">{s.sourceTitle}</p>
          <p className="text-muted-foreground mt-0.5 text-xs">
            Link &ldquo;{s.anchorText}&rdquo; → {s.sourceUrl || 'target page'}{' '}
            <span className="text-muted-foreground/80 tabular-nums">
              ({Math.round(s.confidence * 100)}% match)
            </span>
          </p>
          {s.excerpt && (
            <p className="text-muted-foreground mt-1 line-clamp-2 text-xs">{s.excerpt}</p>
          )}
        </li>
      ))}
    </ul>
  )
}

export function LinksTab({ onNavigate }: { onNavigate?: (path: string) => void }) {
  const { data, loading, error, refetch } = useSeoResource(fetchLinkGraphSnapshot, [])
  const [indexing, setIndexing] = useState(false)
  const [healthLoading, setHealthLoading] = useState(false)
  const [healthIssues, setHealthIssues] = useState<
    Awaited<ReturnType<typeof fetchLinkHealthIssues>>['data'] | null
  >(null)
  const [selectedOrphan, setSelectedOrphan] = useState<LinkGraphEntityRef | null>(null)
  const [suggestions, setSuggestions] = useState<LinkSuggestion[]>([])
  const [suggestLoading, setSuggestLoading] = useState(false)

  const totalLinks = (data?.internalLinks ?? 0) + (data?.externalLinks ?? 0)
  const internalPct = totalLinks > 0 ? Math.round((data!.internalLinks / totalLinks) * 100) : 0
  const externalPct = totalLinks > 0 ? 100 - internalPct : 0
  const healthScore = useMemo(
    () =>
      data
        ? scoreFromCoverage(data.linkCoveragePercent, data.orphanCount, data.brokenLinkCount)
        : null,
    [data],
  )
  const healthGrade =
    healthScore !== null
      ? gradeMeta(
          healthScore >= 80
            ? 'good'
            : healthScore >= 60
              ? 'fair'
              : healthScore >= 40
                ? 'poor'
                : 'critical',
        )
      : null

  const handleAiIndex = useCallback(async () => {
    setIndexing(true)
    const res = await runLinkAiIndex()
    setIndexing(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success(res.data?.message ?? 'Link index updated.')
    refetch()
  }, [refetch])

  const handleLinkHealthScan = useCallback(async () => {
    setHealthLoading(true)
    const res = await fetchLinkHealthIssues()
    setHealthLoading(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    setHealthIssues(res.data ?? null)
    toast.success(`Checked ${res.data?.checked ?? 0} links.`)
  }, [])

  const loadSuggestions = useCallback(async (orphan: LinkGraphEntityRef) => {
    setSelectedOrphan(orphan)
    setSuggestLoading(true)
    setSuggestions([])
    const res = await fetchLinkSuggestions({
      targetEntityId: orphan.id,
      targetEntityType: orphan.entityType,
    })
    setSuggestLoading(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    setSuggestions(res.data?.suggestions ?? [])
  }, [])

  const openEditor = (ref: LinkGraphEntityRef) => {
    const path = editPathForDoc(
      { type: ref.entityType === 'post' ? 'post' : 'page' },
      ref.collection,
      ref.id,
    )
    onNavigate?.(path)
  }

  if (loading) return <SeoLoading label="Analyzing link graph…" />
  if (error) return <SeoErrorState message={error} onRetry={refetch} />
  if (!data)
    return <SeoEmptyState title="No link data" description="Publish content to track links." />

  return (
    <div className="space-y-6">
      <div>
        <h2 className="text-foreground text-lg font-medium">Internal linking snapshot</h2>
        <p className="text-muted-foreground mt-1 text-sm">
          Track internal and external links across published pages and posts. Use AI to recover
          orphaned content and improve link coverage.
        </p>
      </div>

      {/* Distribution */}
      <SectionCard title="Link distribution" description="Published content only">
        <div className="space-y-3">
          <div className="flex h-3 overflow-hidden rounded-full">
            <div
              className="bg-primary motion-safe:transition-all"
              style={{ width: `${internalPct}%` }}
              title={`Internal ${internalPct}%`}
            />
            <div
              className="bg-success motion-safe:transition-all"
              style={{ width: `${externalPct}%` }}
              title={`External ${externalPct}%`}
            />
          </div>
          <div className="flex flex-wrap gap-6 text-sm">
            <span className="text-foreground">
              <span className="bg-primary mr-2 inline-block h-2 w-2 rounded-full" aria-hidden />
              Internal: {data.internalLinks.toLocaleString()} ({internalPct}%)
            </span>
            <span className="text-foreground">
              <span className="bg-success mr-2 inline-block h-2 w-2 rounded-full" aria-hidden />
              External: {data.externalLinks.toLocaleString()} ({externalPct}%)
            </span>
          </div>
          {externalPct > 0 && externalPct < 15 && (
            <p className="border-info/30 bg-info/10 text-info flex items-start gap-2 rounded-lg border p-4 text-sm">
              <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0" aria-hidden />
              External ratio is low. Consider citing relevant high-authority sources where
              appropriate.
            </p>
          )}
        </div>
      </SectionCard>

      {/* Score cards */}
      <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
        <SectionCard title="Site link health">
          {healthScore !== null && healthGrade && (
            <div>
              <span className={`text-3xl font-medium tabular-nums ${healthGrade.text}`}>
                {healthScore}
              </span>
              <p className="text-muted-foreground mt-1 text-xs">{healthGrade.label}</p>
            </div>
          )}
        </SectionCard>
        <SectionCard title="Link coverage">
          <span className="text-foreground text-3xl font-medium tabular-nums">
            {data.linkCoveragePercent}%
          </span>
          <p className="text-muted-foreground mt-1 text-xs">Pages with inbound internal links</p>
        </SectionCard>
        <SectionCard title="Orphaned pages">
          <span
            className={`text-3xl font-medium tabular-nums ${data.orphanCount > 0 ? 'text-destructive' : 'text-success'}`}
          >
            {data.orphanCount}
          </span>
          <p className="text-muted-foreground mt-1 text-xs">No inbound internal links</p>
        </SectionCard>
        <SectionCard title="Broken links">
          <span
            className={`text-3xl font-medium tabular-nums ${data.brokenLinkCount > 0 ? 'text-warning' : 'text-success'}`}
          >
            {data.brokenLinkCount}
          </span>
          <p className="text-muted-foreground mt-1 text-xs">From latest SEO audit</p>
        </SectionCard>
      </div>

      {/* AI actions */}
      <div className="space-y-4">
        <ActionCard
          icon={Bot}
          title="Perform basic AI scanning"
          description="Index published content so AI can suggest which pages should link to each other. Re-run after publishing a significant batch of content."
          impact="High"
          actionLabel={indexing ? 'Indexing…' : 'Run AI index'}
          onAction={handleAiIndex}
          busy={indexing}
        />
        {data.aiIndexLastRunAt && (
          <p className="text-muted-foreground -mt-2 text-xs">
            Last indexed {new Date(data.aiIndexLastRunAt).toLocaleString()}
            {data.aiIndexReady ? ' · AI ready' : ''}
          </p>
        )}
        <ActionCard
          icon={Link2}
          title="Orphaned posts & pages"
          description="These published URLs have no inbound internal links. Add links from related content so visitors and search engines can find them."
          impact="High"
          actionLabel="Review list below"
          onAction={() => {
            document.getElementById('orphan-list')?.scrollIntoView({ behavior: 'smooth' })
          }}
        />
        <ActionCard
          icon={Sparkles}
          title="Link coverage"
          description="Pages with fewer than two outbound internal links. Strengthen topical clusters by linking to related content."
          impact="High"
          actionLabel="Review under-linked"
          onAction={() => {
            document.getElementById('under-linked-list')?.scrollIntoView({ behavior: 'smooth' })
          }}
        />
      </div>

      {/* Orphan list */}
      <SectionCard
        title="Orphaned content"
        description={`${data.orphanCount} published item${data.orphanCount === 1 ? '' : 's'} with no inbound internal links`}
      >
        <div id="orphan-list" className="space-y-4">
          {data.orphaned.length === 0 ? (
            <p className="text-muted-foreground flex items-center gap-2 text-sm">
              <CheckCircle2 className="text-success h-4 w-4" aria-hidden />
              No orphaned pages detected.
            </p>
          ) : (
            <ul className="divide-border divide-y rounded-lg border">
              {data.orphaned.map((row) => (
                <li
                  key={row.id}
                  className="flex flex-wrap items-center justify-between gap-3 px-4 py-3"
                >
                  <div className="min-w-0">
                    <p className="text-foreground truncate text-sm font-medium">{row.title}</p>
                    <p className="text-muted-foreground truncate text-xs">{row.url || row.path}</p>
                  </div>
                  <div className="flex shrink-0 flex-wrap gap-2">
                    <button type="button" className={btnSecondary} onClick={() => openEditor(row)}>
                      Edit
                    </button>
                    <button
                      type="button"
                      className={btnPrimary}
                      onClick={() => void loadSuggestions(row)}
                    >
                      <Sparkles className="h-3.5 w-3.5" aria-hidden />
                      AI suggest
                    </button>
                  </div>
                </li>
              ))}
            </ul>
          )}
          {selectedOrphan && (
            <div className="border-border bg-muted/30 rounded-lg border p-4">
              <p className="text-foreground mb-2 text-sm font-medium">
                AI suggestions for &ldquo;{selectedOrphan.title}&rdquo;
              </p>
              <SuggestionList suggestions={suggestions} loading={suggestLoading} />
            </div>
          )}
        </div>
      </SectionCard>

      {/* Under-linked */}
      <SectionCard title="Under-linked pages" description="Fewer than 2 outbound internal links">
        <div id="under-linked-list">
          {data.underLinked.length === 0 ? (
            <p className="text-muted-foreground text-sm">
              All crawled pages have adequate outbound links.
            </p>
          ) : (
            <ul className="divide-border max-h-80 divide-y overflow-y-auto rounded-lg border">
              {data.underLinked.map((row) => (
                <li
                  key={row.id}
                  className="flex items-center justify-between gap-3 px-4 py-3 text-sm"
                >
                  <span className="text-foreground min-w-0 truncate font-medium">{row.title}</span>
                  <span className="text-muted-foreground shrink-0 tabular-nums">
                    {row.outboundInternal} outbound
                  </span>
                </li>
              ))}
            </ul>
          )}
        </div>
      </SectionCard>

      {/* Live link health */}
      <SectionCard
        title="Live link health scan"
        description="Probe outbound URLs (rate-limited). Complements audit broken-link issues."
        action={
          <button
            type="button"
            className={btnSecondary}
            onClick={() => void handleLinkHealthScan()}
            disabled={healthLoading}
          >
            {healthLoading ? (
              <Loader2 className="h-4 w-4 animate-spin" aria-hidden />
            ) : (
              <RefreshCw className="h-4 w-4" aria-hidden />
            )}
            Scan now
          </button>
        }
      >
        {healthIssues && healthIssues.issues.length > 0 ? (
          <ul className="divide-border max-h-64 divide-y overflow-y-auto rounded-lg border">
            {healthIssues.issues.map((issue) => (
              <li key={issue.id} className="px-4 py-3 text-sm">
                <p className="text-foreground font-medium">{issue.page}</p>
                <p className="text-muted-foreground mt-0.5 flex items-center gap-1 truncate text-xs">
                  <ExternalLink className="h-3 w-3 shrink-0" aria-hidden />
                  {issue.url}
                  <span className="text-destructive ml-1">HTTP {issue.status || 'error'}</span>
                  <span className="text-muted-foreground">· {issue.type}</span>
                </p>
              </li>
            ))}
          </ul>
        ) : (
          <p className="text-muted-foreground text-sm">
            {healthIssues
              ? 'No failing links in the last scan.'
              : 'Run a scan to check live URL responses across published content.'}
          </p>
        )}
      </SectionCard>

      <p className="text-muted-foreground text-xs">
        Crawled {data.postsCrawled.toLocaleString()} published documents · Updated{' '}
        {new Date(data.scannedAt).toLocaleString()}
      </p>
    </div>
  )
}
