// @File: src/pages/ClientWhatsappAnalytics.tsx
// @Desc: Client-area analytics dashboard for the WhatsApp campaigns
//        module. Shows delivery / reply / engagement trends from the
//        time-series metrics stored in Atoms Cloud
//        (``whatsapp_campaign_metrics`` table). Backed by the
//        ``/api/v1/client/whatsapp/campaigns/analytics`` endpoints.
//
//        Sections:
//          - KPI cards: campaigns, recipients, delivery / reply / failure rates
//          - Trend chart: stacked area of sent/delivered/replied over time
//          - Rate chart: delivery_rate vs reply_rate line
//          - Per-campaign picker → funnel chart + hourly bars
//          - Compare table: side-by-side KPI comparison of selected campaigns
//          - CSV export buttons (summary + per-campaign detail)
import { useCallback, useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  Legend,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import {
  AlertTriangle,
  ArrowLeft,
  BarChart3,
  Download,
  Info,
  Lightbulb,
  Loader2,
  RefreshCw,
  Sparkles,
  TrendingUp,
} from "lucide-react";

import {
  CampaignAnalyticsOverview,
  CampaignCompare,
  CampaignFunnel,
  CampaignInsights,
  CampaignInsightWarning,
  CampaignTimeseries,
  WhatsappCampaign,
  waAnalyticsCampaignCsvUrl,
  waAnalyticsCompare,
  waAnalyticsDownload,
  waAnalyticsFunnel,
  waAnalyticsInsights,
  waAnalyticsOverview,
  waAnalyticsSummaryCsvUrl,
  waAnalyticsTimeseries,
  waListCampaigns,
} from "@/lib/whatsappApi";

const PALETTE = {
  sent: "#0f766e",
  delivered: "#0ea5e9",
  read: "#6366f1",
  replied: "#22c55e",
  failed: "#ef4444",
  opted_out: "#f59e0b",
};

type Granularity = "hour" | "day" | "week";

function fmtBucket(iso: string, granularity: Granularity): string {
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return iso;
  if (granularity === "hour") {
    return d.toLocaleString(undefined, {
      month: "short",
      day: "numeric",
      hour: "2-digit",
    });
  }
  return d.toLocaleDateString(undefined, {
    month: "short",
    day: "numeric",
    year: granularity === "week" ? "numeric" : undefined,
  });
}

function fmtPct(value: number): string {
  return `${value.toFixed(1)}%`;
}

function KpiCard(props: {
  label: string;
  value: string | number;
  hint?: string;
  tone?: "default" | "good" | "warn" | "bad";
}) {
  const tone = props.tone ?? "default";
  const toneClasses: Record<string, string> = {
    default: "bg-white border-slate-200 text-slate-900",
    good: "bg-emerald-50 border-emerald-200 text-emerald-900",
    warn: "bg-amber-50 border-amber-200 text-amber-900",
    bad: "bg-rose-50 border-rose-200 text-rose-900",
  };
  return (
    <div className={`rounded-lg border px-4 py-3 shadow-sm ${toneClasses[tone]}`}>
      <div className="text-xs font-medium uppercase tracking-wide text-slate-500">
        {props.label}
      </div>
      <div className="mt-1 text-2xl font-semibold">{props.value}</div>
      {props.hint ? (
        <div className="mt-1 text-xs text-slate-500">{props.hint}</div>
      ) : null}
    </div>
  );
}

function SeverityBadge({ severity }: { severity: CampaignInsightWarning["severity"] }) {
  const map: Record<string, string> = {
    high: "bg-rose-100 text-rose-800 border-rose-200",
    medium: "bg-amber-100 text-amber-800 border-amber-200",
    low: "bg-slate-100 text-slate-700 border-slate-200",
  };
  return (
    <span
      className={`inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${map[severity] ?? map.medium}`}
    >
      {severity}
    </span>
  );
}

function InsightsPanel(props: {
  loading: boolean;
  error: string | null;
  data: CampaignInsights | null;
  onRefresh: () => void;
}) {
  const { loading, error, data, onRefresh } = props;

  return (
    <section className="mb-6 rounded-xl border border-indigo-200 bg-gradient-to-br from-indigo-50 via-white to-emerald-50 p-5 shadow-sm">
      <header className="mb-4 flex flex-wrap items-center justify-between gap-2">
        <div className="flex items-start gap-3">
          <div className="rounded-lg bg-indigo-600 p-2 text-white shadow-sm">
            <Sparkles className="h-5 w-5" />
          </div>
          <div>
            <h2 className="flex items-center gap-2 text-base font-semibold text-slate-900">
              AI Insights
              {data?.fallback ? (
                <span
                  title="Using rule-based fallback — the AI service was unavailable."
                  className="inline-flex items-center gap-1 rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-[10px] font-medium text-amber-800"
                >
                  <Info className="h-3 w-3" /> Basic mode
                </span>
              ) : null}
            </h2>
            <p className="mt-0.5 text-xs text-slate-500">
              Automated trend analysis and optimization suggestions for your campaigns.
            </p>
          </div>
        </div>
        <button
          onClick={onRefresh}
          disabled={loading}
          className="inline-flex items-center gap-1 rounded-md border border-slate-300 bg-white px-3 py-1.5 text-xs text-slate-700 shadow-sm hover:bg-slate-50 disabled:opacity-60"
        >
          {loading ? (
            <Loader2 className="h-3.5 w-3.5 animate-spin" />
          ) : (
            <RefreshCw className="h-3.5 w-3.5" />
          )}
          Regenerate
        </button>
      </header>

      {error ? (
        <div className="rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">
          Failed to generate insights: {error}
        </div>
      ) : loading && !data ? (
        <div className="flex items-center gap-2 text-sm text-slate-500">
          <Loader2 className="h-4 w-4 animate-spin" /> Analyzing campaigns…
        </div>
      ) : data ? (
        <div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
          {/* Summary */}
          <div className="lg:col-span-3">
            <div className="rounded-lg border border-indigo-100 bg-white/70 px-4 py-3 text-sm leading-relaxed text-slate-800">
              {data.summary || "No summary available."}
            </div>
          </div>

          {/* Trends */}
          <div className="rounded-lg border border-slate-200 bg-white p-4">
            <div className="mb-2 flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-slate-600">
              <TrendingUp className="h-4 w-4 text-indigo-600" /> Trends
            </div>
            {data.trends.length ? (
              <ul className="space-y-2 text-sm text-slate-700">
                {data.trends.map((t, i) => (
                  <li key={i} className="flex gap-2">
                    <span className="mt-1 inline-block h-1.5 w-1.5 flex-shrink-0 rounded-full bg-indigo-500" />
                    <span>{t}</span>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="text-xs text-slate-500">
                No notable trends detected yet.
              </p>
            )}
          </div>

          {/* Recommendations */}
          <div className="rounded-lg border border-slate-200 bg-white p-4">
            <div className="mb-2 flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-slate-600">
              <Lightbulb className="h-4 w-4 text-emerald-600" /> Recommendations
            </div>
            {data.recommendations.length ? (
              <ul className="space-y-2 text-sm text-slate-700">
                {data.recommendations.map((r, i) => (
                  <li key={i} className="flex gap-2">
                    <span className="mt-1 inline-block h-1.5 w-1.5 flex-shrink-0 rounded-full bg-emerald-500" />
                    <span>{r}</span>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="text-xs text-slate-500">
                No specific recommendations — keep up the current cadence.
              </p>
            )}
          </div>

          {/* Warnings */}
          <div className="rounded-lg border border-slate-200 bg-white p-4">
            <div className="mb-2 flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-slate-600">
              <AlertTriangle className="h-4 w-4 text-rose-600" /> Warnings
            </div>
            {data.warnings.length ? (
              <ul className="space-y-2 text-sm text-slate-700">
                {data.warnings.map((w, i) => (
                  <li key={i} className="rounded-md border border-slate-100 bg-slate-50 px-2 py-1.5">
                    <div className="flex items-center justify-between gap-2">
                      <span className="truncate text-xs font-medium text-slate-800">
                        {w.campaign_name}
                      </span>
                      <SeverityBadge severity={w.severity} />
                    </div>
                    <div className="mt-1 text-xs text-slate-600">{w.reason}</div>
                  </li>
                ))}
              </ul>
            ) : (
              <p className="text-xs text-slate-500">
                No campaigns are currently flagged — nice work!
              </p>
            )}
          </div>

          <div className="lg:col-span-3 text-right text-[11px] text-slate-400">
            Generated by {data.model}
            {data.fallback ? " (fallback)" : ""}
          </div>
        </div>
      ) : (
        <div className="text-sm text-slate-500">
          Click Regenerate to produce AI insights.
        </div>
      )}
    </section>
  );
}

function SectionCard(props: {
  title: string;
  subtitle?: string;
  actions?: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <section className="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
      <header className="mb-4 flex flex-wrap items-center justify-between gap-2">
        <div>
          <h2 className="text-base font-semibold text-slate-900">{props.title}</h2>
          {props.subtitle ? (
            <p className="mt-0.5 text-xs text-slate-500">{props.subtitle}</p>
          ) : null}
        </div>
        {props.actions ? <div className="flex gap-2">{props.actions}</div> : null}
      </header>
      {props.children}
    </section>
  );
}

export default function ClientWhatsappAnalytics() {
  const [granularity, setGranularity] = useState<Granularity>("day");
  const [overview, setOverview] = useState<CampaignAnalyticsOverview | null>(null);
  const [overviewLoading, setOverviewLoading] = useState(true);
  const [overviewError, setOverviewError] = useState<string | null>(null);

  const [campaigns, setCampaigns] = useState<WhatsappCampaign[]>([]);
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [timeseries, setTimeseries] = useState<CampaignTimeseries | null>(null);
  const [funnel, setFunnel] = useState<CampaignFunnel | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detailError, setDetailError] = useState<string | null>(null);

  const [compareIds, setCompareIds] = useState<Set<number>>(new Set());
  const [compare, setCompare] = useState<CampaignCompare | null>(null);
  const [compareLoading, setCompareLoading] = useState(false);

  const [downloading, setDownloading] = useState<string | null>(null);

  const [insights, setInsights] = useState<CampaignInsights | null>(null);
  const [insightsLoading, setInsightsLoading] = useState(false);
  const [insightsError, setInsightsError] = useState<string | null>(null);

  // ---------------------------------------------------------------
  // Loaders
  // ---------------------------------------------------------------

  const loadOverview = useCallback(async () => {
    setOverviewLoading(true);
    setOverviewError(null);
    try {
      const data = await waAnalyticsOverview({ granularity });
      setOverview(data);
    } catch (err) {
      setOverviewError(err instanceof Error ? err.message : String(err));
    } finally {
      setOverviewLoading(false);
    }
  }, [granularity]);

  const loadCampaigns = useCallback(async () => {
    try {
      const list = await waListCampaigns();
      setCampaigns(list);
      if (list.length && selectedId === null) {
        setSelectedId(list[0].id);
      }
    } catch {
      // Non-fatal — overview still renders.
    }
  }, [selectedId]);

  const loadDetail = useCallback(async () => {
    if (selectedId === null) return;
    setDetailLoading(true);
    setDetailError(null);
    try {
      const [ts, fn] = await Promise.all([
        waAnalyticsTimeseries(selectedId, { granularity: "hour" }),
        waAnalyticsFunnel(selectedId),
      ]);
      setTimeseries(ts);
      setFunnel(fn);
    } catch (err) {
      setDetailError(err instanceof Error ? err.message : String(err));
    } finally {
      setDetailLoading(false);
    }
  }, [selectedId]);

  const loadCompare = useCallback(async () => {
    if (compareIds.size === 0) {
      setCompare(null);
      return;
    }
    setCompareLoading(true);
    try {
      const data = await waAnalyticsCompare(Array.from(compareIds));
      setCompare(data);
    } catch {
      setCompare(null);
    } finally {
      setCompareLoading(false);
    }
  }, [compareIds]);

  const loadInsights = useCallback(async () => {
    setInsightsLoading(true);
    setInsightsError(null);
    try {
      const data = await waAnalyticsInsights({ granularity });
      setInsights(data);
    } catch (err) {
      setInsightsError(err instanceof Error ? err.message : String(err));
    } finally {
      setInsightsLoading(false);
    }
  }, [granularity]);

  useEffect(() => {
    void loadOverview();
  }, [loadOverview]);

  useEffect(() => {
    void loadCampaigns();
  }, [loadCampaigns]);

  useEffect(() => {
    void loadDetail();
  }, [loadDetail]);

  useEffect(() => {
    void loadCompare();
  }, [loadCompare]);

  useEffect(() => {
    void loadInsights();
  }, [loadInsights]);

  // ---------------------------------------------------------------
  // Derived data
  // ---------------------------------------------------------------

  const trendData = useMemo(() => {
    if (!overview) return [];
    return overview.trend.map((p) => ({
      ...p,
      label: fmtBucket(p.bucket_ts, granularity),
    }));
  }, [overview, granularity]);

  const detailSeries = useMemo(() => {
    if (!timeseries) return [];
    return timeseries.series.map((p) => ({
      ...p,
      label: fmtBucket(p.bucket_ts, "hour"),
    }));
  }, [timeseries]);

  const funnelData = useMemo(() => {
    if (!funnel) return [];
    return funnel.steps.map((s) => ({ name: s.label, value: s.value, rate: s.rate }));
  }, [funnel]);

  const toggleCompare = (id: number) => {
    setCompareIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const handleDownload = async (url: string, filename: string) => {
    setDownloading(filename);
    try {
      await waAnalyticsDownload(url, filename);
    } catch (err) {
      alert(err instanceof Error ? err.message : String(err));
    } finally {
      setDownloading(null);
    }
  };

  // ---------------------------------------------------------------
  // Render
  // ---------------------------------------------------------------

  const kpis = overview?.kpis;

  return (
    <div className="min-h-screen bg-slate-50 py-8">
      <div className="mx-auto max-w-7xl px-4">
        {/* Page header */}
        <div className="mb-6 flex flex-wrap items-center justify-between gap-3">
          <div>
            <Link
              to="/client/whatsapp/campaigns"
              className="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-700"
            >
              <ArrowLeft className="h-4 w-4" /> Back to Campaigns
            </Link>
            <h1 className="mt-2 flex items-center gap-2 text-2xl font-semibold text-slate-900">
              <BarChart3 className="h-6 w-6 text-emerald-600" /> Campaign Analytics
            </h1>
            <p className="mt-1 text-sm text-slate-500">
              Delivery rates, reply rates and engagement trends for every WhatsApp
              campaign you've launched.
            </p>
          </div>
          <div className="flex items-center gap-2">
            <select
              value={granularity}
              onChange={(e) => setGranularity(e.target.value as Granularity)}
              className="rounded-md border border-slate-300 bg-white px-3 py-2 text-sm shadow-sm"
            >
              <option value="hour">Hourly</option>
              <option value="day">Daily</option>
              <option value="week">Weekly</option>
            </select>
            <button
              onClick={() => void loadOverview()}
              className="inline-flex items-center gap-1 rounded-md border border-slate-300 bg-white px-3 py-2 text-sm text-slate-700 shadow-sm hover:bg-slate-50"
            >
              <RefreshCw className="h-4 w-4" /> Refresh
            </button>
            <button
              onClick={() =>
                handleDownload(
                  waAnalyticsSummaryCsvUrl(),
                  "whatsapp_campaigns_summary.csv",
                )
              }
              disabled={downloading === "whatsapp_campaigns_summary.csv"}
              className="inline-flex items-center gap-1 rounded-md bg-emerald-600 px-3 py-2 text-sm text-white shadow-sm hover:bg-emerald-700 disabled:opacity-60"
            >
              {downloading === "whatsapp_campaigns_summary.csv" ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <Download className="h-4 w-4" />
              )}{" "}
              Export CSV
            </button>
          </div>
        </div>

        {overviewError ? (
          <div className="mb-4 rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">
            {overviewError}
          </div>
        ) : null}

        {/* KPI cards */}
        <div className="mb-6 grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-6">
          <KpiCard
            label="Campaigns"
            value={overviewLoading ? "…" : kpis?.total_campaigns ?? 0}
          />
          <KpiCard
            label="Recipients"
            value={overviewLoading ? "…" : kpis?.total_recipients?.toLocaleString() ?? 0}
          />
          <KpiCard
            label="Sent"
            value={overviewLoading ? "…" : kpis?.sent?.toLocaleString() ?? 0}
          />
          <KpiCard
            label="Delivery rate"
            value={overviewLoading ? "…" : fmtPct(kpis?.delivery_rate ?? 0)}
            hint={`${kpis?.delivered ?? 0} delivered`}
            tone="good"
          />
          <KpiCard
            label="Reply rate"
            value={overviewLoading ? "…" : fmtPct(kpis?.reply_rate ?? 0)}
            hint={`${kpis?.replied ?? 0} replied`}
            tone="good"
          />
          <KpiCard
            label="Failure rate"
            value={overviewLoading ? "…" : fmtPct(kpis?.failure_rate ?? 0)}
            hint={`${kpis?.failed ?? 0} failed`}
            tone={
              (kpis?.failure_rate ?? 0) > 10
                ? "bad"
                : (kpis?.failure_rate ?? 0) > 3
                ? "warn"
                : "default"
            }
          />
        </div>

        {/* AI-powered insights */}
        <InsightsPanel
          loading={insightsLoading}
          error={insightsError}
          data={insights}
          onRefresh={() => void loadInsights()}
        />

        {/* Trend + Rate charts */}
        <div className="mb-6 grid grid-cols-1 gap-4 lg:grid-cols-2">
          <SectionCard
            title="Engagement trend"
            subtitle="Sent vs delivered vs replied over time"
          >
            <div className="h-72 w-full">
              {overviewLoading ? (
                <div className="flex h-full items-center justify-center text-slate-400">
                  <Loader2 className="h-5 w-5 animate-spin" />
                </div>
              ) : trendData.length === 0 ? (
                <div className="flex h-full items-center justify-center text-sm text-slate-400">
                  No data yet — launch a campaign to see metrics here.
                </div>
              ) : (
                <ResponsiveContainer>
                  <AreaChart data={trendData}>
                    <defs>
                      <linearGradient id="gSent" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="5%" stopColor={PALETTE.sent} stopOpacity={0.4} />
                        <stop offset="95%" stopColor={PALETTE.sent} stopOpacity={0} />
                      </linearGradient>
                      <linearGradient id="gDelivered" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="5%" stopColor={PALETTE.delivered} stopOpacity={0.4} />
                        <stop offset="95%" stopColor={PALETTE.delivered} stopOpacity={0} />
                      </linearGradient>
                      <linearGradient id="gReplied" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="5%" stopColor={PALETTE.replied} stopOpacity={0.4} />
                        <stop offset="95%" stopColor={PALETTE.replied} stopOpacity={0} />
                      </linearGradient>
                    </defs>
                    <CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
                    <XAxis dataKey="label" tick={{ fontSize: 11 }} />
                    <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />
                    <Tooltip />
                    <Legend wrapperStyle={{ fontSize: 12 }} />
                    <Area
                      type="monotone"
                      dataKey="sent"
                      stroke={PALETTE.sent}
                      fill="url(#gSent)"
                      name="Sent"
                    />
                    <Area
                      type="monotone"
                      dataKey="delivered"
                      stroke={PALETTE.delivered}
                      fill="url(#gDelivered)"
                      name="Delivered"
                    />
                    <Area
                      type="monotone"
                      dataKey="replied"
                      stroke={PALETTE.replied}
                      fill="url(#gReplied)"
                      name="Replied"
                    />
                  </AreaChart>
                </ResponsiveContainer>
              )}
            </div>
          </SectionCard>

          <SectionCard
            title="Rate trend"
            subtitle="Delivery rate % vs reply rate % over time"
          >
            <div className="h-72 w-full">
              {overviewLoading ? (
                <div className="flex h-full items-center justify-center text-slate-400">
                  <Loader2 className="h-5 w-5 animate-spin" />
                </div>
              ) : trendData.length === 0 ? (
                <div className="flex h-full items-center justify-center text-sm text-slate-400">
                  No metrics available for this range.
                </div>
              ) : (
                <ResponsiveContainer>
                  <LineChart data={trendData}>
                    <CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
                    <XAxis dataKey="label" tick={{ fontSize: 11 }} />
                    <YAxis
                      tick={{ fontSize: 11 }}
                      domain={[0, 100]}
                      tickFormatter={(v) => `${v}%`}
                    />
                    <Tooltip formatter={(v: number) => `${v.toFixed(1)}%`} />
                    <Legend wrapperStyle={{ fontSize: 12 }} />
                    <Line
                      type="monotone"
                      dataKey="delivery_rate"
                      stroke={PALETTE.delivered}
                      strokeWidth={2}
                      name="Delivery rate"
                      dot={false}
                    />
                    <Line
                      type="monotone"
                      dataKey="reply_rate"
                      stroke={PALETTE.replied}
                      strokeWidth={2}
                      name="Reply rate"
                      dot={false}
                    />
                  </LineChart>
                </ResponsiveContainer>
              )}
            </div>
          </SectionCard>
        </div>

        {/* Campaign detail */}
        <SectionCard
          title="Per-campaign detail"
          subtitle="Drill into a single campaign to see its funnel and hourly metrics"
          actions={
            <select
              value={selectedId ?? ""}
              onChange={(e) =>
                setSelectedId(e.target.value ? Number(e.target.value) : null)
              }
              className="rounded-md border border-slate-300 bg-white px-3 py-2 text-sm shadow-sm"
            >
              <option value="">Select campaign…</option>
              {campaigns.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name} ({c.status})
                </option>
              ))}
            </select>
          }
        >
          {detailError ? (
            <div className="rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">
              {detailError}
            </div>
          ) : selectedId === null ? (
            <p className="text-sm text-slate-500">
              Choose a campaign above to inspect its delivery funnel and hourly
              engagement.
            </p>
          ) : detailLoading ? (
            <div className="flex h-40 items-center justify-center text-slate-400">
              <Loader2 className="h-5 w-5 animate-spin" />
            </div>
          ) : (
            <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
              {/* Funnel */}
              <div className="h-72 w-full">
                <h3 className="mb-1 text-sm font-medium text-slate-700">
                  Delivery funnel
                </h3>
                {funnelData.length === 0 ? (
                  <div className="flex h-full items-center justify-center text-sm text-slate-400">
                    No funnel data.
                  </div>
                ) : (
                  <ResponsiveContainer>
                    <BarChart data={funnelData} layout="vertical">
                      <CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
                      <XAxis type="number" tick={{ fontSize: 11 }} />
                      <YAxis
                        type="category"
                        dataKey="name"
                        tick={{ fontSize: 12 }}
                        width={80}
                      />
                      <Tooltip
                        formatter={(v: number, _n: string, p: { payload?: { rate?: number } }) =>
                          `${v.toLocaleString()} (${(p?.payload?.rate ?? 0).toFixed(1)}%)`
                        }
                      />
                      <Bar dataKey="value" name="Recipients">
                        {funnelData.map((_, idx) => (
                          <Cell
                            key={idx}
                            fill={
                              [
                                "#64748b",
                                PALETTE.sent,
                                PALETTE.delivered,
                                PALETTE.read,
                                PALETTE.replied,
                              ][idx] ?? PALETTE.sent
                            }
                          />
                        ))}
                      </Bar>
                    </BarChart>
                  </ResponsiveContainer>
                )}
              </div>

              {/* Hourly bars */}
              <div className="h-72 w-full">
                <h3 className="mb-1 flex items-center justify-between text-sm font-medium text-slate-700">
                  Hourly activity
                  <button
                    onClick={() =>
                      handleDownload(
                        waAnalyticsCampaignCsvUrl(selectedId),
                        `whatsapp_campaign_${selectedId}_recipients.csv`,
                      )
                    }
                    disabled={downloading?.includes(`_${selectedId}_`) ?? false}
                    className="inline-flex items-center gap-1 rounded-md border border-slate-300 bg-white px-2 py-1 text-xs text-slate-700 shadow-sm hover:bg-slate-50"
                  >
                    <Download className="h-3 w-3" /> Recipients CSV
                  </button>
                </h3>
                {detailSeries.length === 0 ? (
                  <div className="flex h-full items-center justify-center text-sm text-slate-400">
                    No hourly data yet.
                  </div>
                ) : (
                  <ResponsiveContainer>
                    <BarChart data={detailSeries}>
                      <CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
                      <XAxis dataKey="label" tick={{ fontSize: 11 }} />
                      <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />
                      <Tooltip />
                      <Legend wrapperStyle={{ fontSize: 12 }} />
                      <Bar
                        dataKey="delivered"
                        stackId="a"
                        fill={PALETTE.delivered}
                        name="Delivered"
                      />
                      <Bar
                        dataKey="replied"
                        stackId="a"
                        fill={PALETTE.replied}
                        name="Replied"
                      />
                      <Bar
                        dataKey="failed"
                        stackId="a"
                        fill={PALETTE.failed}
                        name="Failed"
                      />
                    </BarChart>
                  </ResponsiveContainer>
                )}
              </div>
            </div>
          )}
        </SectionCard>

        {/* Compare */}
        <div className="mt-6">
          <SectionCard
            title="Compare campaigns"
            subtitle="Tick up to 10 campaigns to see their KPIs side-by-side"
          >
            <div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
              <div className="max-h-64 overflow-y-auto rounded border border-slate-200">
                <ul className="divide-y divide-slate-100">
                  {campaigns.length === 0 ? (
                    <li className="px-3 py-2 text-sm text-slate-400">
                      No campaigns yet.
                    </li>
                  ) : (
                    campaigns.map((c) => (
                      <li key={c.id} className="px-3 py-2">
                        <label className="flex items-center gap-2 text-sm">
                          <input
                            type="checkbox"
                            checked={compareIds.has(c.id)}
                            onChange={() => toggleCompare(c.id)}
                          />
                          <span className="flex-1 truncate">{c.name}</span>
                          <span className="text-xs text-slate-500">{c.status}</span>
                        </label>
                      </li>
                    ))
                  )}
                </ul>
              </div>

              <div className="overflow-x-auto lg:col-span-2">
                {compareLoading ? (
                  <div className="flex h-32 items-center justify-center text-slate-400">
                    <Loader2 className="h-5 w-5 animate-spin" />
                  </div>
                ) : !compare || compare.campaigns.length === 0 ? (
                  <p className="text-sm text-slate-500">
                    Select campaigns on the left to compare.
                  </p>
                ) : (
                  <table className="w-full text-sm">
                    <thead className="bg-slate-50 text-xs uppercase text-slate-500">
                      <tr>
                        <th className="px-3 py-2 text-left">Campaign</th>
                        <th className="px-3 py-2 text-right">Recipients</th>
                        <th className="px-3 py-2 text-right">Sent</th>
                        <th className="px-3 py-2 text-right">Delivery %</th>
                        <th className="px-3 py-2 text-right">Reply %</th>
                        <th className="px-3 py-2 text-right">Failure %</th>
                      </tr>
                    </thead>
                    <tbody>
                      {compare.campaigns.map((c) => (
                        <tr key={c.id} className="border-t border-slate-100">
                          <td className="px-3 py-2">
                            <div className="font-medium text-slate-900">
                              {c.name}
                            </div>
                            <div className="text-xs text-slate-500">{c.status}</div>
                          </td>
                          <td className="px-3 py-2 text-right">
                            {c.total_recipients.toLocaleString()}
                          </td>
                          <td className="px-3 py-2 text-right">
                            {c.sent.toLocaleString()}
                          </td>
                          <td className="px-3 py-2 text-right text-emerald-700">
                            {fmtPct(c.delivery_rate)}
                          </td>
                          <td className="px-3 py-2 text-right text-emerald-700">
                            {fmtPct(c.reply_rate)}
                          </td>
                          <td
                            className={`px-3 py-2 text-right ${
                              c.failure_rate > 10
                                ? "text-rose-700"
                                : c.failure_rate > 3
                                ? "text-amber-700"
                                : "text-slate-700"
                            }`}
                          >
                            {fmtPct(c.failure_rate)}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            </div>
          </SectionCard>
        </div>
      </div>
    </div>
  );
}