"use client";

/**
 * Content Audit — Analyzes all pages by GSC performance data,
 * classifies into action buckets, detects cannibalization.
 */

import { Fragment, useState, useEffect, useCallback } from "react";
import { useBrand } from "@/context/brand-context";
import { useBackgroundTasks } from "@/lib/stores/task-store";
import {
  FileSearch, Loader2, Sparkles, TrendingUp, TrendingDown, Minus, AlertTriangle,
  ChevronDown, ChevronUp, ChevronRight,
} from "lucide-react";

import PageDetailPanel from "@/components/content-audit/page-detail-panel";

type PageAction = "keep" | "update" | "merge" | "delete" | "optimize" | "cannibalized";

interface AuditedPage {
  url: string; clicks30d: number; clicksPrev30d: number; trend: string;
  position: number; ctr: number; impressions: number; action: PageAction; reason: string;
  firstSeenAt?: string | null;
  lastSeenAt?: string | null;
  discoveredSource?: "gsc" | "sitemap" | "site_tag" | "crawl" | null;
}

const ACTION_COLORS: Record<PageAction, { bg: string; text: string; label: string }> = {
  keep: { bg: "bg-green-50", text: "text-green-700", label: "Keep" },
  update: { bg: "bg-amber-50", text: "text-amber-700", label: "Update" },
  optimize: { bg: "bg-blue-50", text: "text-blue-700", label: "Optimize" },
  merge: { bg: "bg-purple-50", text: "text-purple-700", label: "Merge" },
  delete: { bg: "bg-red-50", text: "text-red-700", label: "Delete" },
  cannibalized: { bg: "bg-orange-50", text: "text-orange-700", label: "Cannibalized" },
};

function TrendIcon({ trend }: { trend: string }) {
  if (trend === "growing") return <TrendingUp className="w-3.5 h-3.5 text-green-500" />;
  if (trend === "declining") return <TrendingDown className="w-3.5 h-3.5 text-red-500" />;
  if (trend === "dead") return <AlertTriangle className="w-3.5 h-3.5 text-red-400" />;
  return <Minus className="w-3.5 h-3.5 text-slate-400" />;
}

// ─── Health score (client-side, derived from the audited row) ──────────────
// Pure function — no network call. Mirrors the spec's ladder:
//   position penalty (15/10 at >10/>20)
//   CTR penalty (10/10 at <2%/<1%)
//   trend penalty (10 when declining)
// We can't read bounce rate / tech issues / meta-desc presence without
// hitting the page-detail API for every row, so the score is a quick
// "health at a glance" signal based purely on the GSC row itself.
// Users get the full multi-signal view by expanding the row.
function calculatePageHealth(p: AuditedPage): number {
  let score = 100;
  if (p.position > 20) score -= 25;
  else if (p.position > 10) score -= 15;
  if (p.ctr > 0 && p.ctr < 1) score -= 20;
  else if (p.ctr > 0 && p.ctr < 2) score -= 10;
  if (p.trend === "declining") score -= 15;
  if (p.trend === "dead") score -= 40;
  return Math.max(0, Math.min(100, score));
}

function healthColor(score: number): { dot: string; text: string; label: string } {
  if (score >= 80) return { dot: "bg-emerald-500", text: "text-emerald-700", label: "Healthy" };
  if (score >= 60) return { dot: "bg-amber-500",   text: "text-amber-700",   label: "Needs work" };
  return                  { dot: "bg-red-500",     text: "text-red-700",     label: "Critical" };
}

/** Detect page type from URL pattern. Matches the spec's hint list
 *  plus location-page heuristics. Returned string doubles as the
 *  filter-key so Type All | Blog | Services | Spanish | English
 *  works without a mapping table. */
type PageType =
  | "homepage"
  | "spanish"
  | "article"
  | "service"
  | "location"
  | "about"
  | "category"
  | "system"
  | "other";

/**
 * Classify a page URL into one of the content buckets. Multi-signal
 * heuristic — most real-world content sites put blog posts at root
 * level with 3+ word slugs (e.g. /symptoms-of-poor-circulation/)
 * rather than under a /blog/ prefix, so relying on path prefix alone
 * leaves hundreds of pages mis-bucketed as "Other".
 *
 * Priority order matters — earlier buckets win ties:
 *   1. System/asset URLs (sitemap.xml, wp-admin, etc.)
 *   2. Homepage ("/" or empty path)
 *   3. Spanish (any path segment /es/ or /espanol/ — a Spanish
 *      article is still Spanish)
 *   4. Location (explicit city/state patterns or /location/ prefix)
 *   5. About/team/contact (exact-match short paths)
 *   6. Service (/conditions/, /treatments/, /procedures/, /services/)
 *   7. Category (/category/, /tag/, /page/N/, /archive/)
 *   8. Article (root-level slug with 3+ word descriptors — the
 *      catch-all for long-form content, OR /news|/blog|/articles
 *      prefixes, OR any multi-segment content path not matched
 *      above).
 *   9. Page (short root-level slug, 1-2 words — generic landing).
 *   0. Other (nothing matched — rare).
 */
function detectPageType(url: string): PageType {
  let path = "";
  try {
    path = url.startsWith("http") ? new URL(url).pathname.toLowerCase() : url.toLowerCase();
  } catch {
    path = url.replace(/^https?:\/\/[^/]+/, "").toLowerCase();
  }

  // 1. System / asset paths (wp-*, sitemap, asset extensions)
  if (
    /^\/(wp-content|wp-admin|wp-includes|wp-json|feed|sitemap|robots\.txt|favicon)/.test(path) ||
    /\.(xml|txt|json|css|js|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|pdf|map)(\?|$)/i.test(path)
  ) return "system";

  // 2. Homepage
  if (path === "/" || path === "") return "homepage";

  // 3. Spanish content — check BEFORE service/article so Spanish
  //    articles keep the Spanish label.
  if (/\/(es|espanol)(\/|$)/.test(path)) return "spanish";

  // 4. Location pages
  if (
    /\/(location|locations|office|offices|clinic|clinics)(\/|$)/.test(path) ||
    /\/(katy|humble|houston|sugar-?land|the-?woodlands|spring|cypress|tomball|pearland|pasadena|baytown|league-?city|missouri-?city|richmond|rosenberg|stafford|bellaire|webster|clear-?lake|friendswood|galveston|beaumont|conroe)(-?tx|-?texas)?\/?$/i.test(path)
  ) return "location";

  // 5. About / team / contact — exact-match short paths.
  if (/^\/(about|about-us|team|doctors|physicians|our-team|staff|contact|contact-us|careers|privacy|terms|privacy-policy|terms-of-service|accessibility)\/?$/.test(path)) return "about";

  // 6. Service / condition / treatment pages
  if (
    /^\/(conditions|treatments|procedures|services|specialties|conditions-we-(help-with|treat))(\/|$)/.test(path) ||
    /^\/category\/(conditions|treatments|procedures|services)\//.test(path)
  ) return "service";

  // 7. Category / tag / archive / pagination
  if (
    /^\/(category|tag|archive|author)\//.test(path) ||
    /\/page\/\d+\/?$/.test(path)
  ) return "category";

  // 8-9. Content vs generic page — heuristic on slug shape.
  const segments = path.split("/").filter(Boolean);
  if (segments.length === 1) {
    // Root-level single segment. Count hyphen-separated words: 3+
    // reads as a long-form article slug ("symptoms-of-poor-circulation"),
    // 1-2 reads as a short landing page ("pricing", "schedule").
    const wordCount = segments[0].split("-").length;
    if (wordCount >= 3) return "article";
    return "other"; // short slug — could be anything, leave ambiguous
  }

  if (segments.length >= 2) {
    // Explicit blog/news/resources prefixes.
    if (/^(news|blog|articles|insights|resources|education|learn|health-hub|blog-posts)$/.test(segments[0])) return "article";
    // Default multi-segment content paths to article — on a content
    // site, anything with 2+ segments that wasn't already bucketed
    // is much more likely editorial than utility.
    return "article";
  }

  return "other";
}

const TYPE_META: Record<PageType, { label: string; bg: string }> = {
  homepage: { label: "Homepage", bg: "bg-indigo-50 text-indigo-700" },
  spanish:  { label: "Spanish",  bg: "bg-rose-50 text-rose-700" },
  article:  { label: "Article",  bg: "bg-blue-50 text-blue-700" },
  service:  { label: "Service",  bg: "bg-emerald-50 text-emerald-700" },
  location: { label: "Location", bg: "bg-amber-50 text-amber-700" },
  about:    { label: "About",    bg: "bg-slate-100 text-slate-700" },
  category: { label: "Category", bg: "bg-gray-100 text-gray-700" },
  system:   { label: "System",   bg: "bg-red-50 text-red-600" },
  other:    { label: "Other",    bg: "bg-slate-50 text-slate-500" },
};

export default function ContentAuditPage() {
  const { brand } = useBrand();
  const { addTask, completeTask, failTask } = useBackgroundTasks();

  const [results, setResults] = useState<AuditedPage[]>([]);
  const [aiSummary, setAiSummary] = useState<string | null>(null);
  const [totalPages, setTotalPages] = useState(0);
  const [loading, setLoading] = useState(true);
  const [running, setRunning] = useState(false);
  const [filter, setFilter] = useState<PageAction | "all">("all");
  const [typeFilter, setTypeFilter] = useState<PageType | "all">("all");
  const [healthFilter, setHealthFilter] = useState<"all" | "healthy" | "needs_work" | "critical">("all");
  const [search, setSearch] = useState("");
  const [sortBy, setSortBy] = useState<"clicks30d" | "impressions" | "position" | "ctr" | "health" | "firstSeenAt">("clicks30d");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
  // Set of row URLs currently expanded. Using a Set so multiple rows
  // can be expanded at once — cheap to render since each panel's
  // data fetches are keyed on its URL.
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  function toggleExpand(url: string) {
    setExpanded((prev) => {
      const next = new Set(prev);
      next.has(url) ? next.delete(url) : next.add(url);
      return next;
    });
  }

  const loadLatest = useCallback(async () => {
    if (!brand?.id) return;
    setLoading(true);
    try {
      const r = await fetch(`/api/content-audit/latest?brandId=${brand.id}`);
      if (r.ok) { const d = await r.json(); if (d.audit) { setResults(d.audit.results as AuditedPage[]); setAiSummary(d.audit.aiSummary); setTotalPages(d.audit.totalPages); } }
    } finally { setLoading(false); }
  }, [brand.id]);

  useEffect(() => { loadLatest(); }, [loadLatest]);

  async function runAudit() {
    setRunning(true);
    const taskId = addTask({ id: `content_audit_${Date.now()}`, type: "content_audit", label: "Running Content Audit...", brandId: brand.id, resultUrl: "/content-audit" });
    try {
      const r = await fetch("/api/content-audit/run", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ brandId: brand.id }) });
      if (r.ok) { const d = await r.json(); setResults(d.results); setAiSummary(d.aiSummary); setTotalPages(d.totalPages); completeTask(taskId, { resultUrl: "/content-audit", resultSummary: `Audited ${d.totalPages} pages` }); }
      else failTask(taskId, "Audit failed");
    } catch { failTask(taskId, "Network error"); }
    setRunning(false);
  }

  const actionCounts = results.reduce((acc, r) => { acc[r.action] = (acc[r.action] || 0) + 1; return acc; }, {} as Record<string, number>);

  // Multi-dimensional filter chain — action → type → health → search.
  // All applied in-memory; the dataset is always <= ~1000 rows so no
  // need for server-side paging.
  const filtered = results.filter((r) => {
    if (filter !== "all" && r.action !== filter) return false;
    if (typeFilter !== "all" && detectPageType(r.url) !== typeFilter) return false;
    if (healthFilter !== "all") {
      const h = calculatePageHealth(r);
      if (healthFilter === "healthy" && h < 80) return false;
      if (healthFilter === "needs_work" && (h < 60 || h >= 80)) return false;
      if (healthFilter === "critical" && h >= 60) return false;
    }
    if (search) {
      const q = search.toLowerCase();
      if (!r.url.toLowerCase().includes(q)) return false;
    }
    return true;
  });
  const sorted = [...filtered].sort((a, b) => {
    if (sortBy === "firstSeenAt") {
      const at = a.firstSeenAt ? new Date(a.firstSeenAt).getTime() : 0;
      const bt = b.firstSeenAt ? new Date(b.firstSeenAt).getTime() : 0;
      return sortDir === "desc" ? bt - at : at - bt;
    }
    const av = sortBy === "health" ? calculatePageHealth(a) : ((a[sortBy] as number | undefined) ?? 0);
    const bv = sortBy === "health" ? calculatePageHealth(b) : ((b[sortBy] as number | undefined) ?? 0);
    return sortDir === "desc" ? bv - av : av - bv;
  });

  function toggleSort(col: typeof sortBy) {
    if (sortBy === col) setSortDir((d) => d === "desc" ? "asc" : "desc");
    else { setSortBy(col); setSortDir("desc"); }
  }

  const SortIcon = ({ col }: { col: typeof sortBy }) => sortBy === col ? (sortDir === "desc" ? <ChevronDown className="w-3 h-3" /> : <ChevronUp className="w-3 h-3" />) : null;

  if (loading) return <div className="flex items-center justify-center h-64"><Loader2 className="w-8 h-8 animate-spin text-slate-300" /></div>;

  return (
    <div className="space-y-6 max-w-6xl">
      <div className="flex items-start justify-between">
        <div>
          <h1 className="text-2xl font-bold text-slate-900">Content Audit</h1>
          <p className="text-sm text-slate-500 mt-1">Analyze page performance and identify content actions</p>
        </div>
        <button onClick={runAudit} disabled={running} className="flex items-center gap-2 px-4 py-2 bg-slate-900 text-white text-sm font-semibold rounded-lg hover:bg-slate-800 disabled:opacity-50">
          {running ? <Loader2 className="w-4 h-4 animate-spin" /> : <FileSearch className="w-4 h-4" />} {running ? "Auditing..." : "Run Audit"}
        </button>
      </div>

      {/* Summary cards */}
      {totalPages > 0 && (
        <div className="grid grid-cols-7 gap-2">
          <div className="bg-white rounded-xl border border-slate-200 p-3 text-center">
            <p className="text-lg font-bold text-slate-900">{totalPages}</p>
            <p className="text-[10px] text-slate-500">Total Pages</p>
          </div>
          {(Object.entries(ACTION_COLORS) as [PageAction, typeof ACTION_COLORS["keep"]][]).map(([action, c]) => (
            <button key={action} onClick={() => setFilter(filter === action ? "all" : action)}
              className={`rounded-xl border p-3 text-center transition-all ${filter === action ? `${c.bg} border-current ${c.text}` : "bg-white border-slate-200"}`}>
              <p className="text-lg font-bold">{actionCounts[action] || 0}</p>
              <p className="text-[10px] font-semibold">{c.label}</p>
            </button>
          ))}
        </div>
      )}

      {/* AI Summary */}
      {aiSummary && (
        <div className="bg-white rounded-xl border border-slate-200 p-5 flex items-start gap-3">
          <Sparkles className="w-5 h-5 text-violet-500 mt-0.5 shrink-0" />
          <div>
            <p className="text-sm font-semibold text-slate-800 mb-1">AI Analysis</p>
            <p className="text-sm text-slate-600 leading-relaxed whitespace-pre-line">{aiSummary}</p>
          </div>
        </div>
      )}

      {/* Filters — type / health / search. Action filter is handled by
          the summary cards above; these are the secondary cuts most
          users want while triaging the table. */}
      {results.length > 0 && (
        <div className="flex items-center gap-2 flex-wrap bg-white rounded-xl border border-slate-200 px-4 py-3">
          <input
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Search URL…"
            className="flex-1 min-w-[200px] px-3 py-1.5 text-xs border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500/40"
          />
          <select
            value={typeFilter}
            onChange={(e) => setTypeFilter(e.target.value as PageType | "all")}
            className="text-xs border border-slate-200 rounded-lg px-2.5 py-1.5 bg-white"
          >
            <option value="all">All types</option>
            <option value="article">Article</option>
            <option value="service">Service</option>
            <option value="location">Location</option>
            <option value="spanish">Spanish</option>
            <option value="about">About</option>
            <option value="category">Category</option>
            <option value="homepage">Homepage</option>
            <option value="system">System</option>
            <option value="other">Other</option>
          </select>
          <select
            value={healthFilter}
            onChange={(e) => setHealthFilter(e.target.value as typeof healthFilter)}
            className="text-xs border border-slate-200 rounded-lg px-2.5 py-1.5 bg-white"
          >
            <option value="all">All health</option>
            <option value="healthy">Healthy (80+)</option>
            <option value="needs_work">Needs work (60-79)</option>
            <option value="critical">Critical (&lt;60)</option>
          </select>
          <span className="ml-auto text-[10px] text-slate-400">
            {sorted.length} of {results.length}
          </span>
        </div>
      )}

      {/* Results table */}
      {sorted.length > 0 && (
        <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-slate-100 bg-slate-50">
                <th className="w-8 px-2" />
                <th className="text-left px-4 py-2.5 text-[11px] font-bold text-slate-500 uppercase">Page</th>
                <th className="text-left px-2 py-2.5 text-[11px] font-bold text-slate-500 uppercase w-20">Type</th>
                <th className="text-center px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer w-24" onClick={() => toggleSort("health")}>Health <SortIcon col="health" /></th>
                <th className="text-right px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer" onClick={() => toggleSort("clicks30d")}>Clicks <SortIcon col="clicks30d" /></th>
                <th className="text-center px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase">Trend</th>
                <th className="text-right px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer" onClick={() => toggleSort("position")}>Position <SortIcon col="position" /></th>
                <th className="text-right px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer" onClick={() => toggleSort("ctr")}>CTR <SortIcon col="ctr" /></th>
                <th className="text-right px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer" onClick={() => toggleSort("impressions")}>Impressions <SortIcon col="impressions" /></th>
                <th className="text-right px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase cursor-pointer" onClick={() => toggleSort("firstSeenAt")}>Discovered <SortIcon col="firstSeenAt" /></th>
                <th className="text-center px-3 py-2.5 text-[11px] font-bold text-slate-500 uppercase">Action</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-slate-100">
              {sorted.slice(0, 50).map((page, i) => {
                const ac = ACTION_COLORS[page.action];
                const isOpen = expanded.has(page.url);
                const health = calculatePageHealth(page);
                const hc = healthColor(health);
                const pageType = detectPageType(page.url);
                const typeMeta = TYPE_META[pageType];
                return (
                  <Fragment key={i}>
                    <tr
                      className={`hover:bg-slate-50 cursor-pointer ${isOpen ? "bg-slate-50" : ""}`}
                      onClick={() => toggleExpand(page.url)}
                    >
                      {/* Chevron column — click anywhere on the row to
                          toggle, but the explicit icon makes the
                          affordance discoverable. */}
                      <td className="px-2 py-2.5 text-center">
                        <ChevronRight className={`w-3.5 h-3.5 text-slate-400 transition-transform ${isOpen ? "rotate-90 text-slate-700" : ""}`} />
                      </td>
                      <td className="px-4 py-2.5 text-xs font-mono text-slate-700 truncate max-w-[280px]" title={page.url}>
                        {page.url.replace(/^https?:\/\/[^/]+/, "")}
                      </td>
                      <td className="px-2 py-2.5">
                        <span className={`text-[9px] font-bold uppercase tracking-wide px-1.5 py-0.5 rounded ${typeMeta.bg}`}>
                          {typeMeta.label}
                        </span>
                      </td>
                      <td className="text-center px-3 py-2.5" title={`Health score: ${health}/100`}>
                        <span className={`inline-flex items-center gap-1.5 text-xs font-bold ${hc.text}`}>
                          <span className={`inline-block w-1.5 h-1.5 rounded-full ${hc.dot}`} />
                          {health}
                        </span>
                      </td>
                      <td className="text-right px-3 py-2.5 text-xs font-semibold text-slate-800">{page.clicks30d.toLocaleString()}</td>
                      <td className="text-center px-3 py-2.5"><TrendIcon trend={page.trend} /></td>
                      <td className="text-right px-3 py-2.5 text-xs text-slate-600">{page.position > 0 ? page.position.toFixed(1) : "—"}</td>
                      <td className="text-right px-3 py-2.5 text-xs text-slate-600">{page.ctr > 0 ? `${page.ctr.toFixed(1)}%` : "—"}</td>
                      <td className="text-right px-3 py-2.5 text-xs text-slate-600">{page.impressions.toLocaleString()}</td>
                      <td className="text-right px-3 py-2.5 text-xs">
                        {page.firstSeenAt ? (() => {
                          const d = new Date(page.firstSeenAt);
                          const days = Math.floor((Date.now() - d.getTime()) / 86_400_000);
                          const ageDot = days <= 30 ? "bg-emerald-400" : days <= 90 ? "bg-amber-400" : "bg-red-400";
                          const label = days === 0 ? "Today" : days === 1 ? "Yesterday" : days < 14 ? `${days}d ago` : days < 60 ? `${Math.round(days / 7)}w ago` : d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: days > 365 ? "numeric" : undefined });
                          const sourceLabel = page.discoveredSource === "gsc" ? "via GSC"
                            : page.discoveredSource === "sitemap" ? "via Sitemap"
                            : page.discoveredSource === "site_tag" ? "via Site Tag"
                            : page.discoveredSource === "crawl" ? "via Crawl"
                            : null;
                          return (
                            <span className="flex flex-col items-end gap-0.5" title={d.toISOString().split("T")[0]}>
                              <span className="flex items-center gap-1.5">
                                <span className={`w-1.5 h-1.5 rounded-full ${ageDot} shrink-0`} />
                                <span className="text-slate-600">{label}</span>
                              </span>
                              {sourceLabel && <span className="text-[9px] text-slate-400">{sourceLabel}</span>}
                            </span>
                          );
                        })() : <span className="text-slate-300">Unknown</span>}
                      </td>
                      <td className="text-center px-3 py-2.5">
                        <span className={`text-[10px] font-bold px-2 py-0.5 rounded-full ${ac.bg} ${ac.text}`} title={page.reason}>{ac.label}</span>
                      </td>
                    </tr>
                    {isOpen && (
                      <tr className="bg-slate-50/40">
                        <td colSpan={11} className="px-4 py-4 border-t border-slate-100">
                          <PageDetailPanel brandId={brand.id} pageUrl={page.url} />
                        </td>
                      </tr>
                    )}
                  </Fragment>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      {totalPages === 0 && !loading && (
        <div className="bg-white rounded-xl border border-slate-200 p-12 text-center">
          <FileSearch className="w-10 h-10 text-slate-200 mx-auto mb-3" />
          <p className="text-sm font-semibold text-slate-700 mb-1">No Content Audit Yet</p>
          <p className="text-xs text-slate-500">Run an audit to analyze your content inventory</p>
        </div>
      )}
    </div>
  );
}
