"use client";

import { useState } from "react";
import {
  ClipboardList,
  LayoutTemplate,
  SlidersHorizontal,
  FileBarChart,
  TrendingUp,
  MapPin,
  Briefcase,
  Check,
  BarChart3,
  Table2,
  PieChart,
  LineChart,
  Target,
  Users,
  Globe,
  DollarSign,
  Database,
  CheckCircle2,
  XCircle,
  Search,
  Sparkles,
  RefreshCw,
  Info,
  FileDown,
  FileText,
  TableProperties,
  Copy,
  Presentation,
  Eye,
  Save,
  Calendar,
  Building2,
  ChevronDown,
  Loader2,
  AlertCircle,
  Bot,
} from "lucide-react";
import { useBrand } from "@/context/brand-context";
import { useBackgroundTasks } from "@/lib/stores/task-store";
import FeatureGate from "@/components/plan/feature-gate";

// ─── Dev-only mock data flag ─────────────────────────────────────────────────
// Mock preview content is only surfaced when this flag is explicitly set.
// In production this is always false, and no mock data will appear.
const DEV_MOCK_ENABLED =
  process.env.NEXT_PUBLIC_MESEO_ENV === "development" &&
  process.env.NEXT_PUBLIC_DEBUG_MOCK_DATA === "true";

// ─── Types ────────────────────────────────────────────────────────────────────

type Tab = "templates" | "custom";

interface Template {
  id:          string;
  label:       string;
  description: string;
  icon:        React.ComponentType<{ className?: string }>;
  accent:      string;
  bg:          string;
  sections:    string[];
}

interface LayoutSection {
  id:       string;
  label:    string;
  type:     "card" | "table" | "chart";
  icon:     React.ComponentType<{ className?: string }>;
  description: string;
}

type AiTone = "executive" | "detailed" | "simple";

const AI_TONE_LABELS: Record<AiTone, string> = {
  executive: "Executive",
  detailed:  "Detailed",
  simple:    "Simple",
};

/** Tone-specific placeholder copy shown in the Performance Summary
 *  block until real AI-summary generation is wired up. Previously
 *  this page rendered hand-authored prose with fabricated numbers
 *  ("$93K revenue, 18% lift, 487 conversions across 5 channels") as
 *  if they were live results — users had no way to tell it was
 *  preview text, and the numbers didn't match any real brand. The
 *  tone buttons still toggle state so the UI keeps its muscle memory
 *  once a real generator lands; the copy just becomes honest while
 *  we build the back-end. */
const AI_SUMMARY_PLACEHOLDERS: Record<AiTone, string> = {
  executive:
    "Executive summary preview — when a report is generated for this brand, the AI will ship a high-level narrative covering revenue trends, channel performance, and the single most important win/loss of the period. Select sources and a template, then hit Generate.",
  detailed:
    "Detailed summary preview — the generated version will walk through every connected channel (GA4, GSC, GBP, Site Tag) with specific numbers, conversion paths, and per-channel ROI. Select sources and a template, then hit Generate.",
  simple:
    "Simple summary preview — when generated, this will be a short, plain-English readout suitable for clients unfamiliar with SEO jargon. Select sources and a template, then hit Generate.",
};

interface DataSource {
  id:          string;
  label:       string;
  description: string;
  connected:   boolean;
  icon:        React.ComponentType<{ className?: string }>;
  accent:      string;
  bg:          string;
}

const DATA_SOURCES: DataSource[] = [
  { id: "ga4",  label: "GA4",                    description: "Traffic, sessions, users, and conversion events",    connected: true,  icon: BarChart3, accent: "text-orange-600",  bg: "bg-orange-50" },
  { id: "gsc",  label: "Google Search Console",  description: "Impressions, clicks, CTR, and keyword positions",   connected: true,  icon: Search,    accent: "text-blue-600",    bg: "bg-blue-50"   },
  { id: "gbp",  label: "Google Business Profile", description: "Local visibility, reviews, and map pack insights", connected: false, icon: MapPin,    accent: "text-amber-600",   bg: "bg-amber-50"  },
];

// ─── Mock data ────────────────────────────────────────────────────────────────

const TEMPLATES: Template[] = [
  {
    id: "executive",
    label: "Executive Summary",
    description: "High-level KPIs, revenue trends, and channel performance for leadership reviews.",
    icon: Briefcase,
    accent: "text-violet-600",
    bg: "bg-violet-50",
    sections: ["Revenue Overview", "Conversion Summary", "Channel Breakdown", "ROI Metrics"],
  },
  {
    id: "seo",
    label: "SEO Performance",
    description: "Organic rankings, traffic trends, technical health, and content performance.",
    icon: FileBarChart,
    accent: "text-green-600",
    bg: "bg-green-50",
    sections: ["Organic Traffic", "Keyword Rankings", "Technical Issues", "Page Performance"],
  },
  {
    id: "conversion",
    label: "Conversion Intelligence",
    description: "Funnel analysis, attribution models, conversion paths, and assisted conversions.",
    icon: TrendingUp,
    accent: "text-brand-600",
    bg: "bg-brand-50",
    sections: ["Funnel Overview", "Attribution Breakdown", "Conversion Paths", "Assisted Lift"],
  },
  {
    id: "local",
    label: "Local / GBP Report",
    description: "Google Business Profile insights, local rankings, reviews, and map pack visibility.",
    icon: MapPin,
    accent: "text-amber-600",
    bg: "bg-amber-50",
    sections: ["GBP Overview", "Local Rankings", "Review Summary", "Map Pack Visibility"],
  },
  {
    id: "llmo",
    label: "LLMO ROI Report",
    description: "AI attribution, citation coverage, competitive AI positioning, and revenue impact.",
    icon: Bot,
    accent: "text-violet-600",
    bg: "bg-violet-50",
    sections: ["AI Traffic Summary", "Platform Breakdown", "Citation Coverage", "AI Recommendations", "Revenue Attribution", "Growth Forecast"],
  },
];

const LAYOUT_SECTIONS: LayoutSection[] = [
  { id: "revenue-cards",     label: "Revenue Cards",         type: "card",  icon: DollarSign, description: "Total revenue, ROI, and growth KPIs" },
  { id: "conversion-cards",  label: "Conversion Cards",      type: "card",  icon: Target,     description: "Conversion counts by channel and type" },
  { id: "traffic-cards",     label: "Traffic Cards",          type: "card",  icon: Users,      description: "Users, sessions, and bounce rate" },
  { id: "channel-cards",     label: "Channel Summary Cards",  type: "card",  icon: Globe,      description: "Per-channel performance at a glance" },
  { id: "landing-table",     label: "Landing Pages Table",    type: "table", icon: Table2,     description: "Top pages by clicks, conversions, revenue" },
  { id: "conversion-table",  label: "Conversion Details Table", type: "table", icon: Table2,   description: "Channel × page × conversion type breakdown" },
  { id: "keyword-table",     label: "Keyword Rankings Table", type: "table", icon: Table2,     description: "Top keywords with position and traffic" },
  { id: "crm-table",         label: "CRM / Orders Table",     type: "table", icon: Table2,     description: "Lead or order records with status" },
  { id: "traffic-chart",     label: "Traffic Trend Chart",    type: "chart", icon: LineChart,  description: "Sessions over time by channel" },
  { id: "conversion-chart",  label: "Conversion Funnel Chart", type: "chart", icon: BarChart3, description: "Clicks → Sessions → Conversions funnel" },
  { id: "revenue-chart",     label: "Revenue Breakdown Chart", type: "chart", icon: PieChart,  description: "Revenue share by channel" },
  { id: "type-chart",        label: "Conversion Type Chart",  type: "chart", icon: BarChart3,  description: "Phone calls, forms, orders, bookings" },
  { id: "ai-traffic-cards",  label: "AI Traffic Cards",       type: "card",  icon: Bot,        description: "AI referrals, conversions, and top platform" },
  { id: "ai-citation-table", label: "AI Citation Table",      type: "table", icon: Bot,        description: "Keywords cited by AI with position and channel" },
  { id: "ai-revenue-chart",  label: "AI Revenue Chart",       type: "chart", icon: Bot,        description: "AI-attributed revenue by channel over time" },
];

const TYPE_STYLES: Record<string, { label: string; cls: string }> = {
  card:  { label: "Card",  cls: "bg-blue-50 text-blue-700"    },
  table: { label: "Table", cls: "bg-emerald-50 text-emerald-700" },
  chart: { label: "Chart", cls: "bg-orange-50 text-orange-700"  },
};

// ─── Page ─────────────────────────────────────────────────────────────────────

// Report Studio is a Growth+ feature. FeatureGate wrapper catches
// direct navigations that bypass the sidebar's locked-click handler.
export default function ReportStudioPageGated() {
  return (
    <FeatureGate feature="report_studio">
      <ReportStudioPage />
    </FeatureGate>
  );
}

function ReportStudioPage() {
  const [tab, setTab] = useState<Tab>("templates");
  const [selectedTemplate, setSelectedTemplate] = useState<string | null>(null);
  const [selectedSections, setSelectedSections] = useState<Set<string>>(new Set());
  const [aiTone, setAiTone] = useState<AiTone>("executive");
  const [enabledSources, setEnabledSources] = useState<Set<string>>(
    new Set(DATA_SOURCES.filter((s) => s.connected).map((s) => s.id))
  );
  const { brand, brands, setBrand: setSelectedBrand, isConnected } = useBrand();
  const { addTask, completeTask, failTask } = useBackgroundTasks();
  // Check real integration status for the active brand — used to warn users
  // when selected data sources won't return real data for this brand.
  const ga4Connected = isConnected("ga4");
  const gscConnected = isConnected("gsc");
  const hasMissingRequiredIntegration =
    (enabledSources.has("ga4") && !ga4Connected) ||
    (enabledSources.has("gsc") && !gscConnected);
  const [reportName, setReportName] = useState(`${brand.name} — Monthly SEO Report`);
  const [dateRange, setDateRange] = useState("30d");
  const [brandDropdown, setBrandDropdown] = useState(false);
  const [saveNotice, setSaveNotice] = useState<string | null>(null);

  // Build state. `report` holds the BrandReport shape returned by
  // /api/report-studio/generate — when non-null the Preview section
  // renders its executive summary + KPIs + wins/opportunities
  // straight from live data instead of the "Draft Saved" placeholder.
  // `hasBuiltReport` stays as a separate boolean so a user who
  // previously built a report sees their result on re-mount even if
  // they haven't rebuilt it in this session (report is in-memory —
  // a future enhancement could persist to DB for cross-session).
  const [building, setBuilding] = useState(false);
  const [buildError, setBuildError] = useState<string | null>(null);
  const [hasBuiltReport, setHasBuiltReport] = useState(false);
  type ReportShape = {
    generatedAt: string;
    dateRange: { start: string; end: string; days: number };
    brand: { id: string; name: string; domain: string };
    executiveSummary: {
      narrative: string;
      healthScore: number | null;
      kpis: Array<{ label: string; value: number; unit?: string; changePct?: number | null; direction?: "up" | "down" | "flat" }>;
      topWin: string | null;
      topConcern: string | null;
      topOpportunity: string | null;
    };
    wins?: { topPages?: Array<{ url: string; clicks: number; position: number }>; topKeywords?: Array<{ query: string; clicks: number; position: number }> };
    sources?: Record<string, boolean>;
  };
  const [report, setReport] = useState<ReportShape | null>(null);
  const [summaryCopied, setSummaryCopied] = useState(false);

  // PPTX export state
  const [exportingPptx, setExportingPptx] = useState(false);
  const [exportError, setExportError] = useState<string | null>(null);

  async function handleExportPptx() {
    if (exportingPptx) return;
    setExportingPptx(true);
    setExportError(null);
    try {
      // Generate report JSON on the server, then hand it off to the PPTX
      // serialiser in a second call. Keeps the PPTX route stateless.
      const days = dateRange === "7d" ? 7 : dateRange === "90d" ? 90 : dateRange === "12m" ? 365 : 30;
      const reportRes = await fetch("/api/report-studio/export", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ brandId: brand.id, dateRange: days, format: "json" }),
      });
      if (!reportRes.ok) {
        const data = await reportRes.json().catch(() => ({}));
        throw new Error(data.error || "Failed to generate report");
      }
      const { report } = await reportRes.json();

      const pptxRes = await fetch("/api/report-studio/export/pptx", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          report,
          brand: { name: brand.name, domain: brand.domain },
        }),
      });
      if (!pptxRes.ok) {
        const data = await pptxRes.json().catch(() => ({}));
        throw new Error(data.error || "Failed to export PPTX");
      }

      const blob = await pptxRes.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `${brand.name.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-report-${report.dateRange.end}.pptx`;
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch (err) {
      setExportError(err instanceof Error ? err.message : "Export failed");
    }
    setExportingPptx(false);
  }

  const canBuild =
    !building &&
    selectedSections.size > 0 &&
    enabledSources.size > 0 &&
    !!reportName.trim();

  async function handleBuildReport() {
    if (!canBuild) return;
    console.info("[report-studio] Generate clicked", {
      template: selectedTemplate,
      dateRange,
      dataSources: Array.from(enabledSources),
      sections: Array.from(selectedSections),
      aiTone,
    });
    setBuilding(true);
    setBuildError(null);
    const taskId = addTask({ id: `report_${Date.now()}`, type: "report_generation", label: "Building Report...", brandId: brand.id, resultUrl: "/report-studio" });
    try {
      // Map the UI's dateRange string to a day count the server
      // expects. Defaults to 28 for unknown values (same fallback
      // the server uses, so parity guaranteed).
      const days = dateRange === "7d" ? 7 : dateRange === "90d" ? 90 : dateRange === "12m" ? 365 : 28;

      // Translate selectedSections (custom-layout tab) into the
      // ReportSectionKey set the server knows about. Unknown ids
      // drop out silently; passing undefined runs all sections.
      const sectionMap: Record<string, string> = {
        "revenue-cards": "executive_summary",
        "conversion-cards": "executive_summary",
        "traffic-cards": "executive_summary",
        "channel-cards": "executive_summary",
        "landing-table": "wins",
        "conversion-table": "wins",
        "keyword-table": "wins",
        "crm-table": "appendix",
        "traffic-chart": "executive_summary",
        "conversion-chart": "executive_summary",
        "revenue-chart": "executive_summary",
        "type-chart": "executive_summary",
      };
      const sectionKeys = selectedSections.size > 0
        ? Array.from(new Set(Array.from(selectedSections).map((s) => sectionMap[s]).filter(Boolean)))
        : undefined;

      const res = await fetch("/api/report-studio/generate", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ brandId: brand.id, dateRange: days, sections: sectionKeys }),
      });

      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        setBuildError(data.error || "Failed to build report. Please try again.");
        setBuilding(false);
        failTask(taskId, data.error || "Failed to build report");
        return;
      }

      const data = await res.json() as { report?: ReportShape };
      if (!data.report) {
        setBuildError("Report generated but response was malformed.");
        setBuilding(false);
        failTask(taskId, "Malformed response");
        return;
      }

      setReport(data.report);
      setHasBuiltReport(true);
      completeTask(taskId, { resultUrl: "/report-studio", resultSummary: `Report "${reportName.trim()}" built with ${data.report.executiveSummary.kpis.length} KPIs` });
    } catch (err) {
      setBuildError(err instanceof Error ? err.message : "Network error. Please try again.");
      failTask(taskId, err instanceof Error ? err.message : "Network error");
    }
    setBuilding(false);
  }

  /** Copy the AI executive summary narrative (real, not placeholder)
   *  to the clipboard. Falls back to the current tone's placeholder
   *  copy when no report has been built yet — still gives users
   *  something to paste for demo/preview purposes. */
  async function handleCopySummary() {
    const text = report?.executiveSummary?.narrative?.trim() || AI_SUMMARY_PLACEHOLDERS[aiTone];
    try {
      if (typeof navigator !== "undefined" && navigator.clipboard) {
        await navigator.clipboard.writeText(text);
      } else {
        const ta = document.createElement("textarea");
        ta.value = text;
        document.body.appendChild(ta);
        ta.select();
        document.execCommand("copy");
        document.body.removeChild(ta);
      }
      setSummaryCopied(true);
      setTimeout(() => setSummaryCopied(false), 2000);
    } catch {
      setBuildError("Copy failed — clipboard may be blocked in this context.");
    }
  }

  /** Regenerate the executive summary. If no report has been built
   *  yet, triggers a full build (the summary rides along). If a
   *  report already exists, this re-runs the whole pipeline — there's
   *  no cheaper tone-only endpoint, and a regenerate-from-same-inputs
   *  is effectively a fresh build anyway. Gated on canBuild so we
   *  don't fire with missing required inputs. */
  async function handleRegenerateSummary() {
    if (!canBuild || building) return;
    await handleBuildReport();
  }

  function toggleSource(id: string) {
    const source = DATA_SOURCES.find((s) => s.id === id);
    if (!source?.connected) return;
    setEnabledSources((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }

  function toggleSection(id: string) {
    setSelectedSections((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }

  return (
    <div className="space-y-6">
      {/* ── Report Builder Header ── */}
      <div className="bg-gradient-to-r from-slate-900 to-slate-800 rounded-2xl px-6 py-5 shadow-lg">
        {/* Top row: icon + title + save */}
        <div className="flex items-center gap-3 mb-4">
          <div className="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center shrink-0">
            <ClipboardList className="w-5 h-5 text-white" />
          </div>
          <div className="flex-1">
            <p className="text-slate-400 text-[10px] font-semibold uppercase tracking-widest">Report Studio</p>
            <p className="text-white text-sm font-bold">Build and customize reports</p>
          </div>
          <button
            onClick={() => { setSaveNotice("Template saved!"); setTimeout(() => setSaveNotice(null), 2500); }}
            className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors ${
              saveNotice
                ? "bg-green-500 text-white"
                : "bg-white/10 text-white hover:bg-white/20"
            }`}
          >
            {saveNotice ? <CheckCircle2 className="w-4 h-4" /> : <Save className="w-4 h-4" />}
            {saveNotice || "Save Template"}
          </button>
        </div>

        {/* Report name input */}
        <div className="mb-4">
          <input
            type="text"
            value={reportName}
            onChange={(e) => setReportName(e.target.value)}
            placeholder="Report name..."
            className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-2.5 text-white text-sm font-medium placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-brand-500/50 focus:border-white/20 transition"
          />
        </div>

        {/* Controls row: brand + date range */}
        <div className="flex items-center gap-3 flex-wrap">
          {/* Brand selector */}
          <div className="relative">
            <button
              onClick={() => setBrandDropdown(!brandDropdown)}
              className="flex items-center gap-2 px-3 py-2 rounded-lg bg-white/10 border border-white/10 text-sm font-medium text-white hover:bg-white/15 transition-colors"
            >
              <div className={`w-6 h-6 rounded ${brand.color} flex items-center justify-center shrink-0`}>
                <span className="text-[8px] font-bold text-white">{brand.initials}</span>
              </div>
              <span>{brand.name}</span>
              <ChevronDown className={`w-3.5 h-3.5 text-slate-400 transition-transform ${brandDropdown ? "rotate-180" : ""}`} />
            </button>

            {brandDropdown && (
              <>
                <div className="fixed inset-0 z-40" onClick={() => setBrandDropdown(false)} />
                <div className="absolute top-full left-0 mt-1.5 bg-white border border-slate-200 rounded-xl shadow-lg py-1.5 z-50 min-w-[220px]">
                  <p className="px-3 py-1.5 text-[10px] font-bold uppercase tracking-widest text-slate-400">Select Brand</p>
                  {brands.map((b) => (
                    <button
                      key={b.id}
                      onClick={() => { setSelectedBrand(b); setBrandDropdown(false); setReportName(`${b.name} — Monthly SEO Report`); }}
                      className={`w-full flex items-center gap-2.5 px-3 py-2 transition-colors ${b.id === brand.id ? "bg-brand-50" : "hover:bg-slate-50"}`}
                    >
                      <div className={`w-7 h-7 rounded-lg ${b.color} flex items-center justify-center shrink-0`}>
                        <span className="text-[10px] font-bold text-white">{b.initials}</span>
                      </div>
                      <div className="text-left">
                        <p className={`text-sm font-semibold ${b.id === brand.id ? "text-brand-700" : "text-slate-800"}`}>{b.name}</p>
                        <p className="text-[10px] text-slate-400">{b.domain}</p>
                      </div>
                      {b.id === brand.id && <Check className="w-4 h-4 text-brand-600 ml-auto" />}
                    </button>
                  ))}
                </div>
              </>
            )}
          </div>

          {/* Date range selector */}
          <div className="flex items-center bg-white/10 rounded-lg p-0.5 gap-0.5">
            {[
              { key: "7d", label: "7 Days" },
              { key: "30d", label: "30 Days" },
              { key: "90d", label: "90 Days" },
              { key: "12m", label: "12 Months" },
            ].map((r) => (
              <button
                key={r.key}
                onClick={() => setDateRange(r.key)}
                className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-semibold transition-colors ${
                  dateRange === r.key
                    ? "bg-white text-slate-900 shadow-sm"
                    : "text-slate-400 hover:text-white"
                }`}
              >
                {r.key === dateRange && <Calendar className="w-3 h-3" />}
                {r.label}
              </button>
            ))}
          </div>

          {/* Report info pills */}
          <div className="flex items-center gap-2 ml-auto">
            <span className="flex items-center gap-1.5 text-[11px] font-semibold text-emerald-400 bg-emerald-500/15 border border-emerald-500/25 px-2.5 py-1 rounded-lg">
              <Database className="w-3 h-3" />
              {enabledSources.size} sources
            </span>
            <span className="flex items-center gap-1.5 text-[11px] font-semibold text-sky-400 bg-sky-500/15 border border-sky-500/25 px-2.5 py-1 rounded-lg">
              <BarChart3 className="w-3 h-3" />
              {selectedSections.size || "0"} sections
            </span>
          </div>
        </div>
      </div>

      {/* ── Data Sources ── */}
      <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
        <div className="px-6 py-4 border-b border-slate-100 flex items-center gap-2">
          <Database className="w-4 h-4 text-brand-600" />
          <h2 className="font-semibold text-slate-800 text-sm">Data Sources</h2>
          <span className="ml-auto text-xs text-slate-400">
            {DATA_SOURCES.filter((s) => s.connected).length} of {DATA_SOURCES.length} connected
          </span>
        </div>

        <div className="divide-y divide-slate-100">
          {DATA_SOURCES.map((src) => {
            const Icon = src.icon;
            const isEnabled = enabledSources.has(src.id);
            return (
              <div key={src.id} className="px-6 py-3.5 flex items-center gap-4">
                <div className={`w-9 h-9 rounded-lg ${src.bg} flex items-center justify-center shrink-0`}>
                  <Icon className={`w-4.5 h-4.5 ${src.accent}`} />
                </div>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <span className="text-sm font-semibold text-slate-800">{src.label}</span>
                    {src.connected ? (
                      <span className="inline-flex items-center gap-1 text-[10px] font-semibold text-green-700 bg-green-50 rounded-full px-2 py-0.5">
                        <CheckCircle2 className="w-3 h-3" />
                        Connected
                      </span>
                    ) : (
                      <span className="inline-flex items-center gap-1 text-[10px] font-semibold text-slate-400 bg-slate-100 rounded-full px-2 py-0.5">
                        <XCircle className="w-3 h-3" />
                        Not Connected
                      </span>
                    )}
                  </div>
                  <p className="text-xs text-slate-500 mt-0.5">{src.description}</p>
                </div>
                {/* Toggle */}
                <button
                  onClick={() => toggleSource(src.id)}
                  disabled={!src.connected}
                  className={`relative w-10 h-[22px] rounded-full transition-colors shrink-0 ${
                    !src.connected
                      ? "bg-slate-100 cursor-not-allowed"
                      : isEnabled
                        ? "bg-brand-500"
                        : "bg-slate-300"
                  }`}
                >
                  <span
                    className={`absolute top-[3px] w-4 h-4 rounded-full bg-white shadow-sm transition-transform ${
                      isEnabled && src.connected ? "translate-x-[22px]" : "translate-x-[3px]"
                    }`}
                  />
                </button>
              </div>
            );
          })}
        </div>
      </div>

      {/* ── Tab toggle ── */}
      <div className="flex items-center bg-slate-100 rounded-xl p-1 gap-1 w-fit">
        <button
          onClick={() => setTab("templates")}
          className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors ${
            tab === "templates"
              ? "bg-white text-slate-900 shadow-sm"
              : "text-slate-500 hover:text-slate-700"
          }`}
        >
          <LayoutTemplate className="w-4 h-4" />
          Template Selection
        </button>
        <button
          onClick={() => setTab("custom")}
          className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-semibold transition-colors ${
            tab === "custom"
              ? "bg-white text-slate-900 shadow-sm"
              : "text-slate-500 hover:text-slate-700"
          }`}
        >
          <SlidersHorizontal className="w-4 h-4" />
          Custom Layout
        </button>
      </div>

      {/* ── Template Selection ── */}
      {tab === "templates" && (
        <div className="space-y-4">
          <p className="text-sm text-slate-500">Choose a pre-built report template to get started.</p>

          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
            {TEMPLATES.map((tmpl) => {
              const Icon = tmpl.icon;
              const isSelected = selectedTemplate === tmpl.id;
              return (
                <button
                  key={tmpl.id}
                  onClick={() => setSelectedTemplate(isSelected ? null : tmpl.id)}
                  className={`text-left bg-white rounded-xl border-2 px-5 py-4 transition-all ${
                    isSelected
                      ? "border-brand-500 shadow-sm"
                      : "border-slate-200 hover:border-slate-300"
                  }`}
                >
                  <div className="flex items-start gap-3">
                    <div className={`w-10 h-10 rounded-xl ${tmpl.bg} flex items-center justify-center shrink-0 mt-0.5`}>
                      <Icon className={`w-5 h-5 ${tmpl.accent}`} />
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center justify-between gap-2">
                        <h3 className="text-sm font-bold text-slate-900">{tmpl.label}</h3>
                        {isSelected && (
                          <div className="w-5 h-5 rounded-full bg-brand-500 flex items-center justify-center shrink-0">
                            <Check className="w-3 h-3 text-white" />
                          </div>
                        )}
                      </div>
                      <p className="text-xs text-slate-500 mt-1">{tmpl.description}</p>
                      <div className="flex flex-wrap gap-1.5 mt-3">
                        {tmpl.sections.map((s) => (
                          <span key={s} className="text-[10px] font-semibold text-slate-500 bg-slate-100 rounded-md px-2 py-0.5">
                            {s}
                          </span>
                        ))}
                      </div>
                    </div>
                  </div>
                </button>
              );
            })}
          </div>

          {selectedTemplate && (
            <div className="bg-brand-50 border border-brand-100 rounded-xl px-5 py-3 flex items-center justify-between">
              <p className="text-sm text-brand-700">
                <span className="font-semibold">{TEMPLATES.find((t) => t.id === selectedTemplate)?.label}</span> template selected — ready to generate.
              </p>
              <button className="px-4 py-2 bg-brand-600 text-white text-sm font-semibold rounded-lg hover:bg-brand-700 transition-colors">
                Generate Report
              </button>
            </div>
          )}
        </div>
      )}

      {/* ── Custom Layout ── */}
      {tab === "custom" && (
        <div className="space-y-4">
          <p className="text-sm text-slate-500">
            Pick the sections you want in your report. Mix cards, tables, and charts.
          </p>

          {/* Selected count + Build action */}
          <div className={`rounded-xl border px-5 py-3 flex items-center justify-between gap-3 flex-wrap ${
            selectedSections.size > 0 ? "bg-brand-50 border-brand-100" : "bg-slate-50 border-slate-200"
          }`}>
            <div className="flex items-center gap-2 min-w-0">
              <p className={`text-sm ${selectedSections.size > 0 ? "text-brand-700" : "text-slate-500"}`}>
                <span className="font-semibold">{selectedSections.size}</span> section{selectedSections.size !== 1 ? "s" : ""} selected
              </p>
              {enabledSources.size === 0 && (
                <span className="text-[11px] text-amber-600">· No data sources enabled</span>
              )}
              {!reportName.trim() && (
                <span className="text-[11px] text-amber-600">· Report name required</span>
              )}
            </div>
            <div className="flex items-center gap-2">
              {!canBuild && selectedSections.size === 0 && (
                <span className="text-[11px] text-slate-400">Select at least one section to build a report</span>
              )}
              <button
                onClick={handleBuildReport}
                disabled={!canBuild}
                className={`inline-flex items-center gap-1.5 px-4 py-2 text-sm font-semibold rounded-lg transition-colors ${
                  canBuild
                    ? "bg-brand-600 text-white hover:bg-brand-700"
                    : "bg-slate-200 text-slate-400 cursor-not-allowed opacity-50"
                }`}
              >
                {building ? <Loader2 className="w-4 h-4 animate-spin" /> : <FileBarChart className="w-4 h-4" />}
                {building
                  ? "Generating report…"
                  : selectedSections.size > 0
                    ? `Build Report (${selectedSections.size} section${selectedSections.size === 1 ? "" : "s"})`
                    : "Build Report"}
              </button>
            </div>
          </div>

          {/* Integration-missing warning */}
          {hasMissingRequiredIntegration && (
            <div className="flex items-start gap-2 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3">
              <AlertCircle className="w-4 h-4 text-amber-600 shrink-0 mt-0.5" />
              <div className="text-xs text-amber-700 leading-relaxed">
                <p className="font-semibold">Some sections require connected integrations for real data</p>
                <p className="mt-0.5">
                  {enabledSources.has("ga4") && !ga4Connected && "GA4 is not connected for this brand. "}
                  {enabledSources.has("gsc") && !gscConnected && "GSC is not connected for this brand. "}
                  Connect in <a href="/integrations" className="font-semibold underline hover:no-underline">Integrations</a>, or deselect those sources below to build a report without them.
                </p>
              </div>
            </div>
          )}

          {/* Build error */}
          {buildError && (
            <div className="flex items-start gap-2 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3">
              <AlertCircle className="w-4 h-4 text-amber-600 shrink-0 mt-0.5" />
              <p className="text-xs text-amber-700 leading-relaxed">{buildError}</p>
            </div>
          )}

          {/* Section grid */}
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
            {LAYOUT_SECTIONS.map((section) => {
              const Icon = section.icon;
              const isSelected = selectedSections.has(section.id);
              const typeStyle = TYPE_STYLES[section.type];
              return (
                <button
                  key={section.id}
                  onClick={() => toggleSection(section.id)}
                  className={`text-left bg-white rounded-xl border-2 px-4 py-3.5 transition-all ${
                    isSelected
                      ? "border-brand-500 shadow-sm"
                      : "border-slate-200 hover:border-slate-300"
                  }`}
                >
                  <div className="flex items-start justify-between gap-2">
                    <div className="flex items-center gap-2">
                      <Icon className="w-4 h-4 text-slate-400 shrink-0" />
                      <span className="text-sm font-semibold text-slate-800">{section.label}</span>
                    </div>
                    {isSelected ? (
                      <div className="w-5 h-5 rounded-full bg-brand-500 flex items-center justify-center shrink-0">
                        <Check className="w-3 h-3 text-white" />
                      </div>
                    ) : (
                      <div className="w-5 h-5 rounded-full border-2 border-slate-200 shrink-0" />
                    )}
                  </div>
                  <p className="text-[11px] text-slate-500 mt-1.5 ml-6">{section.description}</p>
                  <div className="mt-2 ml-6">
                    <span className={`text-[10px] font-semibold rounded-md px-2 py-0.5 ${typeStyle.cls}`}>
                      {typeStyle.label}
                    </span>
                  </div>
                </button>
              );
            })}
          </div>
        </div>
      )}
      {/* ── AI Executive Summary ── */}
      <div className="bg-white rounded-2xl border border-slate-200 overflow-hidden shadow-sm">
        {/* Section header */}
        <div className="px-6 py-5 bg-gradient-to-r from-brand-50/80 to-violet-50/80 border-b border-brand-100">
          <div className="flex items-start gap-3">
            <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-brand-500 to-violet-600 flex items-center justify-center shrink-0 shadow-sm">
              <Sparkles className="w-5 h-5 text-white" />
            </div>
            <div className="flex-1">
              <h2 className="text-lg font-bold text-slate-900">AI Executive Summary</h2>
              <p className="text-xs text-slate-500 mt-0.5">AI-generated narrative summarizing key performance insights for client presentations.</p>
            </div>
            <span className="text-[10px] font-semibold text-brand-600 bg-brand-100 border border-brand-200 rounded-full px-2.5 py-0.5 shrink-0">AI-powered</span>
          </div>
        </div>

        {/* Tone + regenerate */}
        <div className="px-6 py-3 border-b border-slate-100 flex items-center gap-3 flex-wrap">
          <span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Tone</span>
          <div className="flex items-center bg-slate-100 rounded-lg p-0.5 gap-0.5">
            {(Object.keys(AI_TONE_LABELS) as AiTone[]).map((tone) => (
              <button
                key={tone}
                onClick={() => setAiTone(tone)}
                className={`px-3 py-1.5 rounded-md text-xs font-semibold transition-colors ${
                  aiTone === tone
                    ? "bg-white text-slate-900 shadow-sm"
                    : "text-slate-500 hover:text-slate-700"
                }`}
              >
                {AI_TONE_LABELS[tone]}
              </button>
            ))}
          </div>
          {/* Regenerate re-runs the whole build pipeline with the
              currently-selected tone + sources + range. Disabled
              while building so a double-click can't queue duplicate
              Claude calls. */}
          <button
            onClick={handleRegenerateSummary}
            disabled={building || !canBuild}
            className="ml-auto flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-semibold text-slate-600 hover:bg-slate-50 transition-colors disabled:opacity-50"
          >
            <RefreshCw className={`w-3 h-3 ${building ? "animate-spin" : ""}`} />
            {building ? "Generating…" : "Regenerate"}
          </button>
        </div>

        {/* Summary text — client-facing card */}
        <div className="px-6 py-6">
          <div className="bg-gradient-to-br from-slate-50 to-white rounded-xl border border-slate-200 px-6 py-5 shadow-inner">
            <div className="flex items-center gap-2 mb-3">
              <div className="w-6 h-6 rounded bg-gradient-to-br from-brand-500 to-violet-600 flex items-center justify-center">
                <Sparkles className="w-3 h-3 text-white" />
              </div>
              <span className="text-[10px] font-bold uppercase tracking-widest text-slate-400">Performance Summary</span>
              <span className="text-[10px] text-slate-300 ml-auto">{brand.name} — Last {dateRange === "7d" ? "7 days" : dateRange === "30d" ? "30 days" : dateRange === "90d" ? "90 days" : "12 months"}</span>
            </div>
            {/* Placeholder copy until real AI-summary generation is
                wired. The tone buttons above still switch variants so
                the UI exercise remains useful for preview and testing.
                Italic + muted colour signals "preview, not live data"
                visually; the copy itself explicitly says so.
                When a report HAS been built, we swap to the real
                AI narrative (no italic, full slate-700) so users
                can read + copy the actual generated copy.
            */}
            {report?.executiveSummary?.narrative?.trim() ? (
              <p className="text-sm text-slate-700 leading-relaxed whitespace-pre-wrap">{report.executiveSummary.narrative}</p>
            ) : (
              <p className="text-sm text-slate-500 italic leading-relaxed">{AI_SUMMARY_PLACEHOLDERS[aiTone]}</p>
            )}
          </div>
        </div>
      </div>

      {/* ── Export Actions ── */}
      <div className="bg-white rounded-2xl border border-slate-200 overflow-hidden shadow-sm">
        <div className="px-6 py-4 border-b border-slate-100 flex items-center gap-3">
          <div className="w-9 h-9 rounded-lg bg-emerald-50 flex items-center justify-center shrink-0">
            <FileDown className="w-4.5 h-4.5 text-emerald-600" />
          </div>
          <div>
            <h2 className="font-bold text-slate-900 text-base">Export Report</h2>
            <p className="text-xs text-slate-500">Share with clients, stakeholders, or your team.</p>
          </div>
        </div>

        {/* Primary + secondary export actions */}
        <div className="px-6 py-5">
          <div className="grid grid-cols-2 lg:grid-cols-5 gap-3">
            <button className="flex flex-col items-center gap-2 px-4 py-4 bg-brand-600 text-white rounded-xl hover:bg-brand-700 transition-colors shadow-sm">
              <FileDown className="w-5 h-5" />
              <span className="text-xs font-semibold">Export PDF</span>
              <span className="text-[10px] text-brand-200">Client-ready</span>
            </button>
            <button
              onClick={handleExportPptx}
              disabled={exportingPptx}
              className="flex flex-col items-center gap-2 px-4 py-4 bg-white border border-slate-200 rounded-xl hover:bg-slate-50 hover:border-slate-300 transition-colors disabled:opacity-60 disabled:cursor-not-allowed"
            >
              {exportingPptx ? (
                <Loader2 className="w-5 h-5 text-orange-600 animate-spin" />
              ) : (
                <Presentation className="w-5 h-5 text-orange-600" />
              )}
              <span className="text-xs font-semibold text-slate-700">
                {exportingPptx ? "Exporting…" : "Export PPTX"}
              </span>
              <span className="text-[10px] text-slate-400">PowerPoint</span>
            </button>
            <button className="flex flex-col items-center gap-2 px-4 py-4 bg-white border border-slate-200 rounded-xl hover:bg-slate-50 hover:border-slate-300 transition-colors">
              <FileText className="w-5 h-5 text-blue-600" />
              <span className="text-xs font-semibold text-slate-700">Google Docs</span>
              <span className="text-[10px] text-slate-400">Editable</span>
            </button>
            <button className="flex flex-col items-center gap-2 px-4 py-4 bg-white border border-slate-200 rounded-xl hover:bg-slate-50 hover:border-slate-300 transition-colors">
              <TableProperties className="w-5 h-5 text-emerald-600" />
              <span className="text-xs font-semibold text-slate-700">CSV / Excel</span>
              <span className="text-[10px] text-slate-400">Raw data</span>
            </button>
            {/* Copy Summary — copies the real AI narrative when a
                report has been built, falling back to the tone's
                placeholder copy otherwise (gives users something to
                paste even on empty-state / demo flows). */}
            <button
              onClick={handleCopySummary}
              className="flex flex-col items-center gap-2 px-4 py-4 bg-white border border-slate-200 rounded-xl hover:bg-slate-50 hover:border-slate-300 transition-colors"
            >
              {summaryCopied ? <Check className="w-5 h-5 text-green-600" /> : <Copy className="w-5 h-5 text-violet-600" />}
              <span className="text-xs font-semibold text-slate-700">{summaryCopied ? "Copied!" : "Copy Summary"}</span>
              <span className="text-[10px] text-slate-400">Clipboard</span>
            </button>
          </div>
          {exportError && (
            <div className="mt-3 flex items-center gap-2 text-xs text-red-700 bg-red-50 border border-red-200 rounded-lg px-3 py-2">
              <AlertCircle className="w-3.5 h-3.5 shrink-0" />
              <span>{exportError}</span>
            </div>
          )}
        </div>
      </div>

      {/* ── Report Preview ── */}
      <div className="bg-white rounded-2xl border border-slate-200 overflow-hidden shadow-sm">
        <div className="px-6 py-4">
          <div className="flex items-center gap-2 mb-3">
            <Eye className="w-3.5 h-3.5 text-slate-400" />
            <span className="text-xs font-bold uppercase tracking-widest text-slate-400">Report Preview</span>
          </div>

          {!hasBuiltReport && !DEV_MOCK_ENABLED ? (
            /* Empty state — no report built yet */
            <div className="border border-dashed border-slate-200 rounded-xl bg-slate-50/50 px-6 py-16 text-center">
              <div className="w-14 h-14 rounded-2xl bg-white border border-slate-200 flex items-center justify-center mx-auto mb-4">
                <FileBarChart className="w-7 h-7 text-slate-300" />
              </div>
              <h3 className="text-sm font-bold text-slate-700 mb-1">No Reports Yet</h3>
              <p className="text-xs text-slate-500 max-w-sm mx-auto leading-relaxed">
                Build your first report by selecting sections and clicking <span className="font-semibold text-slate-700">Build Report</span>. Your preview will appear here.
              </p>
              {selectedSections.size === 0 && (
                <p className="text-[10px] text-slate-400 mt-3">Tip: switch to the <span className="font-semibold">Custom Layout</span> tab to pick sections.</p>
              )}
            </div>
          ) : hasBuiltReport && report && !DEV_MOCK_ENABLED ? (
            /* Built — render the real BrandReport from
               /api/report-studio/generate. Gradient header +
               brand-scoped metadata, then executive summary,
               health score + KPIs, topWin / topConcern /
               topOpportunity cards, and finally top pages +
               top keywords tables from wins. */
            <div className="border border-slate-200 rounded-xl overflow-hidden bg-white shadow-sm">
              <div className="bg-gradient-to-r from-brand-600 to-violet-600 px-6 py-5">
                <p className="text-[10px] font-semibold text-white/60 uppercase tracking-widest">
                  {report.brand.name} — meSEO Report
                </p>
                <p className="text-lg font-bold text-white mt-0.5">
                  {selectedTemplate
                    ? TEMPLATES.find((t) => t.id === selectedTemplate)?.label ?? "Performance Report"
                    : "Performance Report"}
                </p>
                <p className="text-[11px] text-white/70 mt-1">
                  {report.dateRange.start} → {report.dateRange.end} · {report.dateRange.days} days · generated {new Date(report.generatedAt).toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" })}
                </p>
              </div>

              <div className="px-6 py-5 space-y-5">
                {/* Executive narrative */}
                {report.executiveSummary.narrative && (
                  <div>
                    <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-1.5">Executive Summary</p>
                    <p className="text-sm text-slate-700 leading-relaxed whitespace-pre-wrap">{report.executiveSummary.narrative}</p>
                  </div>
                )}

                {/* KPI grid — one row per 4 columns. Source of truth
                    is the server's ReportKpi[] so we just render what
                    came back; no client-side math. */}
                {report.executiveSummary.kpis.length > 0 && (
                  <div>
                    <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-2">Key Metrics</p>
                    <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
                      {report.executiveSummary.kpis.map((kpi, i) => (
                        <div key={i} className="bg-slate-50 rounded-lg px-3 py-2.5">
                          <p className="text-[10px] text-slate-400 font-semibold uppercase">{kpi.label}</p>
                          <p className="text-lg font-bold text-slate-900 mt-0.5 tabular-nums">
                            {kpi.value.toLocaleString()}{kpi.unit ?? ""}
                          </p>
                          {typeof kpi.changePct === "number" && (
                            <p className={`text-[10px] font-semibold ${
                              kpi.direction === "up" ? "text-green-600"
                              : kpi.direction === "down" ? "text-red-600"
                              : "text-slate-500"
                            }`}>
                              {kpi.changePct > 0 ? "+" : ""}{kpi.changePct.toFixed(1)}% vs prev
                            </p>
                          )}
                        </div>
                      ))}
                    </div>
                  </div>
                )}

                {/* Top win / concern / opportunity callouts. Each
                    only renders when populated so a brand with only
                    one of the three doesn't get empty-card noise. */}
                {(report.executiveSummary.topWin || report.executiveSummary.topConcern || report.executiveSummary.topOpportunity) && (
                  <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                    {report.executiveSummary.topWin && (
                      <div className="bg-green-50 border border-green-200 rounded-lg px-3 py-2.5">
                        <p className="text-[10px] font-bold uppercase tracking-widest text-green-700">Top Win</p>
                        <p className="text-xs text-green-900 mt-1 leading-relaxed">{report.executiveSummary.topWin}</p>
                      </div>
                    )}
                    {report.executiveSummary.topConcern && (
                      <div className="bg-red-50 border border-red-200 rounded-lg px-3 py-2.5">
                        <p className="text-[10px] font-bold uppercase tracking-widest text-red-700">Top Concern</p>
                        <p className="text-xs text-red-900 mt-1 leading-relaxed">{report.executiveSummary.topConcern}</p>
                      </div>
                    )}
                    {report.executiveSummary.topOpportunity && (
                      <div className="bg-blue-50 border border-blue-200 rounded-lg px-3 py-2.5">
                        <p className="text-[10px] font-bold uppercase tracking-widest text-blue-700">Top Opportunity</p>
                        <p className="text-xs text-blue-900 mt-1 leading-relaxed">{report.executiveSummary.topOpportunity}</p>
                      </div>
                    )}
                  </div>
                )}

                {/* Top pages + top keywords tables — only when the
                    wins section came back populated. Renders at most
                    5 rows each to keep the preview compact; a future
                    Export PDF will dump the full list. */}
                {report.wins?.topPages && report.wins.topPages.length > 0 && (
                  <div>
                    <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-2">Top Pages by Clicks</p>
                    <div className="border border-slate-200 rounded-lg overflow-hidden">
                      <table className="w-full text-xs">
                        <thead className="bg-slate-50">
                          <tr className="text-left text-[10px] font-bold uppercase tracking-wider text-slate-400">
                            <th className="px-3 py-2">URL</th>
                            <th className="px-3 py-2 text-right">Clicks</th>
                            <th className="px-3 py-2 text-right">Position</th>
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-slate-100">
                          {report.wins.topPages.slice(0, 5).map((p, i) => (
                            <tr key={i}>
                              <td className="px-3 py-1.5 font-mono text-slate-700 truncate max-w-[300px]" title={p.url}>
                                {p.url.replace(/^https?:\/\/[^/]+/, "") || "/"}
                              </td>
                              <td className="px-3 py-1.5 text-right tabular-nums font-semibold text-slate-800">{p.clicks.toLocaleString()}</td>
                              <td className="px-3 py-1.5 text-right tabular-nums text-slate-600">{p.position.toFixed(1)}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                )}

                {report.wins?.topKeywords && report.wins.topKeywords.length > 0 && (
                  <div>
                    <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-2">Top Keywords by Clicks</p>
                    <div className="border border-slate-200 rounded-lg overflow-hidden">
                      <table className="w-full text-xs">
                        <thead className="bg-slate-50">
                          <tr className="text-left text-[10px] font-bold uppercase tracking-wider text-slate-400">
                            <th className="px-3 py-2">Query</th>
                            <th className="px-3 py-2 text-right">Clicks</th>
                            <th className="px-3 py-2 text-right">Position</th>
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-slate-100">
                          {report.wins.topKeywords.slice(0, 5).map((k, i) => (
                            <tr key={i}>
                              <td className="px-3 py-1.5 text-slate-700 truncate max-w-[300px]" title={k.query}>{k.query}</td>
                              <td className="px-3 py-1.5 text-right tabular-nums font-semibold text-slate-800">{k.clicks.toLocaleString()}</td>
                              <td className="px-3 py-1.5 text-right tabular-nums text-slate-600">{k.position.toFixed(1)}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                )}
              </div>
            </div>
          ) : hasBuiltReport && !DEV_MOCK_ENABLED ? (
            /* Built state but report payload missing (shouldn't happen
               given handleBuildReport sets both together, but defence-
               in-depth for a future refactor). */
            <div className="border border-slate-200 rounded-xl bg-white px-6 py-12 text-center">
              <div className="w-14 h-14 rounded-2xl bg-brand-50 border border-brand-200 flex items-center justify-center mx-auto mb-4">
                <FileBarChart className="w-7 h-7 text-brand-600" />
              </div>
              <h3 className="text-sm font-bold text-slate-700 mb-1">Report Built</h3>
              <p className="text-xs text-slate-500 max-w-md mx-auto leading-relaxed">
                Report data missing from preview — rebuild to refresh.
              </p>
            </div>
          ) : (
          <div className="border border-slate-200 rounded-xl overflow-hidden bg-white shadow-sm">
            {/* Dev-mock report header */}
            <div className="bg-gradient-to-r from-brand-600 to-violet-600 px-6 py-5">
              <p className="text-[10px] font-semibold text-white/60 uppercase tracking-widest">{brand.name} — meSEO Report</p>
              <p className="text-lg font-bold text-white mt-0.5">
                {selectedTemplate
                  ? TEMPLATES.find((t) => t.id === selectedTemplate)?.label ?? "Custom Report"
                  : selectedSections.size > 0
                    ? "Custom Report"
                    : "Executive Summary"}
              </p>
              <p className="text-xs text-white/70 mt-1">{brand.domain} &middot; Generated Mar 25, 2026 &middot; Last 30 days</p>
            </div>

            {/* Dev-mock report body */}
            <div className="px-6 py-5 space-y-4">
              {/* KPI row */}
              <div className="grid grid-cols-4 gap-3">
                {[
                  { label: "Conversions", value: "487", change: "+18%" },
                  { label: "Revenue",     value: "$243.5k", change: "+22%" },
                  { label: "ROI",         value: "3.2x", change: "+12%" },
                  { label: "Assisted Lift", value: "+28%", change: "+8%" },
                ].map((kpi) => (
                  <div key={kpi.label} className="bg-slate-50 rounded-lg px-3 py-2.5">
                    <p className="text-[10px] text-slate-400 font-semibold uppercase">{kpi.label}</p>
                    <p className="text-lg font-bold text-slate-900 mt-0.5">{kpi.value}</p>
                    <p className="text-[10px] font-semibold text-green-600">{kpi.change}</p>
                  </div>
                ))}
              </div>

              {/* Dev-mock chart placeholder */}
              <div className="bg-slate-50 rounded-lg px-4 py-6 flex items-center justify-center">
                <div className="text-center">
                  <BarChart3 className="w-8 h-8 text-slate-300 mx-auto" />
                  <p className="text-xs text-slate-400 mt-2">Channel Performance Chart</p>
                </div>
              </div>

              {/* Dev-mock table */}
              <div className="border border-slate-100 rounded-lg overflow-hidden">
                <div className="grid grid-cols-4 gap-4 px-4 py-2 bg-slate-50 text-[10px] font-bold uppercase tracking-widest text-slate-400">
                  <span>Channel</span>
                  <span className="text-right">Clicks</span>
                  <span className="text-right">Conversions</span>
                  <span className="text-right">Revenue</span>
                </div>
                {[
                  { ch: "Organic", clicks: "4.2k", conv: "186", rev: "$93k"  },
                  { ch: "AI",      clicks: "1.1k", conv: "67",  rev: "$33.5k" },
                  { ch: "Social",  clicks: "890",  conv: "34",  rev: "$17k"  },
                  { ch: "GBP",     clicks: "2.1k", conv: "142", rev: "$71k"  },
                  { ch: "Direct",  clicks: "1.6k", conv: "58",  rev: "$29k"  },
                ].map((row) => (
                  <div key={row.ch} className="grid grid-cols-4 gap-4 px-4 py-2 border-t border-slate-100 text-xs">
                    <span className="font-semibold text-slate-800">{row.ch}</span>
                    <span className="text-right text-slate-600">{row.clicks}</span>
                    <span className="text-right font-semibold text-slate-900">{row.conv}</span>
                    <span className="text-right font-bold text-green-700">{row.rev}</span>
                  </div>
                ))}
              </div>

              {/* AI summary preview */}
              <div className="bg-gradient-to-br from-brand-50 to-violet-50 rounded-lg border border-brand-100 px-4 py-3">
                <p className="text-[10px] font-bold uppercase tracking-widest text-brand-500 mb-1.5">AI Summary</p>
                <p className="text-xs text-slate-500 italic leading-relaxed line-clamp-3">{AI_SUMMARY_PLACEHOLDERS[aiTone]}</p>
              </div>
            </div>
          </div>
          )}
        </div>
      </div>
    </div>
  );
}
