'use client'

import { useEffect, useState } from 'react'
import { Check, ChevronDown, Loader2, Sparkles, Wand2 } from 'lucide-react'
import { toast } from 'sonner'
import {
  applySeoIssueFix,
  fetchSeoIssueFixSuggestion,
  fetchSeoContentBrief,
  fetchSeoContentResearch,
  generateSeoContentBrief,
  ignoreSeoIssue,
  isInlineSeoFixIssue,
  researchAndBriefSeoIssue,
  supportsSeoContentBrief,
  supportsSeoContentResearch,
  type SeoContentBrief,
  type SeoContentResearch,
  type SeoFixFieldChange,
  type SeoIssue,
  type SeoIssueFixSuggestion,
} from '../../lib/seo-service.js'
import { hasPlanFeature, type PlanInfo } from '../../lib/plan.js'
import { PlanUpgradeCallout } from '../PlanUpgradeCallout.js'
import { SeoErrorState, btnPrimary, btnSecondary } from './primitives.js'

function formatValue(value: string | boolean | null): string {
  if (value === null || value === '') return '—'
  if (typeof value === 'boolean') return value ? 'Yes' : 'No'
  if (value.length > 280) return `${value.slice(0, 277)}…`
  return value
}

function ChangePreview({ changes }: { changes: SeoFixFieldChange[] }) {
  if (changes.length === 0) return null
  return (
    <div className="border-border overflow-x-auto rounded-md border">
      <table className="w-full min-w-[480px] text-sm" aria-label="Proposed SEO changes">
        <thead>
          <tr className="border-border bg-muted/40 text-muted-foreground border-b text-left">
            <th scope="col" className="py-2 pr-3 pl-3 font-medium">
              Field
            </th>
            <th scope="col" className="py-2 pr-3 font-medium">
              Current
            </th>
            <th scope="col" className="py-2 pr-3 font-medium">
              Proposed
            </th>
          </tr>
        </thead>
        <tbody className="divide-border divide-y">
          {changes.map((c) => (
            <tr key={c.field}>
              <td className="text-foreground py-2 pr-3 pl-3 font-medium">{c.label}</td>
              <td className="text-muted-foreground max-w-48 py-2 pr-3 wrap-break-word">
                {formatValue(c.before)}
              </td>
              <td className="text-foreground max-w-48 py-2 pr-3 wrap-break-word">
                {formatValue(c.after)}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

function ContentResearchCard({ research }: { research: SeoContentResearch }) {
  return (
    <div className="border-border bg-card space-y-3 rounded-md border p-4">
      <div className="flex items-center gap-2">
        <span className="bg-accent text-foreground inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium">
          <Sparkles className="h-3 w-3" aria-hidden />
          Topic research
        </span>
      </div>
      <p className="text-foreground text-sm">{research.summary}</p>
      <ul className="text-foreground space-y-1.5 text-sm">
        {research.focusKeyword ? (
          <li>
            <span className="text-muted-foreground">Focus keyword: </span>
            {research.focusKeyword}
          </li>
        ) : null}
        {research.suggestedWordCount ? (
          <li>
            <span className="text-muted-foreground">Suggested length: </span>~
            {research.suggestedWordCount} words
          </li>
        ) : null}
      </ul>
      {research.outline.length > 0 ? (
        <div>
          <p className="text-muted-foreground mb-1.5 text-xs font-medium tracking-wide uppercase">
            Suggested outline
          </p>
          <ul className="text-foreground list-disc space-y-1 pl-5 text-sm">
            {research.outline.map((item) => (
              <li key={item}>{item}</li>
            ))}
          </ul>
        </div>
      ) : null}
      {research.faqCandidates.length > 0 ? (
        <div>
          <p className="text-muted-foreground mb-1.5 text-xs font-medium tracking-wide uppercase">
            FAQ candidates
          </p>
          <ul className="text-foreground list-disc space-y-1 pl-5 text-sm">
            {research.faqCandidates.map((q) => (
              <li key={q}>{q}</li>
            ))}
          </ul>
        </div>
      ) : null}
    </div>
  )
}

function ContentBriefCard({ brief }: { brief: SeoContentBrief }) {
  return (
    <div className="border-border bg-card space-y-3 rounded-md border p-4">
      <div className="flex items-center gap-2">
        <span className="bg-primary/10 text-primary inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium">
          <Sparkles className="h-3 w-3" aria-hidden />
          AI content brief
        </span>
      </div>
      <p className="text-foreground text-sm">{brief.summary}</p>
      <ul className="text-foreground space-y-1.5 text-sm">
        {brief.suggestedH1 ? (
          <li>
            <span className="text-muted-foreground">Suggested H1: </span>
            {brief.suggestedH1}
          </li>
        ) : null}
        {brief.targetWordCount ? (
          <li>
            <span className="text-muted-foreground">Target length: </span>~{brief.targetWordCount}{' '}
            words
          </li>
        ) : null}
        {brief.keyTakeawayDraft ? (
          <li>
            <span className="text-muted-foreground">GEO takeaway: </span>
            {brief.keyTakeawayDraft}
          </li>
        ) : null}
        {brief.geoNote ? (
          <li>
            <span className="text-muted-foreground">GEO note: </span>
            {brief.geoNote}
          </li>
        ) : null}
      </ul>
      {brief.topics.length > 0 ? (
        <div>
          <p className="text-muted-foreground mb-1.5 text-xs font-medium tracking-wide uppercase">
            Topics to cover
          </p>
          <ul className="text-foreground list-disc space-y-1 pl-5 text-sm">
            {brief.topics.map((topic) => (
              <li key={topic}>{topic}</li>
            ))}
          </ul>
        </div>
      ) : null}
      {brief.sections.map((section) => (
        <div key={section.heading}>
          <p className="text-foreground text-sm font-medium">{section.heading}</p>
          {section.bullets.length > 0 ? (
            <ul className="text-muted-foreground mt-1 list-disc space-y-1 pl-5 text-sm">
              {section.bullets.map((bullet) => (
                <li key={bullet}>{bullet}</li>
              ))}
            </ul>
          ) : null}
        </div>
      ))}
    </div>
  )
}

function manualPath(issue: SeoIssue): string | null {
  const ent = issue.entityType
  const id = issue.entityId
  switch (issue.fixActionType) {
    case 'edit-metadata':
    case 'edit-canonical':
    case 'edit-og':
    case 'edit-og-image':
    case 'edit-schema':
      if (ent && id) {
        return `/seo?tab=content&entityType=${ent}&entityId=${encodeURIComponent(id)}`
      }
      return null
    case 'edit-content':
      if (ent === 'page' && id) return `/pages/${id}`
      if (ent && id) {
        return `/seo?tab=content&entityType=${ent}&entityId=${encodeURIComponent(id)}`
      }
      return null
    case 'fix-broken-link':
    case 'fix-link':
    case 'create-redirect':
      return '/seo?tab=redirects'
    case 'optimize-media':
      return '/media'
    case 'improve-speed':
      return '/seo?tab=technical'
    default:
      if (ent === 'page' && id) return `/pages/${id}`
      return null
  }
}

export function SeoIssueFixPanel({
  issue,
  expanded,
  onChanged,
  onNavigate,
  onOpenDetails,
  planInfo,
}: {
  issue: SeoIssue
  expanded: boolean
  onChanged?: () => void
  onNavigate?: (path: string) => void
  onOpenDetails?: () => void
  planInfo?: PlanInfo | null
}) {
  const inlineFix = isInlineSeoFixIssue(issue.type)
  const contentBriefEligible = supportsSeoContentBrief(issue.type)
  const researchEligible = supportsSeoContentResearch(issue.type)
  const inlineApplyEnabled = hasPlanFeature(planInfo, 'seo.inlineApply')
  const contentBriefEnabled = hasPlanFeature(planInfo, 'seo.contentBrief')
  const contentResearchEnabled = hasPlanFeature(planInfo, 'seo.contentResearch')

  const [suggestion, setSuggestion] = useState<SeoIssueFixSuggestion | null>(null)
  const [contentBrief, setContentBrief] = useState<SeoContentBrief | null>(null)
  const [contentResearch, setContentResearch] = useState<SeoContentResearch | null>(null)
  const [competitorUrls, setCompetitorUrls] = useState(['', '', ''])
  const [briefStale, setBriefStale] = useState(false)
  const [researchStale, setResearchStale] = useState(false)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [generatingBrief, setGeneratingBrief] = useState(false)
  const [researching, setResearching] = useState(false)

  useEffect(() => {
    if (!expanded) {
      setSuggestion(null)
      setContentBrief(null)
      setContentResearch(null)
      setCompetitorUrls(['', '', ''])
      setBriefStale(false)
      setResearchStale(false)
      setError(null)
      return
    }

    let alive = true
    setLoading(true)
    setError(null)

    async function load() {
      if (inlineFix) {
        const res = await fetchSeoIssueFixSuggestion(issue.id)
        if (!alive) return
        if (res.error) setError(res.error)
        else setSuggestion(res.suggestion ?? null)
        return
      }

      if (contentBriefEligible) {
        const briefRes = await fetchSeoContentBrief(issue.id)
        if (!alive) return
        if (briefRes.error) setError(briefRes.error)
        else {
          setContentBrief(briefRes.brief ?? null)
          setBriefStale(briefRes.stale ?? false)
        }

        if (researchEligible) {
          const researchRes = await fetchSeoContentResearch(issue.id)
          if (!alive) return
          if (researchRes.error && !briefRes.error) setError(researchRes.error)
          else if (!researchRes.error) {
            setContentResearch(researchRes.research ?? null)
            setResearchStale(researchRes.stale ?? false)
          }
        }
      }
    }

    load()
      .catch((e) => alive && setError(e instanceof Error ? e.message : 'Failed to load'))
      .finally(() => alive && setLoading(false))

    return () => {
      alive = false
    }
  }, [expanded, issue.id, inlineFix, contentBriefEligible, researchEligible])

  function parsedCompetitorUrls(): string[] {
    return competitorUrls
      .map((u) => u.trim())
      .filter(Boolean)
      .slice(0, 3)
  }

  async function handleApprove() {
    if (!suggestion?.autoFixable) return
    setBusy(true)
    const res = await applySeoIssueFix(issue.id, suggestion.fingerprint)
    setBusy(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success(
      suggestion?.fixStrategy === 'fix-link'
        ? 'Link updated in content and issue resolved.'
        : 'Redirect created and issue resolved.',
    )
    onChanged?.()
  }

  async function handleResearchAndBrief() {
    setResearching(true)
    const res = await researchAndBriefSeoIssue(issue.id, parsedCompetitorUrls())
    setResearching(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    if (res.research) {
      setContentResearch(res.research)
      setResearchStale(false)
    }
    if (res.brief) {
      setContentBrief(res.brief)
      setBriefStale(false)
    }
    toast.success('Research and content brief generated — review before editing the page.')
  }
  async function handleGenerateBrief() {
    setGeneratingBrief(true)
    const res = await generateSeoContentBrief(issue.id)
    setGeneratingBrief(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    if (res.brief) {
      setContentBrief(res.brief)
      setBriefStale(false)
      toast.success('Content brief generated — review before editing the page.')
    }
  }

  async function handleIgnore() {
    setBusy(true)
    const res = await ignoreSeoIssue(issue.id)
    setBusy(false)
    if (res.error) return toast.error(res.error)
    toast.success('Issue ignored.')
    onChanged?.()
  }

  const manualRoute = manualPath(issue)

  if (!expanded) return null

  return (
    <tr>
      <td colSpan={5} className="bg-muted/30 px-4 py-4">
        <div className="space-y-4">
          {loading ? (
            <div
              className="text-muted-foreground flex items-center gap-2 text-sm"
              role="status"
              aria-live="polite"
            >
              <Loader2 className="h-4 w-4 motion-safe:animate-spin" aria-hidden />
              {inlineFix ? 'Loading suggested fix…' : 'Loading issue details…'}
            </div>
          ) : error ? (
            <SeoErrorState message={error} />
          ) : (
            <>
              {!inlineFix && (issue.description || issue.recommendation) ? (
                <div className="space-y-2">
                  {issue.description ? (
                    <p className="text-foreground text-sm">{issue.description}</p>
                  ) : null}
                  {issue.recommendation ? (
                    <p className="text-muted-foreground text-sm">
                      <span className="text-foreground font-medium">Recommended fix: </span>
                      {issue.recommendation}
                    </p>
                  ) : null}
                </div>
              ) : null}

              {inlineFix && suggestion ? (
                <>
                  <div className="flex flex-wrap items-center gap-2">
                    {suggestion.source === 'ai' && !suggestion.aiUnavailable ? (
                      <span className="bg-primary/10 text-primary inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium">
                        <Sparkles className="h-3 w-3" aria-hidden />
                        {suggestion.fixStrategy === 'fix-link'
                          ? 'Fix link in content'
                          : 'AI suggestion'}
                      </span>
                    ) : suggestion.source === 'deterministic' ? (
                      <span className="bg-muted text-muted-foreground rounded-full px-2.5 py-0.5 text-xs font-medium">
                        {suggestion.fixStrategy === 'fix-link'
                          ? 'Content link fix'
                          : 'Rule-based fix'}
                      </span>
                    ) : null}
                  </div>
                  <div className="flex items-start gap-2">
                    <Sparkles className="text-primary mt-0.5 h-4 w-4 shrink-0" aria-hidden />
                    <p className="text-foreground text-sm">{suggestion.justification}</p>
                  </div>
                  <ChangePreview changes={suggestion.changes} />
                </>
              ) : null}

              {contentBriefEligible ? (
                <>
                  {researchEligible ? (
                    <div className="space-y-2">
                      <p className="text-muted-foreground text-sm">
                        Optional competitor URLs (SSRF-safe fetch, max 3) to enrich topic research
                        for thin content.
                      </p>
                      {competitorUrls.map((value, index) => (
                        <label key={index} className="block">
                          <span className="text-muted-foreground sr-only">
                            Competitor URL {index + 1}
                          </span>
                          <input
                            type="url"
                            value={value}
                            onChange={(e) => {
                              const next = [...competitorUrls]
                              next[index] = e.target.value
                              setCompetitorUrls(next)
                            }}
                            placeholder={`Competitor URL ${index + 1} (optional)`}
                            className="border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none"
                          />
                        </label>
                      ))}
                    </div>
                  ) : null}
                  {researchStale && !contentResearch ? (
                    <p className="text-muted-foreground text-sm" role="status">
                      Previous topic research is outdated because the page changed.
                    </p>
                  ) : null}
                  {contentResearch ? <ContentResearchCard research={contentResearch} /> : null}
                  {briefStale && !contentBrief ? (
                    <p className="text-muted-foreground text-sm" role="status">
                      A previous content brief is outdated because the page changed. Generate a new
                      one.
                    </p>
                  ) : null}
                  {contentBrief ? <ContentBriefCard brief={contentBrief} /> : null}
                  {!contentBrief ? (
                    <p className="text-muted-foreground text-sm">
                      Generate an AI content brief with suggested headings, topics, and GEO guidance
                      for your dev team.
                    </p>
                  ) : null}
                </>
              ) : null}

              <div className="flex flex-wrap items-center gap-2">
                {inlineFix && suggestion?.autoFixable && inlineApplyEnabled ? (
                  <button
                    type="button"
                    className={btnPrimary}
                    onClick={handleApprove}
                    disabled={busy}
                  >
                    <Check className="h-4 w-4" aria-hidden />
                    {busy
                      ? 'Applying…'
                      : suggestion.fixStrategy === 'fix-link'
                        ? 'Fix link in content'
                        : 'Approve redirect'}
                  </button>
                ) : inlineFix && suggestion?.autoFixable && !inlineApplyEnabled ? (
                  <PlanUpgradeCallout feature="seo.inlineApply" upgradeUrl={planInfo?.upgradeUrl} />
                ) : inlineFix && suggestion?.aiUnavailable ? (
                  <p className="text-muted-foreground text-sm">
                    Configure an AI provider in Settings → AI to enable generated fixes for this
                    issue.
                  </p>
                ) : null}

                {contentBriefEligible ? (
                  <>
                    {!contentBriefEnabled || !contentResearchEnabled ? (
                      <PlanUpgradeCallout
                        feature={
                          !contentResearchEnabled ? 'seo.contentResearch' : 'seo.contentBrief'
                        }
                        upgradeUrl={planInfo?.upgradeUrl}
                      />
                    ) : null}
                    {researchEligible && contentResearchEnabled ? (
                      <button
                        type="button"
                        className={!contentBrief && !contentResearch ? btnPrimary : btnSecondary}
                        onClick={handleResearchAndBrief}
                        disabled={busy || researching || generatingBrief}
                      >
                        <Sparkles
                          className={`h-4 w-4 ${researching ? 'motion-safe:animate-pulse' : ''}`}
                          aria-hidden
                        />
                        {researching ? 'Researching…' : 'Research & brief'}
                      </button>
                    ) : null}
                    {contentBriefEnabled ? (
                      <button
                        type="button"
                        className={contentBrief ? btnSecondary : btnPrimary}
                        onClick={handleGenerateBrief}
                        disabled={busy || generatingBrief || researching}
                      >
                        <Wand2
                          className={`h-4 w-4 ${generatingBrief ? 'motion-safe:animate-pulse' : ''}`}
                          aria-hidden
                        />
                        {generatingBrief
                          ? 'Generating brief…'
                          : contentBrief
                            ? 'Regenerate brief'
                            : 'Generate content brief'}
                      </button>
                    ) : null}
                  </>
                ) : null}

                {!inlineFix && !contentBriefEligible ? (
                  <p className="text-muted-foreground text-sm">
                    This issue requires manual follow-up in the admin or codebase.
                  </p>
                ) : null}

                {manualRoute && onNavigate ? (
                  <button
                    type="button"
                    className={btnSecondary}
                    onClick={() => onNavigate(manualRoute)}
                    disabled={busy}
                  >
                    Edit manually
                  </button>
                ) : null}
                <button
                  type="button"
                  className={btnSecondary}
                  onClick={handleIgnore}
                  disabled={busy}
                >
                  Ignore
                </button>
                {onOpenDetails ? (
                  <button
                    type="button"
                    className="text-primary hover:bg-accent focus-visible:ring-ring rounded-md px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none"
                    onClick={onOpenDetails}
                    disabled={busy}
                  >
                    More details
                  </button>
                ) : null}
              </div>
            </>
          )}
        </div>
      </td>
    </tr>
  )
}

export function SeoIssueFixToggle({
  expanded,
  fixable,
  onToggle,
}: {
  expanded: boolean
  fixable: boolean
  onToggle: () => void
}) {
  return (
    <button
      type="button"
      onClick={onToggle}
      aria-expanded={expanded}
      className="text-primary hover:bg-accent focus-visible:ring-ring inline-flex items-center gap-1 rounded-md px-2 py-1 text-sm focus-visible:ring-2 focus-visible:outline-none"
    >
      {fixable ? 'Fix' : 'View'}
      <ChevronDown
        className={`h-3.5 w-3.5 motion-safe:transition-transform ${expanded ? 'rotate-180' : ''}`}
        aria-hidden
      />
    </button>
  )
}
