"use client";
import { useState } from "react";
import useSWR from "swr";
import { api } from "@/lib/api";
import GlassCard from "@/components/GlassCard";
import StatCard from "@/components/StatCard";
import PageExplainer from "@/components/PageExplainer";
import { formatDistanceToNow, parseISO } from "date-fns";
import { clsx } from "clsx";

// ── types ─────────────────────────────────────────────────────────────────────

type Rule = {
  rule: string;
  source_instruction: string;
  evidence: string;
  added_at_iso?: string;
  last_violated_iso?: string;
  archived_at_iso?: string;
  violation_count: number;
  status?: string;
  permanent?: boolean;
  archive_cycle_count?: number;
  sessions_checked?: number;
  sessions_since_violation?: number;
};

type Candidate = {
  target_file: string;
  change_type: string;
  rationale: string;
  diff_description: string;
};

type PendingGroup = {
  key: string;
  candidates: Candidate[];
  session_at_iso?: string;
  summary_excerpt?: string;
  updated_at?: string;
};

type HistoryGroup = {
  key: string;
  status: string;
  candidates: Candidate[];
  session_at_iso?: string;
  resolved_at_iso?: string;
};

// ── helpers ───────────────────────────────────────────────────────────────────

function timeAgo(iso?: string | null): string {
  if (!iso) return "—";
  try { return formatDistanceToNow(parseISO(iso), { addSuffix: true }); }
  catch { return "—"; }
}

function ViolationBadge({ count }: { count: number }) {
  const color =
    count >= 4 ? "bg-red-500/20 text-red-400 border-red-500/30" :
    count >= 2 ? "bg-amber-500/20 text-amber-400 border-amber-500/30" :
                 "bg-emerald-500/20 text-emerald-400 border-emerald-500/30";
  const label = count === 1 ? "1× — first time" : `${count}× — recurring`;
  return (
    <span className={clsx("text-xs px-2 py-0.5 rounded-full border font-mono", color)}>
      {label}
    </span>
  );
}

function LifecycleBadge({ rule }: { rule: Rule }) {
  const status = rule.status ?? "active";
  const cfg: Record<string, { color: string; label: string }> = {
    stuck:    { color: "bg-red-500/20 text-red-400 border-red-500/30",     label: "Stuck" },
    chronic:  { color: "bg-orange-500/20 text-orange-400 border-orange-500/30", label: "Chronic" },
    permanent:{ color: "bg-violet-500/20 text-violet-400 border-violet-500/30", label: "Permanent" },
    active:   { color: "bg-white/10 text-white/40 border-white/10",        label: "Active" },
    archived: { color: "bg-white/5 text-white/25 border-white/5",          label: "Archived" },
    retired:  { color: "bg-white/5 text-white/20 border-white/5",          label: "Retired" },
  };
  const c = cfg[status] ?? cfg.active;
  return (
    <span className={clsx("text-xs px-2 py-0.5 rounded-full border font-mono shrink-0", c.color)}>
      {c.label}
    </span>
  );
}

function StatusBadge({ status }: { status: string }) {
  const styles: Record<string, string> = {
    applied:           "bg-emerald-500/20 text-emerald-400",
    dashboard_approved:"bg-blue-500/20 text-blue-400",
    rejected:          "bg-white/10 text-white/40",
  };
  const labels: Record<string, string> = {
    applied:            "Applied",
    dashboard_approved: "Queued",
    rejected:           "Rejected",
  };
  return (
    <span className={clsx("text-xs px-2 py-0.5 rounded-full", styles[status] ?? "bg-white/10 text-white/40")}>
      {labels[status] ?? status}
    </span>
  );
}

// ── sub-components ────────────────────────────────────────────────────────────

function RuleCard({ rule }: { rule: Rule }) {
  const [expanded, setExpanded] = useState(false);
  const isRecurring = rule.violation_count > 1;
  return (
    <GlassCard className={clsx("p-5 space-y-3", isRecurring && "border border-amber-500/20")}>
      <div className="flex items-start justify-between gap-3">
        <p className="text-sm text-white leading-snug flex-1">{rule.rule}</p>
        <ViolationBadge count={rule.violation_count ?? 1} />
      </div>

      {isRecurring && (
        <p className="text-xs text-amber-400/70">
          This rule was re-violated {rule.violation_count - 1} time{rule.violation_count > 2 ? "s" : ""} after promotion — it may need to be more prominent in TOOLS.md.
        </p>
      )}

      <div className="flex items-center gap-3 text-xs text-white/30">
        <span>Promoted {timeAgo(rule.added_at_iso)}</span>
        {rule.last_violated_iso && rule.violation_count > 1 && (
          <span>· Last re-violated {timeAgo(rule.last_violated_iso)}</span>
        )}
      </div>

      <button onClick={() => setExpanded(!expanded)}
        className="text-xs text-white/30 hover:text-white/60 transition-colors">
        {expanded ? "Hide context" : "Show context"}
      </button>
      {expanded && (
        <div className="space-y-2">
          {rule.source_instruction && (
            <div className="bg-white/3 rounded-lg px-3 py-2">
              <p className="text-xs text-white/30 mb-1">Source instruction</p>
              <p className="text-xs text-white/55 leading-relaxed">{rule.source_instruction}</p>
            </div>
          )}
          {rule.evidence && (
            <div className="bg-white/3 rounded-lg px-3 py-2">
              <p className="text-xs text-white/30 mb-1">Evidence from session</p>
              <p className="text-xs text-white/55 leading-relaxed italic">"{rule.evidence}"</p>
            </div>
          )}
        </div>
      )}
    </GlassCard>
  );
}

function PendingCard({ group, onReview }: { group: PendingGroup; onReview: () => void }) {
  const [loading, setLoading] = useState<string | null>(null);

  const doReview = async (action: "approve" | "reject", index?: number) => {
    const key = `${action}-${index ?? "all"}`;
    setLoading(key);
    try {
      await api.improvements.review(group.key, action, index);
      onReview();
    } finally {
      setLoading(null);
    }
  };

  return (
    <GlassCard className="p-5 space-y-4">
      <div className="flex items-center justify-between">
        <p className="text-xs text-white/30">Session {timeAgo(group.session_at_iso ?? group.updated_at)}</p>
        <div className="flex gap-2">
          <button
            onClick={() => doReview("approve")}
            disabled={!!loading}
            className={clsx("btn-primary text-xs text-white", loading && "opacity-60 cursor-not-allowed")}>
            {loading?.startsWith("approve") ? "Queuing…" : "Approve all"}
          </button>
          <button
            onClick={() => doReview("reject")}
            disabled={!!loading}
            className="btn-ghost text-xs text-white/40">
            Reject all
          </button>
        </div>
      </div>

      {group.summary_excerpt && (
        <p className="text-xs text-white/25 italic leading-relaxed border-l border-white/10 pl-3">
          "{group.summary_excerpt.slice(0, 200)}{group.summary_excerpt.length > 200 ? "…" : ""}"
        </p>
      )}

      <div className="space-y-3">
        {group.candidates.map((c, i) => {
          const changeColor =
            c.change_type === "add"    ? "bg-emerald-500/15 text-emerald-400 border-emerald-500/25" :
            c.change_type === "remove" ? "bg-red-500/15 text-red-400 border-red-500/25" :
                                         "bg-amber-500/15 text-amber-400 border-amber-500/25";
          const changePrefix =
            c.change_type === "add"    ? "+" :
            c.change_type === "remove" ? "−" : "~";
          const diffLineColor =
            c.change_type === "add"    ? "border-l-2 border-emerald-500/50 bg-emerald-500/5" :
            c.change_type === "remove" ? "border-l-2 border-red-500/50 bg-red-500/5" :
                                         "border-l-2 border-amber-500/50 bg-amber-500/5";
          return (
            <div key={i} className="bg-white/3 rounded-xl p-4 space-y-3">
              <div className="flex items-center justify-between gap-2">
                <div className="flex items-center gap-2">
                  <span className="text-xs px-1.5 py-0.5 rounded bg-white/8 text-white/50 font-mono">
                    {c.target_file}
                  </span>
                  <span className={clsx("text-xs px-1.5 py-0.5 rounded border font-mono", changeColor)}>
                    {changePrefix} {c.change_type}
                  </span>
                </div>
                <div className="flex gap-1.5 shrink-0">
                  <button
                    onClick={() => doReview("approve", i + 1)}
                    disabled={!!loading}
                    className="text-xs px-2 py-1 rounded-lg bg-emerald-500/15 text-emerald-400 hover:bg-emerald-500/25 transition-colors disabled:opacity-60">
                    ✓
                  </button>
                  <button
                    onClick={() => doReview("reject", i + 1)}
                    disabled={!!loading}
                    className="text-xs px-2 py-1 rounded-lg bg-white/5 text-white/30 hover:bg-white/10 transition-colors disabled:opacity-60">
                    ✕
                  </button>
                </div>
              </div>
              <div className={clsx("rounded-lg px-3 py-2 font-mono text-sm leading-relaxed", diffLineColor)}>
                {c.diff_description}
              </div>
              <p className="text-xs text-white/35 leading-relaxed">{c.rationale}</p>
            </div>
          );
        })}
      </div>
    </GlassCard>
  );
}

function HistoryCard({ group }: { group: HistoryGroup }) {
  return (
    <GlassCard className="p-4 space-y-3">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <StatusBadge status={group.status} />
          <span className="text-xs text-white/30">
            {group.resolved_at_iso ? timeAgo(group.resolved_at_iso) : timeAgo(group.session_at_iso)}
          </span>
        </div>
        <span className="text-xs text-white/20 font-mono">{group.key.slice(-10)}</span>
      </div>
      <div className="space-y-1.5">
        {group.candidates.map((c, i) => (
          <div key={i} className="flex items-start gap-2">
            <span className="text-xs px-1.5 py-0.5 rounded bg-white/5 text-white/40 font-mono shrink-0">
              {c.target_file}
            </span>
            <p className="text-xs text-white/50 leading-snug">{c.diff_description}</p>
          </div>
        ))}
      </div>
    </GlassCard>
  );
}

function HealthRuleCard({ rule, index, onRetire }: { rule: Rule; index: number; onRetire: () => void }) {
  const [expanded, setExpanded] = useState(false);
  const [retiring, setRetiring] = useState(false);
  const isAlert = rule.status === "stuck" || rule.status === "chronic";

  const doRetire = async () => {
    setRetiring(true);
    try { await api.improvements.ruleAction(index, "retire"); onRetire(); }
    finally { setRetiring(false); }
  };

  return (
    <GlassCard className={clsx("p-5 space-y-3",
      rule.status === "stuck"    && "border border-red-500/25",
      rule.status === "chronic"  && "border border-orange-500/25",
      rule.status === "permanent"&& "border border-violet-500/15",
    )}>
      <div className="flex items-start justify-between gap-3">
        <p className="text-sm text-white leading-snug flex-1">{rule.rule}</p>
        <div className="flex items-center gap-2 shrink-0">
          <ViolationBadge count={rule.violation_count ?? 1} />
          <LifecycleBadge rule={rule} />
        </div>
      </div>

      {rule.status === "stuck" && (
        <p className="text-xs text-red-400/80">
          Always loaded but still being violated. This rule needs to be rewritten, escalated to AGENTS.md, or retired.
        </p>
      )}
      {rule.status === "chronic" && (
        <p className="text-xs text-orange-400/80">
          Cycled between active and archived {rule.archive_cycle_count}× — not being retained.
          Consider rewriting for clarity or promoting to AGENTS.md.
        </p>
      )}

      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3 text-xs text-white/30">
          {rule.sessions_checked !== undefined && (
            <span>{rule.sessions_checked} sessions checked</span>
          )}
          {rule.sessions_since_violation !== undefined && (
            <span>· {rule.sessions_since_violation} sessions quiet</span>
          )}
          {rule.last_violated_iso && (
            <span>· violated {timeAgo(rule.last_violated_iso)}</span>
          )}
        </div>
        <div className="flex items-center gap-2">
          <button onClick={() => setExpanded(!expanded)}
            className="text-xs text-white/30 hover:text-white/60 transition-colors">
            {expanded ? "Hide" : "Evidence"}
          </button>
          {(isAlert || rule.status === "permanent") && (
            <button onClick={doRetire} disabled={retiring}
              className="text-xs px-2 py-1 rounded-lg bg-white/5 text-white/30 hover:bg-white/10 transition-colors disabled:opacity-50">
              {retiring ? "Retiring…" : "Retire"}
            </button>
          )}
        </div>
      </div>

      {expanded && (
        <div className="space-y-2">
          {rule.source_instruction && (
            <div className="bg-white/3 rounded-lg px-3 py-2">
              <p className="text-xs text-white/30 mb-1">Source instruction</p>
              <p className="text-xs text-white/55 leading-relaxed">{rule.source_instruction}</p>
            </div>
          )}
          {rule.evidence && (
            <div className="bg-white/3 rounded-lg px-3 py-2">
              <p className="text-xs text-white/30 mb-1">Last violation evidence</p>
              <p className="text-xs text-white/55 leading-relaxed italic">"{rule.evidence}"</p>
            </div>
          )}
        </div>
      )}
    </GlassCard>
  );
}

function RulesHealthTab({ onRetire }: { onRetire: () => void }) {
  const { data: healthData, mutate } = useSWR(
    "improvements/rules-health",
    api.improvements.rulesHealth,
    { refreshInterval: 30000 }
  );
  const h = healthData as any;
  const stats    = h?.stats    ?? {};
  const stuck    = h?.stuck    ?? [] as Rule[];
  const chronic  = h?.chronic  ?? [] as Rule[];
  const permanent= h?.permanent?? [] as Rule[];
  const active   = h?.active   ?? [] as Rule[];
  const archived = h?.archived ?? [] as Rule[];

  const handleRetire = () => { mutate(); onRetire(); };

  const allActive = [...stuck, ...chronic, ...permanent, ...active];

  return (
    <div className="space-y-6">
      {/* Stats */}
      <div className="grid grid-cols-2 lg:grid-cols-5 gap-3">
        <StatCard label="Active"    value={stats.active_count   ?? "—"} />
        <StatCard label="Permanent" value={stats.permanent_count ?? "—"} sub="always loaded" />
        <StatCard label="Stuck"     value={stats.stuck_count    ?? "—"} sub={stats.stuck_count > 0 ? "needs review" : "none"} />
        <StatCard label="Chronic"   value={stats.chronic_count  ?? "—"} sub={stats.chronic_count > 0 ? "cycling" : "none"} />
        <StatCard label="Archived"  value={stats.archived_count ?? "—"} sub="mastered or retired" />
      </div>

      {/* Alerts */}
      {(stuck.length > 0 || chronic.length > 0) && (
        <GlassCard className="p-4 border border-red-500/20 space-y-1">
          <p className="text-xs font-medium text-red-400">
            {stuck.length + chronic.length} rule{stuck.length + chronic.length > 1 ? "s" : ""} need attention
          </p>
          <p className="text-xs text-white/40">
            Stuck rules are permanent but still being violated. Chronic rules have cycled in/out of archive 2+ times.
            Review the evidence and retire or rewrite them.
          </p>
        </GlassCard>
      )}

      {/* Active rules */}
      {allActive.length === 0 ? (
        <GlassCard className="p-10 text-center">
          <p className="text-white/30 text-sm">No active rules</p>
          <p className="text-white/20 text-xs mt-1">Rules appear here after session analysis detects adherence violations.</p>
        </GlassCard>
      ) : (
        <div className="space-y-3">
          <h3 className="text-xs font-medium text-white/40 uppercase tracking-wider">
            Active Rules ({allActive.length})
          </h3>
          {allActive.map((r: Rule, i: number) => (
            <HealthRuleCard key={i} rule={r} index={i} onRetire={handleRetire} />
          ))}
        </div>
      )}

      {/* Archived rules */}
      {archived.length > 0 && (
        <details className="group">
          <summary className="text-xs font-medium text-white/30 uppercase tracking-wider cursor-pointer hover:text-white/50 transition-colors list-none flex items-center gap-2">
            <span className="group-open:rotate-90 transition-transform inline-block">▶</span>
            Archived Rules ({stats.archived_count ?? archived.length})
          </summary>
          <div className="mt-3 space-y-2">
            {archived.map((r: Rule, i: number) => (
              <GlassCard key={i} className="p-4 opacity-60">
                <div className="flex items-start justify-between gap-3">
                  <p className="text-xs text-white/60 leading-snug flex-1">{r.rule}</p>
                  <div className="flex items-center gap-2 shrink-0">
                    <span className="text-xs text-white/20">{r.violation_count}×</span>
                    <LifecycleBadge rule={r} />
                  </div>
                </div>
                {r.archived_at_iso && (
                  <p className="text-xs text-white/20 mt-2">Archived {timeAgo(r.archived_at_iso)}</p>
                )}
              </GlassCard>
            ))}
          </div>
        </details>
      )}
    </div>
  );
}

// ── page ──────────────────────────────────────────────────────────────────────

export default function ImprovementsPage() {
  const [tab, setTab] = useState<"health" | "pending" | "history">("health");

  const { data: statsData, mutate: mutateStats } = useSWR("improvements/stats", api.improvements.stats, { refreshInterval: 30000 });
  const { data: rulesData } = useSWR("improvements/rules", api.improvements.rules, { refreshInterval: 60000 });
  const { data: pendingData, mutate: mutatePending } = useSWR("improvements/pending", api.improvements.pending, { refreshInterval: 15000 });
  const { data: historyData, mutate: mutateHistory } = useSWR("improvements/history", api.improvements.history, { refreshInterval: 30000 });

  const stats    = statsData as any ?? {};
  const rules    = (rulesData as any)?.rules ?? [] as Rule[];
  const pending  = (pendingData as any)?.pending ?? [] as PendingGroup[];
  const history  = (historyData as any)?.history ?? [] as HistoryGroup[];

  const onReview = () => {
    mutatePending();
    mutateHistory();
    mutateStats();
  };

  return (
    <div className="space-y-6 animate-fade-in">
      <div>
        <h1 className="text-2xl font-semibold text-white">Improvements</h1>
        <p className="text-sm text-white/40 mt-0.5">Self-improvement loop — adherence tracking and behavioral candidates</p>
      </div>

      {/* Stats */}
      <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <StatCard label="Rules in Effect" value={stats.rules_count ?? "—"} />
        <StatCard label="Pending Review" value={stats.pending_count ?? "—"} />
        <StatCard label="Applied" value={stats.applied_count ?? "—"} />
        <StatCard
          label="Recurrence Rate"
          value={stats.rules_count ? `${stats.recurrence_rate ?? 0}%` : "—"}
          sub={stats.recurrence_count > 0 ? `${stats.recurrence_count} rule${stats.recurrence_count > 1 ? "s" : ""} re-occurring` : "no re-violations"}
        />
      </div>

      <PageExplainer sections={[
        { heading: "How this works", rows: [
          { label: "Pass 1 — Adherence Scan", meaning: "After every session flush, Conductor scans for moments where existing instructions were ignored or had to be re-stated. Violated rules are automatically promoted to persistent_rules and loaded at session start as hard constraints." },
          { label: "Pass 2 — Net-New Candidates", meaning: "Same analysis identifies genuinely new patterns/preferences not yet documented. Self-validated via constitution + judge gates. Stored here as pending candidates for your review." },
          { label: "Recurrence Rate", meaning: "% of rules that have been violated more than once after promotion. High rate = improvements not sticking. Low rate = rules are holding." },
        ]},
        { heading: "Rules in Effect", rows: [
          { label: "1× — first time", meaning: "Rule was violated once, promoted, not seen again. Working." },
          { label: "2–3× — recurring (amber)", meaning: "Rule was violated again after promotion. May need to be made more prominent in TOOLS.md." },
          { label: "4×+ — recurring (red)", meaning: "Rule is not sticking. Consider restructuring the underlying instruction in TOOLS.md or AGENTS.md." },
        ]},
        { heading: "Candidate Review", rows: [
          { label: "Approve", meaning: "Creates a Workshop task for Conductor to apply the change (edit file, sync to DB, git tag). You'll see it in the Workshop board." },
          { label: "Reject", meaning: "Discards the candidate. Marked rejected in DB." },
          { label: "Approve/Reject individually", meaning: "Use the ✓/✕ buttons per candidate to cherry-pick from a group. Or use 'Approve all'/'Reject all' for the whole batch." },
        ]},
      ]} />

      {/* Tabs */}
      <div className="flex gap-1 p-1 rounded-xl bg-white/5 w-fit">
        {(["health", "pending", "history"] as const).map(t => (
          <button key={t} onClick={() => setTab(t)}
            className={clsx("px-4 py-1.5 rounded-lg text-xs font-medium transition-all", tab === t
              ? "bg-white/12 text-white" : "text-white/40 hover:text-white/70")}>
            {t === "health" ? "Rules Health" : t === "pending" ? "Pending" : "History"}
            {t === "pending" && pending.length > 0 && (
              <span className="ml-1.5 bg-blue-500/30 text-blue-300 text-xs px-1.5 py-0.5 rounded-full">
                {pending.length}
              </span>
            )}
          </button>
        ))}
      </div>

      {/* Rules Health tab */}
      {tab === "health" && <RulesHealthTab onRetire={() => { mutateStats(); }} />}

      {/* Candidates tab */}
      {tab === "pending" && (
        <div className="space-y-4">
          {pending.length === 0 ? (
            <GlassCard className="p-10 text-center">
              <p className="text-white/30 text-sm">No pending candidates</p>
              <p className="text-white/20 text-xs mt-1">Net-new candidates appear here after sessions where new patterns emerge.</p>
            </GlassCard>
          ) : (
            pending.map((g: PendingGroup) => (
              <PendingCard key={g.key} group={g} onReview={onReview} />
            ))
          )}
        </div>
      )}

      {/* History tab */}
      {tab === "history" && (
        <div className="space-y-3">
          {history.length === 0 ? (
            <GlassCard className="p-10 text-center">
              <p className="text-white/30 text-sm">No history yet</p>
            </GlassCard>
          ) : (
            history.map((g: HistoryGroup) => (
              <HistoryCard key={g.key} group={g} />
            ))
          )}
        </div>
      )}
    </div>
  );
}
