// =============================================================================
// HeadlineSift.com — Story Cluster List Table
// =============================================================================
"use client";

import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useTransition, useState, useEffect } from "react";
import { cn } from "@/lib/utils";
import { generateAiForStory } from "./actions";
import type { RankExplanation, ExplanationLine } from "@/lib/ranking/explainRankScore";

// ============================================================================
// Types
// ============================================================================

export interface StoryRow {
  id: string;
  canonicalTitle: string;
  categoryId: string | null;
  categoryName: string | null;
  countryId: string | null;
  countryName: string | null;
  countryCode: string | null;
  firstSeenAt: Date;
  lastSeenAt: Date;
  sourceCount: number;
  trustedSourceCount: number;
  officialSourcePresent: boolean;
  rankScore: number;
  impactScore: number;
  confidenceScore: number;
  status: string;
  articleCount: number;
  createdAt: Date;
}

interface SelectOption { id: string; name: string; }

interface Props {
  stories: StoryRow[];
  statusFilter: string | null;
  categoryFilter: string | null;
  countryFilter: string | null;
  page: number;
  totalPages: number;
  totalCount: number;
  categoryOptions: SelectOption[];
  countryOptions: SelectOption[];
}

// ============================================================================
// Sub-components
// ============================================================================

function StatusBadge({ status }: { status: string }) {
  const c: Record<string, string> = {
    DRAFT: "bg-slate-100 text-slate-600",
    NEEDS_REVIEW: "bg-amber-50 text-amber-700",
    APPROVED: "bg-blue-50 text-blue-700",
    PUBLISHED: "bg-green-50 text-green-700",
    HIDDEN: "bg-gray-100 text-gray-400",
    REJECTED: "bg-red-50 text-red-700",
  };
  return <span className={cn("inline-flex items-center rounded-full px-2 py-0.5 text-2xs font-semibold uppercase tracking-wider", c[status] ?? "bg-slate-100")}>{status.replace("_", " ")}</span>;
}

function RankScoreBar({ score }: { score: number }) {
  let color = "bg-red-500";
  if (score >= 70) color = "bg-green-500";
  else if (score >= 50) color = "bg-blue-500";
  else if (score >= 30) color = "bg-amber-500";

  return (
    <div className="flex items-center gap-2">
      <div className="h-2 flex-1 min-w-[40px] rounded-full bg-slate-200">
        <div className={cn("h-2 rounded-full transition-all", color)} style={{ width: `${score}%` }} />
      </div>
      <span className="text-xs font-bold tabular-nums w-8 text-right">{Math.round(score)}</span>
    </div>
  );
}

function ExplanationLine({ line }: { line: ExplanationLine }) {
  return (
    <div className="flex items-center gap-2 py-0.5">
      <span className={cn("text-xs font-mono font-semibold tabular-nums w-10 text-right", line.positive ? "text-green-600" : "text-red-600")}>
        {line.positive ? "+" : ""}{line.score}
      </span>
      <span className="text-xs text-body">{line.label}</span>
      {line.detail && <span className="text-2xs text-body-muted">({line.detail})</span>}
    </div>
  );
}

function RankBreakdown({ storyId, storyTitle }: { storyId: string; storyTitle: string }) {
  const [explanation, setExplanation] = useState<RankExplanation | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setLoading(true);
    setError(null);

    // Fetch the explanation from a server action
    fetch(`/admin/stories/api/explain?clusterId=${encodeURIComponent(storyId)}`)
      .then((res) => {
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
      })
      .then((data) => {
        setExplanation(data);
        setLoading(false);
      })
      .catch((err) => {
        setError(err.message);
        setLoading(false);
      });
  }, [storyId]);

  if (loading) {
    return (
      <div className="px-4 py-3 bg-surface-secondary border-t border-border">
        <p className="text-xs text-body-muted animate-pulse">Computing ranking breakdown…</p>
      </div>
    );
  }

  if (error) {
    return (
      <div className="px-4 py-3 bg-surface-secondary border-t border-border">
        <p className="text-xs text-red-600">Failed to load breakdown: {error}</p>
      </div>
    );
  }

  if (!explanation) return null;

  const boosts = explanation.lines.filter((l) => l.positive);
  const penalties = explanation.lines.filter((l) => !l.positive);

  return (
    <div className="px-4 py-3 bg-surface-secondary border-t border-border space-y-3">
      <div className="flex items-center gap-2">
        <span className={cn("text-xs font-semibold", explanation.matchesStored ? "text-green-600" : "text-amber-600")}>
          {explanation.matchesStored ? "✓" : "⚠"}
        </span>
        <span className="text-xs font-semibold text-heading">
          Rank Score: {explanation.totalScore}/100
        </span>
        {!explanation.matchesStored && (
          <span className="text-2xs text-amber-600">(recomputed — may differ from stored score)</span>
        )}
      </div>

      {/* Reasons summary */}
      <div className="text-xs text-body-muted">
        <p className="text-green-700">{explanation.boostSummary}</p>
        {penalties.length > 0 && <p className="text-red-600 mt-0.5">{explanation.penaltySummary}</p>}
      </div>

      {/* Detailed lines */}
      <div className="grid gap-0.5 sm:grid-cols-2">
        <div>
          <p className="text-2xs font-semibold uppercase tracking-wider text-body-muted mb-1">Boosts</p>
          {boosts.map((line, i) => <ExplanationLine key={`b-${i}`} line={line} />)}
          {boosts.length === 0 && <p className="text-2xs text-body-muted/50">None</p>}
        </div>
        <div>
          <p className="text-2xs font-semibold uppercase tracking-wider text-body-muted mb-1">Penalties</p>
          {penalties.map((line, i) => <ExplanationLine key={`p-${i}`} line={line} />)}
          {penalties.length === 0 && <p className="text-2xs text-body-muted/50">None</p>}
        </div>
      </div>
    </div>
  );
}

// ============================================================================
// AI Button
// ============================================================================

function AiButton({ storyId, storyTitle }: { storyId: string; storyTitle: string }) {
  const [isPending, startTransition] = useTransition();

  const handleClick = () => {
    if (!window.confirm(`Generate AI analysis for "${storyTitle.slice(0, 60)}"?`)) return;
    startTransition(() => { generateAiForStory(storyId); });
  };

  return (
    <button
      type="button"
      onClick={handleClick}
      disabled={isPending}
      className="rounded px-2 py-1 text-2xs font-medium text-purple-600 hover:bg-purple-50 transition-colors"
      title="Generate AI analysis"
    >
      {isPending ? "…" : "🤖"}
    </button>
  );
}

// ============================================================================
// Table Component
// ============================================================================

export default function StoryTable({ stories, statusFilter, categoryFilter, countryFilter, page, totalPages, totalCount, categoryOptions, countryOptions }: Props) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();
  const [expandedId, setExpandedId] = useState<string | null>(null);

  const navigate = useCallback((overrides: Record<string, string | null>) => {
    const params = new URLSearchParams(searchParams.toString());
    for (const [k, v] of Object.entries(overrides)) {
      if (v === null) params.delete(k); else params.set(k, v);
    }
    startTransition(() => { router.push(`/admin/stories?${params.toString()}`); });
  }, [router, searchParams, startTransition]);

  const toggleExpand = useCallback((id: string) => {
    setExpandedId((prev) => (prev === id ? null : id));
  }, []);

  const hasFilters = statusFilter !== null || categoryFilter !== null || countryFilter !== null;

  return (
    <div className="space-y-4">
      {/* Filters */}
      <div className="flex flex-wrap items-end gap-3">
        <div>
          <label className="block text-2xs font-medium text-body-muted mb-1">Status</label>
          <select value={statusFilter ?? ""} onChange={(e) => navigate({ status: e.target.value || null, page: null })} className="input text-xs" style={{ maxWidth: "8rem" }}>
            <option value="">All</option>
            <option value="DRAFT">Draft</option>
            <option value="NEEDS_REVIEW">Needs Review</option>
            <option value="APPROVED">Approved</option>
            <option value="PUBLISHED">Published</option>
            <option value="HIDDEN">Hidden</option>
            <option value="REJECTED">Rejected</option>
          </select>
        </div>
        <div>
          <label className="block text-2xs font-medium text-body-muted mb-1">Category</label>
          <select value={categoryFilter ?? ""} onChange={(e) => navigate({ category: e.target.value || null, page: null })} className="input text-xs" style={{ maxWidth: "10rem" }}>
            <option value="">All categories</option>
            {categoryOptions.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </div>
        <div>
          <label className="block text-2xs font-medium text-body-muted mb-1">Country</label>
          <select value={countryFilter ?? ""} onChange={(e) => navigate({ country: e.target.value || null, page: null })} className="input text-xs" style={{ maxWidth: "10rem" }}>
            <option value="">All countries</option>
            {countryOptions.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </div>
        {hasFilters && <span className="text-2xs text-body-muted self-end pb-1.5">{totalCount} result{totalCount !== 1 ? "s" : ""}</span>}
      </div>

      {/* Table */}
      {stories.length === 0 ? (
        <div className="card"><div className="flex flex-col items-center justify-center py-16 text-center"><span className="text-5xl">📰</span><h3 className="mt-4 text-lg font-semibold text-heading">No stories yet</h3><p className="mt-2 text-sm text-body-muted">Story clusters are created when articles are grouped. Run clustering first.</p></div></div>
      ) : (
        <div className="card overflow-x-auto p-0">
          <table className="w-full text-sm">
            <thead><tr className="border-b border-border bg-surface-secondary text-left">
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted">Title</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden sm:table-cell">Category</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden md:table-cell">Country</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden lg:table-cell w-24">Rank</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted hidden lg:table-cell w-16">Sources</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted">Status</th>
              <th className="px-4 py-3 text-xs font-semibold uppercase tracking-wide text-body-muted w-16"><span className="sr-only">AI</span></th>
            </tr></thead>
            <tbody className="divide-y divide-border">
              {stories.map((story) => {
                const isExpanded = expandedId === story.id;
                return (
                  <tr key={story.id}>
                    <td className="px-4 py-3">
                      <button type="button" onClick={() => toggleExpand(story.id)} className="text-left hover:underline decoration-dotted">
                        <span className="font-medium text-heading">{story.canonicalTitle}</span>
                      </button>
                      <div className="flex items-center gap-2 mt-0.5">
                        {story.officialSourcePresent && <span className="text-sm" title="Official source present">🏛️</span>}
                        <span className="text-2xs text-body-muted">{story.articleCount} article{story.articleCount !== 1 ? "s" : ""}</span>
                      </div>
                    </td>
                    <td className="px-4 py-3 hidden sm:table-cell"><span className="text-xs text-body-muted">{story.categoryName ?? "—"}</span></td>
                    <td className="px-4 py-3 hidden md:table-cell">{story.countryName ? <span className="text-xs">{story.countryName}</span> : <span className="text-body-muted/50">—</span>}</td>
                    <td className="px-4 py-3 hidden lg:table-cell"><RankScoreBar score={story.rankScore} /></td>
                    <td className="px-4 py-3 hidden lg:table-cell">
                      <span className="text-xs tabular-nums">{story.sourceCount}</span>
                      {story.trustedSourceCount > 0 && <span className="text-2xs text-green-600 ml-1">({story.trustedSourceCount}⭐)</span>}
                    </td>
                    <td className="px-4 py-3"><StatusBadge status={story.status} /></td>
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-1">
                        <AiButton storyId={story.id} storyTitle={story.canonicalTitle} />
                      </div>
                    </td>
                    {/* Expandable breakdown row */}
                    {isExpanded && (
                      <td colSpan={7} className="p-0">
                        <RankBreakdown storyId={story.id} storyTitle={story.canonicalTitle} />
                      </td>
                    )}
                  </tr>
                );
              })}
            </tbody>
          </table>
          <div className="flex items-center justify-between border-t border-border px-4 py-3">
            <span className="text-xs text-body-muted">{totalCount} {totalCount === 1 ? "story" : "stories"}</span>
            {totalPages > 1 && (
              <div className="flex items-center gap-2">
                <button type="button" disabled={page <= 1} onClick={() => navigate({ page: String(page - 1) })} className="rounded px-2 py-1 text-xs text-brand-600 hover:bg-brand-50 disabled:text-body-muted/30 disabled:cursor-not-allowed">Previous</button>
                <span className="text-xs text-body-muted">{page} / {totalPages}</span>
                <button type="button" disabled={page >= totalPages} onClick={() => navigate({ page: String(page + 1) })} className="rounded px-2 py-1 text-xs text-brand-600 hover:bg-brand-50 disabled:text-body-muted/30 disabled:cursor-not-allowed">Next</button>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
