"use client";

/**
 * Admin Dashboard — premium operations-center surface.
 * Six-card hero KPI row + brand-filterable Platform Metrics grid +
 * full-width activity area chart + Top Brands + Recent Activity.
 *
 * Built on the shared admin design system (src/components/admin/*)
 * so visual tweaks land in one place.
 */

import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react";
import Link from "next/link";
import {
  Building2, Globe, Users, Sparkles, DollarSign, Activity,
  MousePointerClick, Eye, Phone, FileInput, ExternalLink, Percent,
  TrendingUp, Loader2, Gauge, RefreshCw, CalendarCheck,
  BarChart3, Search, Tag, AlertCircle, Clock, ArrowRight,
} from "lucide-react";
import {
  PageHeader, SectionHeader, StatCard, Card, CardHeader, Sparkline,
  StatCardSkeleton, Avatar,
} from "@/components/admin";

interface Overview {
  totalOrgs: number; totalBrands: number; totalUsers: number;
  activeBrands: number;
  ai: { today: number; week: number; month: number };
  estimatedCostMonth: number;
  integrations: { gsc: number; ga4: number; gbpLocations: number };
  siteTags: number;
  trackingCoverage?: {
    windowDays: number;
    totalDistinctTypes: number;
    activeCategories: number;
    totalCategories: number;
    categories: Array<{
      key: string;
      label: string;
      total: number;
      active: boolean;
      activeTypes: string[];
    }>;
  };
}

interface BrandOption { id: string; name: string; domain: string }

interface MetricSeries {
  current: number;
  previous: number;
  trendPct: number | null;
  timeseries: Array<{ date: string; value: number }>;
  /** Conversion metrics only: raw row count (pre-dedup). When > current
   *  the MetricCard renders a "X interactions" subtitle below the
   *  headline number. Absent for non-conversion metrics. */
  interactions?: number;
  previousInteractions?: number;
}

interface MetricsPayload {
  scope: string;
  range: string;
  windowDays: number;
  // ── New triple-source shape (Apr-2026) ──
  // The dashboard now reads from siteTag / ga4 / gsc / comparison so
  // brands can see all three sources side-by-side. The legacy
  // `metrics` field is kept for the conversion-rate breakdown card
  // and any consumer that hasn't migrated yet.
  siteTag?: {
    connected: boolean;
    pageViews: MetricSeries;
    sessions: MetricSeries;
    conversions: MetricSeries;
    conversionRate: MetricSeries;
    formStarts: MetricSeries;
    formSubmits: MetricSeries;
    bookings: MetricSeries;
    phoneCalls: MetricSeries;
    outboundClicks: MetricSeries;
    impressions: MetricSeries;
  };
  ga4?: {
    connected: boolean;
    sessions: MetricSeries;
    users: MetricSeries;
    newUsers: MetricSeries;
    pageviews: MetricSeries;
    conversions: MetricSeries;
    revenue: MetricSeries;
    bounceRate: MetricSeries;
    avgSessionSec: MetricSeries;
    pagesPerSession: MetricSeries;
    conversionRate: MetricSeries;
  };
  gsc?: {
    connected: boolean;
    clicks: MetricSeries;
    impressions: MetricSeries;
    avgPosition: MetricSeries;
    avgCtr: MetricSeries;
    topQueries: Array<{ query: string; clicks: number; impressions: number; position: number; ctr: number }>;
    topPages: Array<{ pageUrl: string; clicks: number; impressions: number; position: number; ctr: number }>;
  };
  comparison?: {
    sessionDelta: number | null;
    conversionDelta: number | null;
    /** Site Tag / GA4 unique-session + hard-conversion capture rate
     *  over the OVERLAP window. 100 = equal capture; >100 = Site Tag
     *  catching MORE than GA4 (expected when gtag interception +
     *  plugin paths are active). */
    sessionCaptureRate: number | null;
    conversionCaptureRate: number | null;
    siteTagSessions: number;
    ga4Sessions: number;
    siteTagConversions: number;
    ga4Conversions: number;
    /** Per-day rates computed over the effective window. Surfaced so
     *  the UI can render "2,529/day vs 3,680/day" subtitles without
     *  re-deriving from the range. */
    siteTagSessionsPerDay: number;
    ga4SessionsPerDay: number;
    siteTagConversionsPerDay: number;
    ga4ConversionsPerDay: number;
    /** Effective overlap window — max(rangeStart, installedAt) → now.
     *  partialOverlap = true when the Site Tag wasn't yet installed
     *  at the rangeStart (UI renders an install-date caveat). */
    effectiveFrom: string;
    effectiveTo: string;
    effectiveDays: number;
    installedAt: string | null;
    partialOverlap: boolean;
    fullComparisonAvailableAt: string | null;
  };
  metrics: {
    totalClicks: MetricSeries;
    impressions: MetricSeries;
    pageViews: MetricSeries;
    sessions: MetricSeries;
    conversions: MetricSeries;
    formSubmits: MetricSeries;
    formStarts: MetricSeries;
    bookings: MetricSeries;
    /** DEPRECATED — alias of formSubmits, kept for backwards compat */
    formFills: MetricSeries;
    phoneCalls: MetricSeries;
    outboundClicks: MetricSeries;
    conversionRate: MetricSeries;
  };
  topBrands: Array<{
    brandId: string; brandName: string; brandDomain: string;
    events: number; sessions: number; conversions: number; conversionRate: number;
  }>;
}

interface ActivityRow {
  id: string;
  action: string;
  category: string;
  timestamp: string;
  user: { id: string; name: string | null; email: string | null; image: string | null } | null;
  brand: { id: string; name: string | null; domain: string | null } | null;
}

type Range = "today" | "7d" | "28d" | "30d" | "90d" | "all";
// 28d is the default (matching the app dashboard). 30d is kept as
// a distinct option for operators who specifically want a calendar-
// month-ish window; the trade-off between the two is the cross-
// surface consistency vs the calendar convenience.
const RANGES: Array<{ id: Range; label: string }> = [
  { id: "today", label: "Today" },
  { id: "7d",    label: "7d" },
  { id: "28d",   label: "28d" },
  { id: "30d",   label: "30d" },
  { id: "90d",   label: "90d" },
  { id: "all",   label: "All" },
];

// Per-category accent for the activity feed left dot.
const CATEGORY_COLOR: Record<string, string> = {
  navigation:  "bg-blue-400",
  search:      "bg-cyan-400",
  audit:       "bg-orange-400",
  report:      "bg-violet-400",
  integration: "bg-sky-400",
  content:     "bg-emerald-400",
  ai:          "bg-purple-400",
  export:      "bg-amber-400",
  settings:    "bg-slate-400",
  auth:        "bg-indigo-400",
  admin:       "bg-rose-400",
};

function formatNumber(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 formatRelative(iso: string): string {
  try {
    const sec = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);
    if (sec < 60) return `${sec}s ago`;
    if (sec < 3600) return `${Math.floor(sec / 60)}m ago`;
    if (sec < 86_400) return `${Math.floor(sec / 3600)}h ago`;
    return `${Math.floor(sec / 86_400)}d ago`;
  } catch { return ""; }
}

export default function AdminOverview() {
  const [overview, setOverview] = useState<Overview | null>(null);
  const [brands, setBrands] = useState<BrandOption[]>([]);
  const [scope, setScope] = useState<string>("all");
  const [range, setRange] = useState<Range>("28d");
  const [metrics, setMetrics] = useState<MetricsPayload | null>(null);
  const [activity, setActivity] = useState<ActivityRow[]>([]);
  const [metricsLoading, setMetricsLoading] = useState(false);

  // Mount-once fetches: overview + brand list + recent activity.
  useEffect(() => {
    fetch("/api/admin/overview").then((r) => r.ok ? r.json() : null).then(setOverview).catch(() => {});
    fetch("/api/admin/brands?limit=200")
      .then((r) => r.ok ? r.json() : null)
      .then((d) => {
        if (Array.isArray(d?.brands)) {
          setBrands(d.brands.map((b: { id: string; name: string; domain: string }) => ({
            id: b.id, name: b.name, domain: b.domain,
          })));
        }
      })
      .catch(() => {});
    fetch("/api/admin/activity?limit=8")
      .then((r) => r.ok ? r.json() : null)
      .then((d) => setActivity(d?.rows ?? []))
      .catch(() => {});
  }, []);

  // Re-fetch on scope/range change. Clear stale metrics immediately so
  // old values don't flash through the new fetch window.
  const loadMetrics = useCallback(async () => {
    setMetrics(null);
    setMetricsLoading(true);
    try {
      const r = await fetch(`/api/admin/platform-metrics?brandId=${encodeURIComponent(scope)}&range=${range}`);
      if (r.ok) setMetrics(await r.json());
    } finally { setMetricsLoading(false); }
  }, [scope, range]);
  useEffect(() => { loadMetrics(); }, [loadMetrics]);

  // Previously the entire page was opacity-0 until the overview
  // fetch resolved — a 20-30s blank page on cold loads because the
  // overview endpoint runs tracking-coverage queries that hit
  // TrackedEvent + SiteEvent (millions of rows). Now the page
  // renders its layout + skeletons immediately and fills sections
  // as each fetch resolves. The opacity transition only applies to
  // individual cards, not the full page wrapper.
  const fadeClass = "opacity-100";

  // Hero KPI sparklines come from a synthesized 30-point flat-ish
  // series — the overview endpoint doesn't ship per-day deltas yet,
  // so we draw a subtle backdrop using the headline number scaled.
  // Better: extend /api/admin/overview to return 30d series per
  // heroSpark used to generate a synthetic sine-wave behind each
  // hero KPI card. Removed Apr-2026 because (a) the numbers on
  // those cards are static/slow-changing (Organizations=1,
  // Users=3, Brands=5 — a trend line on those is meaningless), and
  // (b) the generated waveform made the actual numbers hard to
  // read. The platform-metrics cards below STILL get real
  // sparklines from their per-day timeseries — those have genuine
  // shape and benefit from the visualisation.

  return (
    <div className={`space-y-8 max-w-7xl transition-opacity duration-200 ${fadeClass}`}>
      <PageHeader
        title="Admin Overview"
        subtitle="Platform health, engagement, and the people building on top of meSEO."
        icon={Activity}
        actions={
          <Link
            href="/admin/health"
            className="inline-flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 bg-white text-xs font-semibold text-slate-700 hover:bg-slate-50"
          >
            <Gauge className="w-3.5 h-3.5" /> System Health
          </Link>
        }
      />

      {/* HERO KPI ROW — six clean stat cards, no sparklines.
          These are slow-changing / static counts — a trend line
          would be meaningless noise behind the headline number.
          The platform-metrics cards below carry the real time-
          series + sparklines. */}
      <section>
        <SectionHeader title="At a glance" />
        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3">
          {!overview ? (
            Array.from({ length: 6 }).map((_, i) => <StatCardSkeleton key={i} />)
          ) : (
            <>
              <StatCard
                label="Organizations"
                value={formatNumber(overview.totalOrgs)}
                icon={Building2}
                variant="compact"
                color="#6366F1"
              />
              <StatCard
                label="Brands"
                value={formatNumber(overview.totalBrands)}
                icon={Globe}
                variant="compact"
                color="#10B981"
              />
              <StatCard
                label="Active 7d"
                value={formatNumber(overview.activeBrands)}
                icon={Activity}
                variant="compact"
                valueClass="text-emerald-600"
                color="#10B981"
              />
              <StatCard
                label="Users"
                value={formatNumber(overview.totalUsers)}
                icon={Users}
                variant="compact"
                color="#3B82F6"
              />
              <StatCard
                label="AI Calls 30d"
                value={formatNumber(overview.ai.month)}
                icon={Sparkles}
                variant="compact"
                valueClass="text-violet-600"
                color="#8B5CF6"
              />
              <StatCard
                label="AI Cost 30d"
                value={`$${overview.estimatedCostMonth}`}
                icon={DollarSign}
                variant="compact"
                valueClass="text-amber-600"
                color="#F59E0B"
              />
            </>
          )}
        </div>
      </section>

      {/* TRACKING COVERAGE — ten-category grid showing which Site
          Tag surfaces are firing platform-wide over the last 7
          days. Green dot = at least one event in that category
          landed on TrackedEvent; grey = no coverage. Operator-
          focused view so platform-wide coverage gaps are visible
          at a glance without drilling into an individual brand. */}
      {overview?.trackingCoverage && (
        <section>
          <SectionHeader title="Tracking Coverage" />
          <TrackingCoverageCard coverage={overview.trackingCoverage} />
        </section>
      )}

      {/* PLATFORM METRICS — brand-filtered + range-bound. Three
          data-source sections (Site Tag / GA4 / GSC) share a single
          brand + range filter at the top so a user can flip between
          "what our first-party tag captured" / "what GA4 saw" / "what
          Google indexed" with one toggle. */}
      <section>
        <SectionHeader
          title="Platform Metrics"
          right={
            <div className="flex items-center gap-2">
              <select
                value={scope}
                onChange={(e) => setScope(e.target.value)}
                className="px-3 py-1.5 text-xs bg-white border border-slate-200 rounded-lg min-w-[180px]"
              >
                <option value="all">All brands</option>
                {brands.map((b) => (<option key={b.id} value={b.id}>{b.name}</option>))}
              </select>
              <div className="inline-flex bg-slate-100 rounded-lg p-0.5">
                {RANGES.map((r) => (
                  <button
                    key={r.id}
                    onClick={() => setRange(r.id)}
                    className={`px-2.5 py-1 text-[11px] font-semibold rounded-md transition-colors ${
                      range === r.id ? "bg-white text-slate-900 shadow-sm" : "text-slate-500 hover:text-slate-700"
                    }`}
                  >{r.label}</button>
                ))}
              </div>
            </div>
          }
        />

        {(metricsLoading || !metrics) ? (
          <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
            {Array.from({ length: 8 }).map((_, i) => <StatCardSkeleton key={i} />)}
          </div>
        ) : !metrics ? null : (
          <div className="space-y-6">

            {/* === SITE TAG (FIRST-PARTY) === */}
            <div className="space-y-3">
              <SourceHeader
                icon={Tag}
                title="Site Tag Data"
                subtitle="First-party"
                color="text-emerald-600"
                bgColor="bg-emerald-50"
                borderColor="border-emerald-200"
                connected={metrics.siteTag?.connected ?? true}
              />
              {/* Row 1: top-of-funnel */}
              <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                <MetricCard label="Page Views"   icon={Eye}        metric={metrics.siteTag?.pageViews ?? metrics.metrics.pageViews}     color="#3B82F6" />
                <MetricCard label="Sessions"     icon={Users}      metric={metrics.siteTag?.sessions ?? metrics.metrics.sessions}       color="#6366F1" />
                <MetricCard label="Conversions"  icon={TrendingUp} metric={metrics.siteTag?.conversions ?? metrics.metrics.conversions} color="#10B981" valueClass="text-emerald-600" />
                <MetricCard label="Conv Rate"    icon={Percent}    metric={metrics.siteTag?.conversionRate ?? metrics.metrics.conversionRate} color="#8B5CF6" valueClass="text-violet-600" format="percent" />
              </div>
              {/* Row 2: engagement actions */}
              <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                <MetricCard label="Form Starts"     icon={FileInput}     metric={metrics.siteTag?.formStarts ?? metrics.metrics.formStarts}    color="#A855F7" />
                <MetricCard label="Form Submits"    icon={FileInput}     metric={metrics.siteTag?.formSubmits ?? metrics.metrics.formSubmits}  color="#EC4899" />
                <MetricCard label="Bookings"        icon={CalendarCheck} metric={metrics.siteTag?.bookings ?? metrics.metrics.bookings}        color="#10B981" valueClass="text-emerald-600" />
                <MetricCard label="Phone Calls"     icon={Phone}         metric={metrics.siteTag?.phoneCalls ?? metrics.metrics.phoneCalls}    color="#F59E0B" />
              </div>
              {/* Row 3: secondary */}
              <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                <MetricCard label="Outbound Clicks" icon={ExternalLink}      metric={metrics.siteTag?.outboundClicks ?? metrics.metrics.outboundClicks} color="#06B6D4" />
                <MetricCard label="Impressions"     icon={MousePointerClick} metric={metrics.siteTag?.impressions ?? metrics.metrics.impressions}       color="#64748B" />
              </div>
            </div>

            {/* === GA4 === */}
            <div className="space-y-3">
              <SourceHeader
                icon={BarChart3}
                title="GA4 Data"
                subtitle="Google Analytics"
                color="text-blue-600"
                bgColor="bg-blue-50"
                borderColor="border-blue-200"
                connected={metrics.ga4?.connected ?? false}
              />
              {metrics.ga4?.connected ? (
                <>
                  <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                    <MetricCard label="Sessions"    icon={Users}      metric={metrics.ga4.sessions}    color="#3B82F6" />
                    <MetricCard label="Users"       icon={Users}      metric={metrics.ga4.users}       color="#6366F1" />
                    <MetricCard label="Bounce Rate" icon={ArrowRight} metric={metrics.ga4.bounceRate}  color="#F59E0B" format="percent" />
                    <MetricCard label="Conv Rate"   icon={Percent}    metric={metrics.ga4.conversionRate} color="#8B5CF6" valueClass="text-violet-600" format="percent" />
                  </div>
                  <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                    <MetricCard label="Conversions"  icon={TrendingUp}        metric={metrics.ga4.conversions}     color="#10B981" valueClass="text-emerald-600" />
                    <MetricCard label="Revenue"      icon={DollarSign}        metric={metrics.ga4.revenue}         color="#10B981" />
                    <MetricCard label="Avg Sess (s)" icon={Clock}             metric={metrics.ga4.avgSessionSec}   color="#64748B" />
                    <MetricCard label="Pages/Sess"   icon={MousePointerClick} metric={metrics.ga4.pagesPerSession} color="#64748B" />
                  </div>
                </>
              ) : (
                <NotConnectedState
                  source="GA4"
                  scope={scope}
                  helpHref="/settings/integrations"
                  hint="Connect GA4 in Settings → Integrations to see Google's view of sessions, conversions, and revenue alongside the Site Tag."
                />
              )}
            </div>

            {/* === GSC === */}
            <div className="space-y-3">
              <SourceHeader
                icon={Search}
                title="GSC Data"
                subtitle="Google Search Console"
                color="text-amber-600"
                bgColor="bg-amber-50"
                borderColor="border-amber-200"
                connected={metrics.gsc?.connected ?? false}
              />
              {metrics.gsc?.connected ? (
                <>
                  <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                    <MetricCard label="Clicks"       icon={MousePointerClick} metric={metrics.gsc.clicks}       color="#F59E0B" />
                    <MetricCard label="Impressions"  icon={Eye}               metric={metrics.gsc.impressions}  color="#64748B" />
                    <MetricCard label="Avg Position" icon={TrendingUp}        metric={metrics.gsc.avgPosition}  color="#8B5CF6" />
                    <MetricCard label="Avg CTR"      icon={Percent}           metric={metrics.gsc.avgCtr}       color="#10B981" format="percent" />
                  </div>
                  <div className="grid grid-cols-1 lg:grid-cols-2 gap-3">
                    <GscTopList
                      title="Top queries"
                      rows={(metrics.gsc.topQueries ?? []).map((q) => ({ label: q.query, clicks: q.clicks, impressions: q.impressions, position: q.position }))}
                    />
                    <GscTopList
                      title="Top pages"
                      rows={(metrics.gsc.topPages ?? []).map((p) => ({ label: extractPath(p.pageUrl), clicks: p.clicks, impressions: p.impressions, position: p.position }))}
                    />
                  </div>
                </>
              ) : (
                <NotConnectedState
                  source="GSC"
                  scope={scope}
                  helpHref="/settings/integrations"
                  hint="Connect GSC in Settings → Integrations to see Google's organic clicks, impressions, and ranking position."
                />
              )}
            </div>

            {/* === COMPARISON === */}
            {metrics.comparison && metrics.ga4?.connected && (
              <div className="space-y-3">
                <SourceHeader
                  icon={AlertCircle}
                  title="Site Tag vs GA4 Reconciliation"
                  subtitle={formatEffectiveWindow(metrics.comparison)}
                  color="text-slate-600"
                  bgColor="bg-slate-50"
                  borderColor="border-slate-200"
                />
                {/* Install-date caveat — only renders on a partial
                    overlap. "Site Tag has been active for 6 days.
                    Full 30-day comparison available after YYYY-MM-DD." */}
                {metrics.comparison.partialOverlap && metrics.comparison.installedAt && (
                  <div className="rounded-lg border border-amber-200 bg-amber-50/60 px-4 py-2.5 flex items-start gap-2.5">
                    <AlertCircle className="w-3.5 h-3.5 text-amber-600 shrink-0 mt-0.5" />
                    <p className="text-[11px] text-amber-800 leading-relaxed">
                      Site Tag has been active for <span className="font-semibold">{metrics.comparison.effectiveDays} day{metrics.comparison.effectiveDays === 1 ? "" : "s"}</span>.
                      {metrics.comparison.fullComparisonAvailableAt && (
                        <> Full {metrics.windowDays}-day comparison available after <span className="font-semibold">{new Date(metrics.comparison.fullComparisonAvailableAt).toLocaleDateString()}</span>.</>
                      )}
                      {" "}Comparison below uses the overlap window only so both sides cover the same days.
                    </p>
                  </div>
                )}
                <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                  <ComparisonCard
                    label="Sessions"
                    siteTag={metrics.comparison.siteTagSessions}
                    ga4={metrics.comparison.ga4Sessions}
                    delta={metrics.comparison.sessionDelta}
                    captureRate={metrics.comparison.sessionCaptureRate}
                    siteTagPerDay={metrics.comparison.siteTagSessionsPerDay}
                    ga4PerDay={metrics.comparison.ga4SessionsPerDay}
                  />
                  <ComparisonCard
                    label="Conversions"
                    siteTag={metrics.comparison.siteTagConversions}
                    ga4={metrics.comparison.ga4Conversions}
                    delta={metrics.comparison.conversionDelta}
                    captureRate={metrics.comparison.conversionCaptureRate}
                    siteTagPerDay={metrics.comparison.siteTagConversionsPerDay}
                    ga4PerDay={metrics.comparison.ga4ConversionsPerDay}
                    higherIsBetter
                  />
                </div>
              </div>
            )}

            {/* === CONVERSION RECONCILIATION ===
                Per-conversion-type Site Tag vs GA4 capture-rate
                breakdown. Single-brand only (GA4 query needs a
                brand-scoped GA4 property + OAuth credentials). Renders
                when a specific brand is selected AND that brand has
                GA4 connected. */}
            {scope !== "all" && metrics.ga4?.connected && (
              <ConversionReconciliationCard
                brandId={scope}
                range={range as "today" | "7d" | "28d" | "30d" | "90d"}
              />
            )}
          </div>
        )}
      </section>

      {/* PLATFORM ACTIVITY — full-width area chart */}
      {metrics && (
        <section>
          <SectionHeader
            title="Platform Activity"
            right={<span className="text-xs text-slate-500">Page views + sessions, last {metrics.windowDays} days</span>}
          />
          <Card>
            <div className="p-5">
              <ActivityChart
                pageViews={metrics.metrics?.pageViews?.timeseries ?? metrics.siteTag?.pageViews?.timeseries ?? []}
                sessions={metrics.metrics?.sessions?.timeseries ?? metrics.siteTag?.sessions?.timeseries ?? []}
              />
            </div>
          </Card>
        </section>
      )}

      {/* TOP BRANDS + RECENT ACTIVITY — two-column row */}
      <div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
        {/* Top brands (lg:col-span-3) */}
        {scope === "all" && metrics && (metrics.topBrands?.length ?? 0) > 0 && (
          <Card className="lg:col-span-3">
            <CardHeader
              title="Top brands by activity"
              icon={TrendingUp}
              right={<span className="text-[10px] text-slate-400 uppercase tracking-widest">Last {metrics.windowDays}d</span>}
            />
            <table className="w-full text-sm">
              <thead className="bg-slate-50 border-b border-slate-100">
                <tr className="text-[10px] font-semibold text-slate-500 uppercase tracking-wider">
                  <th className="text-left px-4 py-2.5">Brand</th>
                  <th className="text-right px-3 py-2.5">Events</th>
                  <th className="text-right px-3 py-2.5">Sessions</th>
                  <th className="text-right px-3 py-2.5">Conversions</th>
                  <th className="text-right px-3 py-2.5">Conv Rate</th>
                  <th className="text-right px-4 py-2.5">Confidence</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-100">
                {(metrics.topBrands ?? []).map((b) => (
                  <tr key={b.brandId} className="hover:bg-slate-50">
                    <td className="px-4 py-2.5">
                      <Link href={`/admin/brands?q=${encodeURIComponent(b.brandDomain)}`} className="text-xs font-semibold text-slate-800 hover:text-brand-600 truncate block max-w-[240px]">
                        {b.brandName}
                      </Link>
                      <p className="text-[10px] text-slate-500 font-mono truncate max-w-[240px]">{b.brandDomain}</p>
                    </td>
                    <td className="px-3 py-2.5 text-right text-xs text-slate-700 tabular-nums">{formatNumber(b.events)}</td>
                    <td className="px-3 py-2.5 text-right text-xs text-slate-700 tabular-nums">{formatNumber(b.sessions)}</td>
                    <td className="px-3 py-2.5 text-right text-xs text-slate-700 tabular-nums">{formatNumber(b.conversions)}</td>
                    <td className="px-3 py-2.5 text-right text-xs font-semibold text-violet-600 tabular-nums">{b.conversionRate}%</td>
                    <td className="px-4 py-2.5 text-right">
                      <BrandConfidenceCell brandId={b.brandId} range={range} />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </Card>
        )}

        {/* Recent activity (lg:col-span-2) */}
        <Card className="lg:col-span-2">
          <CardHeader
            title="Recent activity"
            icon={RefreshCw}
            right={
              <Link href="/admin/activity" className="text-xs font-semibold text-brand-600 hover:underline">
                View all →
              </Link>
            }
          />
          {activity.length === 0 ? (
            <div className="p-8 text-center text-xs text-slate-400 italic">
              No telemetry events yet.
            </div>
          ) : (
            <ul className="divide-y divide-slate-100">
              {activity.slice(0, 8).map((a) => (
                <li key={a.id} className="px-4 py-2.5 flex items-center gap-2.5">
                  <span className={`w-1.5 h-1.5 rounded-full shrink-0 ${CATEGORY_COLOR[a.category] ?? "bg-slate-300"}`} />
                  <Avatar src={a.user?.image} name={a.user?.name ?? a.user?.email ?? "?"} size={20} />
                  <div className="min-w-0 flex-1">
                    <p className="text-xs text-slate-700 truncate">
                      <span className="font-semibold">{a.user?.name ?? a.user?.email ?? "system"}</span>{" "}
                      <span className="text-slate-500">{a.action}</span>
                    </p>
                    {a.brand?.name && <p className="text-[10px] text-slate-400 truncate">{a.brand.name}</p>}
                  </div>
                  <span className="text-[10px] text-slate-400 tabular-nums shrink-0">{formatRelative(a.timestamp)}</span>
                </li>
              ))}
            </ul>
          )}
        </Card>
      </div>
    </div>
  );
}

// ─── Source section header ────────────────────────────────────────
//
// Each Platform Metrics subsection (Site Tag / GA4 / GSC / Comparison)
// gets a banner row with an icon chip, source name, subtitle, and a
// connection-status pill. Visually mirrors the SectionHeader but adds
// the icon chip + the colour-coded status so a single-glance scan
// tells the operator which sources are live.

function SourceHeader({
  icon: Icon,
  title,
  subtitle,
  color,
  bgColor,
  borderColor,
  connected,
}: {
  icon: typeof Eye;
  title: string;
  subtitle: string;
  color: string;
  bgColor: string;
  borderColor: string;
  connected?: boolean;
}) {
  return (
    <div className="flex items-center gap-2 pt-2">
      <span className={`w-7 h-7 rounded-lg ${bgColor} ${color} flex items-center justify-center shrink-0 border ${borderColor}`}>
        <Icon className="w-3.5 h-3.5" />
      </span>
      <div className="flex items-baseline gap-2">
        <h3 className="text-xs font-bold uppercase tracking-widest text-slate-700">{title}</h3>
        <span className="text-[10px] text-slate-400">{subtitle}</span>
      </div>
      {connected != null && (
        <span className={`ml-auto text-[10px] font-bold uppercase tracking-widest px-2 py-0.5 rounded-full border ${
          connected
            ? "bg-emerald-50 text-emerald-700 border-emerald-200"
            : "bg-slate-100 text-slate-500 border-slate-200"
        }`}>
          {connected ? "Connected" : "Not connected"}
        </span>
      )}
    </div>
  );
}

// ─── Empty state for unconnected sources ──────────────────────────
//
// Rendered in place of metric cards when GA4 / GSC isn't connected
// for the selected scope. Single-brand: prompts the operator to wire
// up that brand's integration. All-brands: explains the section is
// empty because no brand has the source connected yet.
function NotConnectedState({
  source,
  scope,
  helpHref,
  hint,
}: {
  source: string;
  scope: string;
  helpHref: string;
  hint: string;
}) {
  const isAllBrands = scope === "all";
  return (
    <div className="rounded-xl border border-dashed border-slate-300 bg-slate-50/40 px-5 py-6 text-center">
      <p className="text-xs font-bold uppercase tracking-widest text-slate-500 mb-1">
        {isAllBrands
          ? `No brands have ${source} connected yet`
          : `${source} not connected for this brand`}
      </p>
      <p className="text-[11px] text-slate-500 max-w-xl mx-auto leading-relaxed">{hint}</p>
      {!isAllBrands && (
        <Link
          href={helpHref}
          className="inline-flex items-center gap-1 mt-3 text-[11px] font-semibold text-blue-600 hover:text-blue-700"
        >
          Connect {source} <ArrowRight className="w-3 h-3" />
        </Link>
      )}
    </div>
  );
}

// ─── GSC top-N list ──────────────────────────────────────────────
//
// Mini table with up to 5 rows of (label, clicks, impressions,
// position). Used for Top Queries + Top Pages on the GSC section.

function GscTopList({ title, rows }: {
  title: string;
  rows: Array<{ label: string; clicks: number; impressions: number; position: number }>;
}) {
  return (
    <Card>
      <CardHeader title={title} />
      {rows.length === 0 ? (
        <div className="px-4 py-6 text-center text-[11px] text-slate-400">No data in window.</div>
      ) : (
        <table className="w-full text-xs">
          <thead className="text-[10px] font-semibold uppercase tracking-widest text-slate-400 border-b border-slate-100">
            <tr>
              <th className="text-left px-4 py-2">Item</th>
              <th className="text-right px-4 py-2">Clicks</th>
              <th className="text-right px-4 py-2">Impr.</th>
              <th className="text-right px-4 py-2">Pos.</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-slate-100">
            {rows.map((r) => (
              <tr key={r.label}>
                <td className="px-4 py-2 truncate max-w-[260px] text-slate-800 font-medium">{r.label}</td>
                <td className="px-4 py-2 text-right tabular-nums font-semibold text-slate-900">{r.clicks.toLocaleString()}</td>
                <td className="px-4 py-2 text-right tabular-nums text-slate-500">{r.impressions.toLocaleString()}</td>
                <td className="px-4 py-2 text-right tabular-nums text-slate-500">{r.position.toFixed(1)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </Card>
  );
}

// ─── Site Tag vs GA4 comparison card ──────────────────────────────
//
// Surfaces the cross-source delta for a single metric. Site Tag
// over-counting vs GA4 is HEALTHY when measuring conversions
// (gtag interception + plugin paths catch what GA4 misses) but
// the inverse is HEALTHY when measuring sessions (Site Tag should
// be close to GA4; a big positive delta there signals a bot or
// duplicate counting issue).

// Format the effective window for the section subtitle, e.g.
// "Comparing Apr 10 – Apr 16 (6 days since Site Tag installed)".
function formatEffectiveWindow(c: {
  effectiveFrom: string;
  effectiveTo: string;
  effectiveDays: number;
  partialOverlap: boolean;
}): string {
  try {
    const from = new Date(c.effectiveFrom);
    const to = new Date(c.effectiveTo);
    const fromStr = from.toLocaleDateString(undefined, { month: "short", day: "numeric" });
    const toStr = to.toLocaleDateString(undefined, { month: "short", day: "numeric" });
    const base = `Comparing ${fromStr} – ${toStr} (${c.effectiveDays} day${c.effectiveDays === 1 ? "" : "s"})`;
    return c.partialOverlap ? `${base} · since Site Tag installed` : base;
  } catch {
    return "Cross-source delta";
  }
}

function ComparisonCard({
  label, siteTag, ga4, delta, higherIsBetter = false,
  captureRate, siteTagPerDay, ga4PerDay,
}: {
  label: string;
  siteTag: number;
  ga4: number;
  delta: number | null;
  higherIsBetter?: boolean;
  captureRate?: number | null;
  siteTagPerDay?: number;
  ga4PerDay?: number;
}) {
  const deltaIsHealthy = delta == null
    ? null
    : higherIsBetter
      ? delta >= 0
      : Math.abs(delta) <= 25; // session reconciliation: ±25% considered healthy
  // Capture-rate pill colour — ≥95% healthy; 70-95% warning; <70% concern.
  // Values >100% (Site Tag catching more) are healthy when higherIsBetter,
  // otherwise worth flagging.
  const captureHealthy = captureRate == null
    ? null
    : higherIsBetter
      ? captureRate >= 95
      : captureRate >= 70 && captureRate <= 130;
  return (
    <Card>
      <div className="p-4 space-y-3">
        <div className="flex items-center justify-between gap-2">
          <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">{label}</p>
          <div className="flex items-center gap-1.5">
            {captureRate != null && (
              <span
                className={`text-[10px] font-bold uppercase tracking-widest px-2 py-0.5 rounded-full border ${
                  captureHealthy
                    ? "bg-emerald-50 text-emerald-700 border-emerald-200"
                    : "bg-amber-50 text-amber-700 border-amber-200"
                }`}
                title="Site Tag / GA4 over the overlap window"
              >
                {captureRate}% capture
              </span>
            )}
            {delta != null && (
              <span className={`text-[10px] font-bold uppercase tracking-widest px-2 py-0.5 rounded-full border ${
                deltaIsHealthy
                  ? "bg-emerald-50 text-emerald-700 border-emerald-200"
                  : "bg-amber-50 text-amber-700 border-amber-200"
              }`}>
                {delta > 0 ? "+" : ""}{delta}%
              </span>
            )}
          </div>
        </div>
        <div className="grid grid-cols-2 gap-3">
          <div>
            <p className="text-[10px] text-slate-400 uppercase tracking-wider">Site Tag</p>
            <p className="text-2xl font-bold text-slate-900 tabular-nums">{siteTag.toLocaleString()}</p>
            {siteTagPerDay != null && (
              <p className="text-[10px] text-slate-500 tabular-nums mt-0.5">{siteTagPerDay.toLocaleString()}/day</p>
            )}
          </div>
          <div>
            <p className="text-[10px] text-slate-400 uppercase tracking-wider">GA4</p>
            <p className="text-2xl font-bold text-slate-900 tabular-nums">{ga4.toLocaleString()}</p>
            {ga4PerDay != null && (
              <p className="text-[10px] text-slate-500 tabular-nums mt-0.5">{ga4PerDay.toLocaleString()}/day</p>
            )}
          </div>
        </div>
        {/* Win caption when Site Tag > GA4 on a higher-is-better
            metric — turns the otherwise-amber delta pill into an
            actionable positive signal ("gtag interception is working"). */}
        {higherIsBetter && delta != null && delta > 0 && (
          <p className="text-[11px] text-emerald-700 bg-emerald-50/60 border-l-2 border-emerald-400 pl-2 py-1 rounded-sm">
            Site Tag capturing <span className="font-semibold">{delta}% more</span> than GA4 — gtag interception + plugin paths working.
          </p>
        )}
      </div>
    </Card>
  );
}

// ─── URL → path helper for top-pages tables ──
function extractPath(url: string): string {
  try { return new URL(url).pathname || url; } catch { return url; }
}

// ─── Brand confidence cell ────────────────────────────────────────
//
// Self-fetching pill that shows the brand's Site Tag confidence
// score (0-100) colour-coded by verdict. Used in the Top Brands
// table so operators can spot brands whose tracking is degrading
// without drilling into each one individually. Uses a 5-minute
// server-side cache on /api/site-tag/confidence so re-rendering
// the table (e.g. on range change) doesn't fan out 5 × 6 queries.

function BrandConfidenceCell({ brandId, range }: { brandId: string; range: Range }) {
  const [score, setScore] = useState<number | null>(null);
  const [verdict, setVerdict] = useState<"Healthy" | "Degraded" | "Poor" | null>(null);

  useEffect(() => {
    // Map admin-range (today/7d/30d/90d/all) → confidence range.
    const r = range === "today" ? "1d"
      : range === "7d" ? "7d"
      : range === "90d" ? "90d"
      : range === "all" ? "90d"  // confidence tops out at 90d
      : "30d";
    let cancelled = false;
    fetch(`/api/site-tag/confidence?brandId=${encodeURIComponent(brandId)}&range=${r}`)
      .then((res) => res.ok ? res.json() : null)
      .then((d: { score?: number; verdict?: "Healthy" | "Degraded" | "Poor" } | null) => {
        if (cancelled || !d) return;
        setScore(typeof d.score === "number" ? d.score : null);
        setVerdict(d.verdict ?? null);
      })
      .catch(() => {});
    return () => { cancelled = true; };
  }, [brandId, range]);

  if (score == null) {
    return <span className="text-[10px] text-slate-300">—</span>;
  }
  const cls = verdict === "Healthy" ? "bg-emerald-50 text-emerald-700 border-emerald-200"
    : verdict === "Degraded" ? "bg-amber-50 text-amber-700 border-amber-200"
    : "bg-rose-50 text-rose-700 border-rose-200";
  return (
    <span className={`inline-flex items-center gap-1 text-[10px] font-bold tabular-nums px-1.5 py-0.5 rounded border ${cls}`}>
      {score}%
    </span>
  );
}

// ─── Conversion Reconciliation card ───────────────────────────────
//
// Pulls the per-conversion-type capture-rate breakdown from
// /api/admin/conversion-reconciliation and renders it as a table:
// GA4 ground truth vs Site Tag count vs missing vs capture rate %.
// Surfaces the diagnosis lines from the endpoint as a bulleted list
// below so operators see actionable findings inline.

interface ReconciliationGap {
  type: string;
  label: string;
  ga4: number;
  siteTag: number;
  missing: number;
  captureRate: string;
}
interface ReconciliationResponse {
  ga4: { connected: boolean; error: string | null };
  gaps: {
    perType: ReconciliationGap[];
    overall: { ga4: number; siteTag: number; missing: number; captureRate: string };
  };
  diagnosis: string[];
  generatedAt: string;
}

function ConversionReconciliationCard({
  brandId, range,
}: {
  brandId: string;
  range: "today" | "7d" | "28d" | "30d" | "90d";
}) {
  const [data, setData] = useState<ReconciliationResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchData = useCallback(() => {
    setLoading(true);
    setError(null);
    fetch(`/api/admin/conversion-reconciliation?brandId=${encodeURIComponent(brandId)}&range=${range}`)
      .then((r) => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)))
      .then((d: ReconciliationResponse) => setData(d))
      .catch((err) => setError(err instanceof Error ? err.message : "Reconciliation fetch failed"))
      .finally(() => setLoading(false));
  }, [brandId, range]);

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

  return (
    <div className="space-y-3">
      <SourceHeader
        icon={Gauge}
        title="Conversion Reconciliation"
        subtitle="Per-type Site Tag vs GA4 capture rate"
        color="text-amber-700"
        bgColor="bg-amber-50"
        borderColor="border-amber-200"
      />
      <Card>
        <div className="px-4 py-3 border-b border-slate-100 flex items-center gap-3">
          <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500">
            Last reconciled: {data?.generatedAt ? new Date(data.generatedAt).toLocaleString() : (loading ? "loading…" : "—")}
          </p>
          <button
            onClick={fetchData}
            disabled={loading}
            className="ml-auto inline-flex items-center gap-1 px-3 py-1 text-[11px] font-semibold rounded-md bg-slate-900 text-white hover:bg-slate-800 disabled:opacity-50"
          >
            <RefreshCw className={`w-3 h-3 ${loading ? "animate-spin" : ""}`} />
            {loading ? "Reconciling…" : "Reconcile Now"}
          </button>
        </div>
        {error && (
          <div className="px-4 py-3 text-[11px] text-rose-700 bg-rose-50 border-b border-rose-100">
            {error}
          </div>
        )}
        {data && !data.ga4.connected && (
          <div className="px-4 py-6 text-center text-[11px] text-slate-500">
            {data.ga4.error ?? "GA4 not connected for this brand."}
          </div>
        )}
        {data && data.ga4.connected && (
          <>
            <table className="w-full text-xs">
              <thead className="text-[10px] font-semibold uppercase tracking-widest text-slate-400 border-b border-slate-100">
                <tr>
                  <th className="text-left px-4 py-2">Conversion type</th>
                  <th className="text-right px-4 py-2">GA4</th>
                  <th className="text-right px-4 py-2">Site Tag</th>
                  <th className="text-right px-4 py-2">Missing</th>
                  <th className="text-right px-4 py-2">Capture rate</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-100">
                {(data.gaps?.perType ?? []).map((g) => {
                  const rate = parseFloat(g.captureRate);
                  const healthy = isNaN(rate) || rate >= 90;
                  return (
                    <tr key={g.type}>
                      <td className="px-4 py-2 font-medium text-slate-800">{g.label}</td>
                      <td className="px-4 py-2 text-right tabular-nums text-slate-700">{g.ga4.toLocaleString()}</td>
                      <td className="px-4 py-2 text-right tabular-nums font-semibold text-slate-900">{g.siteTag.toLocaleString()}</td>
                      <td className={`px-4 py-2 text-right tabular-nums ${g.missing > 0 ? "text-amber-700 font-semibold" : "text-slate-500"}`}>
                        {g.missing > 0 ? `−${g.missing.toLocaleString()}` : "0"}
                      </td>
                      <td className={`px-4 py-2 text-right tabular-nums font-semibold ${healthy ? "text-emerald-700" : "text-amber-700"}`}>
                        {g.captureRate}
                      </td>
                    </tr>
                  );
                })}
                {data.gaps?.overall && (
                  <tr className="bg-slate-50/40 font-semibold">
                    <td className="px-4 py-2 text-slate-900 uppercase tracking-wider text-[10px]">Overall</td>
                    <td className="px-4 py-2 text-right tabular-nums text-slate-900">{(data.gaps.overall.ga4 ?? 0).toLocaleString()}</td>
                    <td className="px-4 py-2 text-right tabular-nums text-slate-900">{(data.gaps.overall.siteTag ?? 0).toLocaleString()}</td>
                    <td className={`px-4 py-2 text-right tabular-nums ${(data.gaps.overall.missing ?? 0) > 0 ? "text-amber-700" : "text-slate-700"}`}>
                      {(data.gaps.overall.missing ?? 0) > 0 ? `−${(data.gaps.overall.missing ?? 0).toLocaleString()}` : "0"}
                    </td>
                    <td className="px-4 py-2 text-right tabular-nums text-slate-900">{data.gaps.overall.captureRate ?? "n/a"}</td>
                  </tr>
                )}
              </tbody>
            </table>
            {(data.diagnosis?.length ?? 0) > 0 && (
              <div className="px-4 py-3 border-t border-slate-100 bg-slate-50/40">
                <p className="text-[10px] font-bold uppercase tracking-widest text-slate-500 mb-1.5">Findings</p>
                <ul className="space-y-1">
                  {(data.diagnosis ?? []).map((d, i) => (
                    <li key={i} className="text-[11px] text-slate-700 leading-relaxed flex gap-2">
                      <span className="text-slate-400 shrink-0">•</span><span>{d}</span>
                    </li>
                  ))}
                </ul>
              </div>
            )}
          </>
        )}
      </Card>
    </div>
  );
}

// ─── Metric card thin wrapper ─────────────────────────────────────

function MetricCard({
  label, icon, metric, color, valueClass, format,
}: {
  label: string;
  icon: typeof Eye;
  metric: MetricSeries | undefined | null;
  color: string;
  valueClass?: string;
  format?: "number" | "percent";
}) {
  // Defensive: API response shape evolved across the Apr-2026 Site
  // Tag / admin-metrics commits (siteTag/ga4/gsc carve-out, tier-1/2
  // rollup, engagement metric). If the deployed client reads a field
  // the API hasn't shipped yet — or a brand without GSC/GA4 lands on
  // the dashboard — `metric` can legitimately be undefined. Render
  // a zero-state card rather than crashing the whole admin shell.
  const safeMetric: MetricSeries = metric ?? {
    current: 0, previous: 0, trendPct: 0, timeseries: [],
  };
  const current = typeof safeMetric.current === "number" ? safeMetric.current : 0;
  // Dual-number display for conversion-style metrics that carry an
  // interactions count. When interactions > current (i.e. dedup has
  // collapsed repeat clicks), render the unique count as the headline
  // and the raw count as a subtle subtitle: "237 / 579 interactions".
  // Stays a plain number for metrics without interactions (page views,
  // sessions, formStarts, etc.).
  const interactions = typeof safeMetric.interactions === "number" ? safeMetric.interactions : null;
  const hasSubtitle = interactions != null && interactions > current;
  const primary = format === "percent" ? `${current.toFixed(2)}%` : formatNumber(current);
  const value: ReactNode = hasSubtitle ? (
    <span className="flex flex-col gap-0.5">
      <span>{primary}</span>
      <span className="text-[10px] font-semibold uppercase tracking-widest text-slate-400 normal-case tracking-normal">
        {formatNumber(interactions!)} interactions
      </span>
    </span>
  ) : primary;
  return (
    <StatCard
      label={label}
      icon={icon}
      value={value}
      trendPct={safeMetric.trendPct ?? null}
      sparkline={(safeMetric.timeseries ?? []).map((p) => p.value)}
      color={color}
      valueClass={valueClass}
      variant="compact"
    />
  );
}

// ─── Activity area chart — 2 series ───────────────────────────────

function ActivityChart({
  pageViews, sessions,
}: {
  pageViews: Array<{ date: string; value: number }>;
  sessions: Array<{ date: string; value: number }>;
}) {
  // Stack the two series into one chart with two stroke colors.
  // Simpler than recharts and avoids the typecheck noise from the
  // missing recharts types. The "tooltip on hover" reduces to a CSS
  // hover state on the dot circles since SVG doesn't carry pointer
  // events through paths.
  const W = 1000;
  const H = 200;
  const PAD = 24;
  const innerW = W - PAD * 2;
  const innerH = H - PAD * 2;
  const len = Math.max(pageViews.length, sessions.length);
  if (len === 0) {
    return <div className="h-[200px] flex items-center justify-center text-xs text-slate-400">No activity in this window.</div>;
  }
  const maxValue = Math.max(
    ...pageViews.map((p) => p.value),
    ...sessions.map((p) => p.value),
    1,
  );
  const xStep = len > 1 ? innerW / (len - 1) : 0;
  const buildPath = (series: Array<{ value: number }>, area = false) => {
    const line = series.map((p, i) => {
      const x = PAD + i * xStep;
      const y = PAD + innerH - (p.value / maxValue) * innerH;
      return `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`;
    }).join(" ");
    return area ? `${line} L${PAD + (series.length - 1) * xStep},${PAD + innerH} L${PAD},${PAD + innerH} Z` : line;
  };

  // X-axis tick labels — first / middle / last only; full list would
  // crowd at 30 points wide.
  const ticks = [0, Math.floor(len / 2), len - 1].filter((i, idx, arr) => arr.indexOf(i) === idx);

  return (
    <div className="w-full">
      <svg viewBox={`0 0 ${W} ${H}`} className="w-full h-[200px]" preserveAspectRatio="none">
        {/* Y-axis gridlines at 25/50/75/100% */}
        {[0.25, 0.5, 0.75, 1].map((r) => {
          const y = PAD + innerH - innerH * r;
          return <line key={r} x1={PAD} y1={y} x2={W - PAD} y2={y} stroke="#F1F5F9" strokeWidth={1} />;
        })}
        {/* Page views (blue area) */}
        <path d={buildPath(pageViews, true)} fill="#3B82F6" fillOpacity={0.12} />
        <path d={buildPath(pageViews)} stroke="#3B82F6" strokeWidth={2} fill="none" />
        {/* Sessions (violet line, no fill) */}
        <path d={buildPath(sessions)} stroke="#8B5CF6" strokeWidth={2} fill="none" strokeDasharray="3 3" />
        {/* X-axis tick labels */}
        {ticks.map((i) => {
          const x = PAD + i * xStep;
          const date = pageViews[i]?.date ?? sessions[i]?.date ?? "";
          return (
            <text key={i} x={x} y={H - 4} fontSize="9" fill="#94A3B8" textAnchor="middle">
              {date.slice(5)}
            </text>
          );
        })}
      </svg>
      <div className="flex items-center gap-4 text-[11px] mt-2">
        <span className="inline-flex items-center gap-1.5">
          <span className="w-3 h-1 bg-blue-500 rounded" />
          <span className="text-slate-600">Page views</span>
        </span>
        <span className="inline-flex items-center gap-1.5">
          <span className="w-3 h-1 bg-violet-500 rounded" style={{ borderTop: "1px dashed #8B5CF6" }} />
          <span className="text-slate-600">Sessions</span>
        </span>
        <span className="text-slate-400 ml-auto">peak {formatNumber(maxValue)}</span>
      </div>
    </div>
  );
}

// ─── Tracking Coverage card ───────────────────────────────────────────
//
// Renders the 10-category coverage grid fed by /api/admin/overview's
// trackingCoverage block. Each tile shows a category name, the sum
// of events in that category over the last 7 days, and a green /
// grey dot reflecting active vs. inactive. A summary line at the
// top reads "N of 10 categories active · M distinct event types in
// the last 7 days" — operator-level glance at platform-wide Site
// Tag health without drilling into an individual brand.

function TrackingCoverageCard({
  coverage,
}: {
  coverage: NonNullable<Overview["trackingCoverage"]>;
}) {
  const { activeCategories, totalCategories, totalDistinctTypes, windowDays, categories } = coverage;
  return (
    <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
      <div className="px-5 py-3.5 border-b border-slate-100 flex items-center gap-3 flex-wrap">
        <span className="text-sm font-bold text-slate-900">
          {activeCategories} of {totalCategories} categories active
        </span>
        <span className="text-[11px] text-slate-500">
          {totalDistinctTypes.toLocaleString()} distinct event type{totalDistinctTypes === 1 ? "" : "s"} in the last {windowDays} day{windowDays === 1 ? "" : "s"}
        </span>
      </div>
      <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 divide-x divide-y divide-slate-100">
        {categories.map((c) => (
          <div
            key={c.key}
            className="px-4 py-3 flex items-center justify-between gap-3"
            title={
              c.active
                ? `Active event types: ${c.activeTypes.join(", ")}`
                : "No events in this category over the last 7 days"
            }
          >
            <div className="min-w-0">
              <div className="flex items-center gap-2">
                <span
                  className={`inline-block w-2 h-2 rounded-full shrink-0 ${c.active ? "bg-emerald-500" : "bg-slate-300"}`}
                  aria-hidden="true"
                />
                <p className={`text-xs font-semibold truncate ${c.active ? "text-slate-800" : "text-slate-500"}`}>
                  {c.label}
                </p>
              </div>
              <p className="text-[10px] text-slate-400 mt-0.5 tabular-nums">
                {c.active ? `${c.total.toLocaleString()} events` : "no coverage"}
              </p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}
