"use client";

/**
 * Admin → Platform Analytics → Growth & Retention
 *
 * Monthly growth lines (users / brands / events / sessions) +
 * churn analysis (active / at-risk / churned / lost) + activation
 * funnel + MRR projection (pre-Stripe).
 */

import { useEffect, useState } from "react";
import Link from "next/link";
import {
  TrendingUp, ArrowLeft, Loader2, AlertTriangle, RefreshCw,
  Users as UsersIcon, Globe, Activity, MousePointerClick,
  AlertCircle, CheckCircle2, ArrowDown, DollarSign,
} from "lucide-react";
import {
  PageHeader, SectionHeader, Card, CardHeader, EmptyState, Sparkline, StatCard,
} from "@/components/admin";

interface MonthRow { month: string; count: number }
interface AtRiskUser { id: string; email: string | null; lastSeen: string | null }
interface FunnelStep { step: string; label: string; count: number; pct: number }
interface Payload {
  scope: { generatedAt: string };
  monthly: { users: MonthRow[]; brands: MonthRow[]; events: MonthRow[]; sessions: MonthRow[] };
  churn: { active: number; atRisk: number; churned: number; lost: number; atRiskUsers: AtRiskUser[] };
  funnel: FunnelStep[];
  mrr: { ifAllPaying: number; brandCount: number; assumption: string; growthPerMonth: number };
}

function fmt(n: number): string {
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000)     return `${(n / 1_000).toFixed(1)}k`;
  return n.toLocaleString();
}
function usd(n: number): string {
  if (n >= 1_000_000) return `$${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000)     return `$${(n / 1_000).toFixed(1)}k`;
  return `$${n.toLocaleString()}`;
}
function fmtMonth(s: string): string {
  try {
    const [y, m] = s.split("-");
    return new Date(Number(y), Number(m) - 1, 1).toLocaleDateString(undefined, { month: "short", year: "2-digit" });
  } catch { return s; }
}
function relTime(iso: string | null): string {
  if (!iso) return "—";
  try {
    const d = Math.floor((Date.now() - new Date(iso).getTime()) / 86_400_000);
    return d <= 0 ? "today" : `${d}d ago`;
  } catch { return iso; }
}

export default function GrowthPage() {
  const [data, setData] = useState<Payload | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [retryKey, setRetryKey] = useState(0);

  useEffect(() => {
    setError(null);
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 15_000);
    fetch("/api/admin/analytics/growth", { signal: controller.signal })
      .then(async (r) => {
        if (!r.ok) {
          let msg = `HTTP ${r.status}`;
          try { const body = await r.json(); if (body?.error) msg = `${msg}: ${body.error}`; } catch {}
          throw new Error(msg);
        }
        return r.json() as Promise<Payload>;
      })
      .then(setData)
      .catch((err: Error) => {
        if (err.name === "AbortError") setError("Request timed out after 15s — try Retry.");
        else setError(err.message || "Failed to load growth metrics.");
      })
      .finally(() => clearTimeout(timeoutId));
    return () => { clearTimeout(timeoutId); controller.abort(); };
  }, [retryKey]);

  if (error) {
    return (
      <div className="max-w-2xl mx-auto mt-16">
        <div className="rounded-xl border border-rose-200 bg-rose-50 p-6 text-center">
          <AlertTriangle className="w-8 h-8 text-rose-500 mx-auto mb-2" />
          <h2 className="text-sm font-bold text-slate-900">Couldn&apos;t load Growth</h2>
          <p className="text-xs text-slate-600 mt-1">{error}</p>
          <button
            onClick={() => setRetryKey((k) => k + 1)}
            className="inline-flex items-center gap-1.5 px-3 py-1.5 mt-4 rounded-lg bg-white border border-slate-200 text-xs font-semibold text-slate-700 hover:bg-slate-50"
          >
            <RefreshCw className="w-3 h-3" /> Retry
          </button>
        </div>
      </div>
    );
  }

  if (!data) {
    return <div className="flex items-center justify-center py-24"><Loader2 className="w-5 h-5 text-slate-400 animate-spin" /></div>;
  }

  const churnTotal = data.churn.active + data.churn.atRisk + data.churn.churned + data.churn.lost || 1;
  const maxFunnel = data.funnel[0]?.count || 1;

  // Identify the biggest single drop-off in the activation funnel
  // (gap between consecutive pct values). The UI highlights it
  // with an amber row + a "biggest drop" badge so operators can
  // see where to focus onboarding.
  let biggestDropIndex = -1;
  let biggestDrop = 0;
  for (let i = 1; i < data.funnel.length; i++) {
    const drop = data.funnel[i - 1].pct - data.funnel[i].pct;
    if (drop > biggestDrop) { biggestDrop = drop; biggestDropIndex = i; }
  }

  return (
    <div className="space-y-6">
      <PageHeader
        title="Growth & Retention"
        subtitle={`${data.mrr.brandCount} total brands · ${data.churn.active} active users · MRR potential ${usd(data.mrr.ifAllPaying)}/mo`}
        icon={TrendingUp}
        actions={
          <Link href="/admin/analytics" className="inline-flex items-center gap-1 text-[11px] text-slate-600 hover:text-slate-900">
            <ArrowLeft className="w-3 h-3" />Back to Analytics
          </Link>
        }
      />

      {/* MRR projection — top-of-page hero card */}
      <Card>
        <div className="p-6 grid grid-cols-1 md:grid-cols-3 gap-6 items-center">
          <div className="md:col-span-1">
            <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">MRR potential</p>
            <p className="text-5xl font-bold text-slate-900 tabular-nums leading-tight inline-flex items-baseline gap-1">
              <DollarSign className="w-7 h-7 text-emerald-600" />{fmt(data.mrr.ifAllPaying).replace("$", "")}
            </p>
            <p className="text-[11px] text-slate-500 mt-1 leading-relaxed">{data.mrr.assumption}</p>
          </div>
          <div className="md:col-span-2 grid grid-cols-2 gap-3">
            <div className="bg-slate-50 rounded-lg p-3 border border-slate-100">
              <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">Last 30d brand additions</p>
              <p className="text-2xl font-bold text-slate-900 tabular-nums">+{usd(data.mrr.growthPerMonth)}/mo</p>
              <p className="text-[10px] text-slate-500 mt-0.5">if those brands convert at the same Pro-plan rate</p>
            </div>
            <div className="bg-slate-50 rounded-lg p-3 border border-slate-100">
              <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">Total brands</p>
              <p className="text-2xl font-bold text-slate-900 tabular-nums">{data.mrr.brandCount.toLocaleString()}</p>
              <p className="text-[10px] text-slate-500 mt-0.5">pre-Stripe — switch to actual plan distribution once billing ships</p>
            </div>
          </div>
        </div>
      </Card>

      {/* Monthly growth — 4 sparkline cards */}
      <section>
        <SectionHeader title="Monthly growth" right={<span className="text-[10px] text-slate-400">last 12 months</span>} />
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
          <MonthlyCard icon={UsersIcon} label="New users"    rows={data.monthly.users}    color="#6366F1" />
          <MonthlyCard icon={Globe}     label="New brands"   rows={data.monthly.brands}   color="#10B981" />
          <MonthlyCard icon={Activity}  label="Events / mo"  rows={data.monthly.events}   color="#8B5CF6" />
          <MonthlyCard icon={MousePointerClick} label="Sessions / mo" rows={data.monthly.sessions} color="#3B82F6" />
        </div>
      </section>

      {/* Churn analysis */}
      <section>
        <SectionHeader title="Churn analysis" right={<span className="text-[10px] text-slate-400">based on PlatformEvent recency</span>} />
        <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-3">
          <ChurnCard label="Active"   sub="≤ 30 days" count={data.churn.active}   total={churnTotal} color="bg-emerald-500" textColor="text-emerald-600" />
          <ChurnCard label="At risk"  sub="30-60 days" count={data.churn.atRisk}   total={churnTotal} color="bg-amber-500"   textColor="text-amber-600" />
          <ChurnCard label="Churned"  sub="60-90 days" count={data.churn.churned}  total={churnTotal} color="bg-orange-500"  textColor="text-orange-600" />
          <ChurnCard label="Lost"     sub="90+ days"   count={data.churn.lost}     total={churnTotal} color="bg-rose-500"    textColor="text-rose-600" />
        </div>
        {data.churn.atRiskUsers.length > 0 && (
          <Card>
            <CardHeader title="At-risk users" right={<span className="text-[10px] text-slate-400">{data.churn.atRiskUsers.length} listed</span>} />
            <table className="w-full text-xs">
              <thead className="text-[10px] font-bold uppercase tracking-widest text-slate-400 border-b border-slate-100 bg-slate-50/40">
                <tr>
                  <th className="text-left px-4 py-2">User</th>
                  <th className="text-right px-4 py-2">Last activity</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-100">
                {data.churn.atRiskUsers.map((u) => (
                  <tr key={u.id}>
                    <td className="px-4 py-2 text-slate-800 truncate">{u.email ?? <span className="font-mono text-[10px] text-slate-500">{u.id.slice(0, 12)}…</span>}</td>
                    <td className="px-4 py-2 text-right text-[11px] text-slate-500">{relTime(u.lastSeen)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </Card>
        )}
      </section>

      {/* Activation funnel */}
      <section>
        <SectionHeader title="Activation funnel"
          right={biggestDropIndex >= 0 && biggestDrop > 0
            ? <span className="text-[10px] text-amber-700 font-semibold">Biggest drop: −{biggestDrop.toFixed(1)}% at {data.funnel[biggestDropIndex].label}</span>
            : undefined}
        />
        <Card>
          {data.funnel.length === 0 ? (
            <EmptyState icon={CheckCircle2} title="No funnel data yet" description="Steps populate as brands sign up + complete onboarding." />
          ) : (
            <div className="divide-y divide-slate-100">
              {data.funnel.map((s, i) => {
                const widthPct = (s.count / maxFunnel) * 100;
                const isDrop = i === biggestDropIndex;
                return (
                  <div key={s.step} className={`px-5 py-3 ${isDrop ? "bg-amber-50/40" : ""}`}>
                    <div className="flex items-center gap-3 mb-1.5">
                      {isDrop ? (
                        <ArrowDown className="w-3.5 h-3.5 text-amber-600 shrink-0" />
                      ) : (
                        <CheckCircle2 className={`w-3.5 h-3.5 shrink-0 ${i === 0 ? "text-emerald-600" : "text-slate-400"}`} />
                      )}
                      <span className="text-xs font-semibold text-slate-800 flex-1">{s.label}</span>
                      <span className="text-[10px] text-slate-500 tabular-nums">{s.count.toLocaleString()} brands</span>
                      <span className="text-xs font-bold text-slate-900 tabular-nums w-12 text-right">{s.pct}%</span>
                    </div>
                    <div className="h-2 bg-slate-100 rounded-full overflow-hidden">
                      <div className={`h-full rounded-full ${isDrop ? "bg-amber-500" : "bg-emerald-500"}`} style={{ width: `${Math.max(widthPct, 1)}%` }} />
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </Card>
      </section>
    </div>
  );
}

function MonthlyCard({
  icon: Icon, label, rows, color,
}: {
  icon: typeof UsersIcon;
  label: string;
  rows: MonthRow[];
  color: string;
}) {
  const total = rows.reduce((s, r) => s + r.count, 0);
  const last = rows[rows.length - 1]?.count ?? 0;
  const prev = rows[rows.length - 2]?.count ?? 0;
  const trend = prev > 0 ? Math.round(((last - prev) / prev) * 1000) / 10 : 0;
  return (
    <StatCard
      label={label}
      value={fmt(total)}
      icon={Icon}
      variant="compact"
      sparkline={rows.map((r) => r.count)}
      trendPct={trend}
      color={color}
      hint={`${fmtMonth(rows[0]?.month ?? "")} → ${fmtMonth(rows[rows.length - 1]?.month ?? "")}`}
    />
  );
}

function ChurnCard({
  label, sub, count, total, color, textColor,
}: {
  label: string;
  sub: string;
  count: number;
  total: number;
  color: string;
  textColor: string;
}) {
  const pct = total > 0 ? Math.round((count / total) * 100) : 0;
  return (
    <Card>
      <div className="p-4">
        <div className="flex items-center justify-between mb-1">
          <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">{label}</p>
          <span className="text-[10px] text-slate-400">{sub}</span>
        </div>
        <p className={`text-3xl font-bold tabular-nums ${textColor}`}>{count.toLocaleString()}</p>
        <div className="h-1.5 bg-slate-100 rounded-full overflow-hidden mt-2">
          <div className={`h-full rounded-full ${color}`} style={{ width: `${pct}%` }} />
        </div>
        <p className="text-[10px] text-slate-500 mt-1 tabular-nums">{pct}% of users</p>
      </div>
    </Card>
  );
}

// Reference an unused icon import that future copy mentions to
// keep tree-shaking happy without a separate import update.
void AlertCircle;
