"use client";

import { useState, useRef, useEffect, useMemo } from "react";
import { useBrand } from "@/context/brand-context";
import { useBackgroundTasks } from "@/lib/stores/task-store";
import Link from "next/link";
import { AnalysisArtifact } from "@/components/analysis-artifact";
import { NarrativeReport } from "@/components/analysis/narrative-report";
import { ReviewPanel } from "@/components/analysis/review-panel";
import { ArtifactRenderer } from "@/components/ai-strategist/artifact-renderer";
import { DataMaturityNotice } from "@/components/ui/data-maturity-notice";
import type { Analysis } from "@/lib/services/analysis-schema";
import type { ExtractedAction } from "@/lib/services/analysis-actions";
import { MarkdownContent } from "@/components/shared/MarkdownContent";
import {
  Send, User, Sparkles, LayoutDashboard, ShieldCheck,
  Lightbulb, Trash2,
  ChevronRight, Plus, Zap,
  ListChecks,
  Search, BarChart3, MessageSquare, Activity,
  Loader2, PlayCircle, FileText, AlertTriangle, X,
  Pencil, Check,
} from "lucide-react";

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

type Mode = "strategist" | "client";
type Role = "user" | "assistant";


interface Artifact {
  title: string;
  type: string;
  code: string;
  renderError?: string;
}

interface Message {
  id: number;
  role: Role;
  text: string;
  mode: Mode;
  timestamp: string;
  artifacts?: Artifact[];
}

interface Shortcut {
  label: string;
  href: string;
  icon: React.ElementType;
}

// ─── Chat Data ───────────────────────────────────────────────────────────────

const DEFAULT_PROMPTS = {
  strategist: [
    "Show me a traffic trend analysis for the past 90 days",
    "Build me an executive dashboard of our SEO health",
    "Visualize our keyword opportunity gaps",
    "Compare our top 10 pages — which are growing vs declining?",
    "Analyze click-through rate patterns by page type",
  ],
  client: [
    "Show me how my website is performing in simple terms",
    "Build me a dashboard of my top wins and losses",
    "Which pages are growing and which are losing traffic?",
    "What should I focus on first?",
  ],
};

const SHORTCUTS: Shortcut[] = [
  { label: "Dashboard",       href: "/dashboard",       icon: LayoutDashboard },
  { label: "Technical Audit", href: "/technical-audit", icon: ShieldCheck },
  { label: "Recommendations", href: "/recommendations", icon: Lightbulb },
  { label: "Execution Hub",   href: "/execution-hub",   icon: ListChecks },
];

// ─── Analysis-Grounded Reply Builder ─────────────────────────────────────────

function buildGroundedReply(
  text: string,
  analysis: Analysis | null,
  mode: Mode,
  domain: string,
  conversationHistory: Message[],
): string {
  const lower = text.toLowerCase();

  // Dashboard / artifact requests should never be answered by this local
  // fallback — it cannot generate JSX. Return an actionable error message
  // instead of a misleading single-metric KPI card.
  const isDashboardRequest =
    /\b(dashboard|artifact|jsx|executive|visualize|visualise|chart|build|create)\b/i.test(text) ||
    (text.length > 200 && /\b(section|row|table|kpi|metric|trend|insight|action)\b/i.test(text));
  if (isDashboardRequest) {
    return mode === "strategist"
      ? "I wasn't able to reach the AI service to generate this dashboard. Please try again — if the issue persists, check that your API key is configured correctly."
      : "I couldn't generate that dashboard right now. Please try again in a moment.";
  }

  // No analysis available — be transparent
  if (!analysis) {
    return mode === "strategist"
      ? `No analysis has been generated yet for **${domain}**. Switch to the **Live Analysis** tab and click **Generate Analysis** to create one. Once generated, I can answer questions grounded in your real data.`
      : `I don't have an analysis for your website yet. To get started, switch to the Live Analysis view and generate one — then I can answer your questions based on real data.`;
  }

  const kpis = analysis.kpis;
  const findings = analysis.findings;
  const recs = analysis.recommendations;
  const predictions = analysis.predictions;
  const sources = analysis.sources;
  const caveats = analysis.caveats;
  const period = `${analysis.period.start} to ${analysis.period.end}`;
  const compLabel = analysis.comparisonPeriod?.label ?? "previous equivalent period";
  const availableSources = sources.filter(s => s.status === "available").map(s => s.label);
  const missingSources = sources.filter(s => s.status === "missing").map(s => s.label);
  const critFindings = findings.filter(f => f.severity === "critical" || f.severity === "high");

  // Determine the last topic from conversation history for follow-up awareness
  const lastAssistant = [...conversationHistory].reverse().find(m => m.role === "assistant");
  const lastTopic = lastAssistant?.text?.toLowerCase() ?? "";

  // ── Specific metric / finding lookup ────────────────────────────────────
  // If the user references a specific metric or finding by name, find and explain it
  const matchedKpi = kpis.find(k => lower.includes(k.label.toLowerCase()));
  const matchedFinding = findings.find(f =>
    lower.includes(f.id) ||
    f.title.toLowerCase().split(/\s+/).filter(w => w.length > 3).some(w => lower.includes(w))
  );
  const matchedRec = recs.find(r =>
    r.title.toLowerCase().split(/\s+/).filter(w => w.length > 3).some(w => lower.includes(w))
  );

  // ── "Tell me more" / "explain" / "why" follow-ups ──────────────────────
  if (lower.match(/tell me more|explain|why|what caused|reason|detail|elaborate|dig deeper|break.*down/)) {
    // Follow up on a specific finding
    if (matchedFinding) {
      return explainFinding(matchedFinding, kpis, recs, period, compLabel, mode);
    }
    // Follow up on a specific KPI
    if (matchedKpi) {
      return explainKpi(matchedKpi, findings, recs, period, compLabel, mode);
    }
    // Follow up on the last topic discussed
    if (lastTopic.includes("finding") || lastTopic.includes("anomal") || lastTopic.includes("drop")) {
      if (critFindings.length > 0) {
        return explainFinding(critFindings[0], kpis, recs, period, compLabel, mode);
      }
    }
    if (lastTopic.includes("kpi") || lastTopic.includes("metric") || lastTopic.includes("performance")) {
      const changingKpi = kpis.find(k => k.change && k.change.direction !== "flat");
      if (changingKpi) return explainKpi(changingKpi, findings, recs, period, compLabel, mode);
    }
    if (lastTopic.includes("recommend")) {
      if (recs.length > 0) return explainRecommendation(recs[0], findings, period, mode);
    }
  }

  // ── Specific metric question ───────────────────────────────────────────
  if (matchedKpi) {
    return explainKpi(matchedKpi, findings, recs, period, compLabel, mode);
  }

  // ── Specific finding question ──────────────────────────────────────────
  if (matchedFinding) {
    return explainFinding(matchedFinding, kpis, recs, period, compLabel, mode);
  }

  // ── KPI / overview questions ───────────────────────────────────────────
  if (lower.match(/kpi|metric|number|stat|performance|how.*doing|overview|summary|result/)) {
    if (kpis.length === 0) return `No KPI data is available for ${period}. ${missingSources.length > 0 ? `Missing sources: ${missingSources.join(", ")}.` : ""}`;
    const improving = kpis.filter(k => k.change?.direction === "up");
    const declining = kpis.filter(k => k.change?.direction === "down");

    let reply = `**Performance overview for ${domain}** (${period} vs ${compLabel}):\n\n`;
    for (const k of kpis) {
      const relatedFinding = findings.find(f => f.affectedMetric === k.label);
      reply += `- **${k.label}**: ${k.value}${k.change ? ` (${k.change.label})` : ""} — _${k.source}_`;
      if (relatedFinding) reply += `\n  ↳ _${relatedFinding.title}_`;
      reply += "\n";
    }

    if (declining.length > 0) {
      reply += `\n**Assessment:** ${declining.length} metric${declining.length > 1 ? "s" : ""} declined (${declining.map(k => k.label).join(", ")}). `;
      if (critFindings.length > 0) {
        reply += `This aligns with ${critFindings.length} critical/high finding${critFindings.length > 1 ? "s" : ""}: ${critFindings.map(f => f.title).join("; ")}.`;
      }
    } else if (improving.length > 0) {
      reply += `\n**Assessment:** ${improving.length} metric${improving.length > 1 ? "s" : ""} improving. `;
      if (findings.length === 0 || findings.every(f => f.severity === "info")) reply += "No significant risks detected.";
    }
    if (missingSources.length > 0) reply += `\n\n_Note: ${missingSources.join(", ")} not connected — analysis is partial._`;
    return reply;
  }

  // ── Findings questions ─────────────────────────────────────────────────
  if (lower.match(/finding|issue|problem|wrong|drop|anomal|risk|concern|error|warning/)) {
    if (findings.length === 0) return `No significant findings were detected for ${period}. All tracked metrics are within expected ranges across ${availableSources.join(", ")}.`;
    let reply = `**${findings.length} finding${findings.length > 1 ? "s" : ""} detected** for ${period}:\n\n`;
    for (const f of findings) {
      reply += `**${f.severity.toUpperCase()} — ${f.title}**\n`;
      reply += `${f.description}\n`;
      if (f.evidence) reply += `_Evidence: ${f.evidence}_\n`;
      if (f.impact) reply += `_Business impact: ${f.impact}_\n`;
      const relatedRec = recs.find(r => r.relatedFinding === f.id);
      if (relatedRec) reply += `→ Recommended action: **${relatedRec.title}** (${relatedRec.priority} priority, ${relatedRec.effort} effort)\n`;
      reply += "\n";
    }
    if (caveats.length > 0) reply += `_${caveats.length} data caveat${caveats.length > 1 ? "s" : ""} noted — ask about caveats for details._`;
    return reply;
  }

  // ── Recommendation questions ───────────────────────────────────────────
  if (lower.match(/recommend|suggest|fix|action|should.*do|priorit|next step|improve|what.*first/)) {
    if (recs.length === 0) return `No specific recommendations at this time. All metrics are stable for ${period}.`;
    let reply = `**${recs.length} recommendation${recs.length > 1 ? "s" : ""}** based on the ${period} analysis:\n\n`;
    for (let i = 0; i < recs.length; i++) {
      const r = recs[i];
      const relatedFinding = r.relatedFinding ? findings.find(f => f.id === r.relatedFinding) : undefined;
      reply += `**${i + 1}. ${r.title}** [${r.priority.toUpperCase()} · ${r.effort} effort]\n`;
      reply += `${r.description}\n`;
      if (r.expectedImpact) reply += `Expected impact: ${r.expectedImpact}\n`;
      if (relatedFinding) reply += `_Triggered by: ${relatedFinding.title}_\n`;
      reply += "\n";
    }
    reply += "I'd suggest starting with the highest-priority, lowest-effort items first.";
    return reply;
  }

  // ── Prediction / outlook questions ─────────────────────────────────────
  if (lower.match(/predict|outlook|forecast|future|expect|project|next month|trend|where.*heading/)) {
    if (predictions.length === 0) return `Not enough data points in ${period} to make reliable predictions. ${kpis.length > 0 ? `Current metrics: ${kpis.slice(0, 2).map(k => `${k.label}: ${k.value}`).join(", ")}.` : ""} More data is needed for forecasting.`;
    let reply = `**Outlook** extrapolated from ${period} trends:\n\n`;
    for (const p of predictions) {
      const direction = p.predicted > p.current ? "increase" : p.predicted < p.current ? "decline" : "remain stable";
      const pct = p.current > 0 ? Math.abs(Math.round(((p.predicted - p.current) / p.current) * 100)) : 0;
      reply += `**${p.metric}** is projected to **${direction}${pct > 0 ? ` by ~${pct}%` : ""}** over the next ${p.timeframe}.\n`;
      reply += `- Current: ${p.current.toLocaleString()} → Projected: ${p.predicted.toLocaleString()}\n`;
      reply += `- Confidence: ${p.confidence} · Basis: ${p.basis}\n`;
      if (p.caveat) reply += `- _Caveat: ${p.caveat}_\n`;
      reply += "\n";
    }
    return reply;
  }

  // ── Source / data questions ─────────────────────────────────────────────
  if (lower.match(/source|data|connect|integrat|ga4|gsc|search console|analytics|available|where.*from/)) {
    let reply = `**Data sources** for this analysis (${period}):\n\n`;
    for (const s of sources) {
      const statusText = s.status === "available" ? `${s.recordCount ?? 0} records${s.dateRange ? ` (${s.dateRange.start} → ${s.dateRange.end})` : ""}` : s.status === "partial" ? "Connected — awaiting data" : s.status === "missing" ? "Not connected" : s.status;
      reply += `- **${s.label}**: ${statusText}\n`;
    }
    if (missingSources.length > 0) reply += `\nConnect ${missingSources.join(" and ")} in **Integrations** to get a more complete analysis. Missing sources mean some KPIs, findings, and predictions may be incomplete.`;
    else reply += "\nAll sources are connected and providing data.";
    if (analysis.narrative?.methodology) reply += `\n\n_Methodology: ${analysis.narrative.methodology}_`;
    return reply;
  }

  // ── Caveat / limitation questions ──────────────────────────────────────
  if (lower.match(/caveat|limit|confidence|gap|miss|stale|methodology|how reliable/)) {
    if (caveats.length === 0) return `No significant data caveats for this analysis. ${availableSources.length} source${availableSources.length !== 1 ? "s" : ""} provided sufficient data for ${period}.`;
    let reply = `**${caveats.length} data caveat${caveats.length > 1 ? "s" : ""}** for this analysis:\n\n`;
    for (const c of caveats) {
      reply += `- **${c.title}** [${c.severity}]: ${c.description}\n  Affects: ${c.affectedSections.join(", ")}\n\n`;
    }
    return reply;
  }

  // ── Default — analyst-style summary with cross-references ──────────────
  let reply = `**Analysis for ${domain}** (${period}):\n\n`;
  reply += `${analysis.summary}\n\n`;

  if (kpis.length > 0) {
    reply += `**Key metrics:** ${kpis.map(k => `${k.label}: ${k.value}${k.change ? ` (${k.change.label})` : ""}`).join(" · ")}\n\n`;
  }

  if (critFindings.length > 0) {
    reply += `**Attention needed:** ${critFindings.length} critical/high finding${critFindings.length > 1 ? "s" : ""} — ${critFindings.map(f => f.title).join("; ")}.\n\n`;
  } else if (findings.length > 0) {
    reply += `**${findings.length} finding${findings.length > 1 ? "s" : ""}** detected, none critical.\n\n`;
  }

  if (recs.length > 0) {
    reply += `**Top recommendation:** ${recs[0].title} — ${recs[0].description}\n\n`;
  }

  reply += `Ask me about specific KPIs, findings, recommendations, predictions, data sources, or caveats.`;
  if (missingSources.length > 0) reply += `\n\n_Note: ${missingSources.join(", ")} not connected — connect in Integrations for a more complete picture._`;
  return reply;
}

// ── Explanation helpers (cross-reference analysis sections) ──────────────

function explainKpi(
  kpi: Analysis["kpis"][0],
  findings: Analysis["findings"],
  recs: Analysis["recommendations"],
  period: string,
  compLabel: string,
  mode: Mode,
): string {
  const relatedFindings = findings.filter(f => f.affectedMetric === kpi.label);
  const relatedRecs = recs.filter(r => relatedFindings.some(f => r.relatedFinding === f.id));

  let reply = `**${kpi.label}: ${kpi.value}**`;
  if (kpi.change) {
    reply += ` (${kpi.change.label} vs ${compLabel})`;
    if (kpi.change.direction === "down") {
      reply += `\n\nThis metric **declined** during ${period}.`;
    } else if (kpi.change.direction === "up") {
      reply += `\n\nThis metric **improved** during ${period}.`;
    } else {
      reply += `\n\nThis metric remained **stable** during ${period}.`;
    }
  }
  reply += `\n\n_Source: ${kpi.source}_`;

  if (relatedFindings.length > 0) {
    reply += `\n\n**Related findings:**\n`;
    for (const f of relatedFindings) {
      reply += `- **${f.title}** [${f.severity}]: ${f.description}\n`;
      if (f.evidence) reply += `  Evidence: _${f.evidence}_\n`;
      if (f.impact) reply += `  Impact: _${f.impact}_\n`;
    }
  } else {
    reply += `\n\nNo anomalies or issues were detected specifically for this metric in the analysis period.`;
  }

  if (relatedRecs.length > 0) {
    reply += `\n**What to do about it:**\n`;
    for (const r of relatedRecs) {
      reply += `- **${r.title}** (${r.priority} priority, ${r.effort} effort): ${r.description}\n`;
    }
  }

  return reply;
}

function explainFinding(
  finding: Analysis["findings"][0],
  kpis: Analysis["kpis"],
  recs: Analysis["recommendations"],
  period: string,
  compLabel: string,
  mode: Mode,
): string {
  const relatedKpi = finding.affectedMetric ? kpis.find(k => k.label === finding.affectedMetric) : undefined;
  const relatedRec = recs.find(r => r.relatedFinding === finding.id);

  let reply = `**${finding.title}** [${finding.severity.toUpperCase()} ${finding.type}]\n\n`;
  reply += `**What happened:** ${finding.description}\n\n`;

  if (finding.evidence) {
    reply += `**Supporting evidence:** ${finding.evidence}\n\n`;
  }

  if (relatedKpi) {
    reply += `**Affected metric:** ${relatedKpi.label} is currently at ${relatedKpi.value}`;
    if (relatedKpi.change) reply += ` (${relatedKpi.change.label} vs ${compLabel})`;
    reply += ".\n\n";
  }

  if (finding.impact) {
    reply += `**Business impact:** ${finding.impact}\n\n`;
  }

  if (relatedRec) {
    reply += `**Recommended action:** ${relatedRec.title} (${relatedRec.priority} priority, ${relatedRec.effort} effort)\n`;
    reply += `${relatedRec.description}\n`;
    if (relatedRec.expectedImpact) reply += `Expected outcome: ${relatedRec.expectedImpact}\n`;
  } else {
    reply += mode === "strategist"
      ? `No specific recommendation is linked to this finding yet. Consider investigating further based on the evidence above.`
      : `We haven't generated a specific fix for this yet, but the evidence above should help guide next steps.`;
  }

  return reply;
}

function explainRecommendation(
  rec: Analysis["recommendations"][0],
  findings: Analysis["findings"],
  period: string,
  mode: Mode,
): string {
  const relatedFinding = rec.relatedFinding ? findings.find(f => f.id === rec.relatedFinding) : undefined;

  let reply = `**${rec.title}** [${rec.priority.toUpperCase()} priority · ${rec.effort} effort]\n\n`;
  reply += `**What to do:** ${rec.description}\n\n`;

  if (rec.expectedImpact) {
    reply += `**Expected impact:** ${rec.expectedImpact}\n\n`;
  }

  if (relatedFinding) {
    reply += `**Why this matters:** This recommendation addresses the finding "${relatedFinding.title}" — ${relatedFinding.description}\n`;
    if (relatedFinding.evidence) reply += `Evidence: _${relatedFinding.evidence}_\n`;
  }

  return reply;
}

// ─── Suggested Prompt Library ────────────────────────────────────────────────

interface SuggestedPrompt {
  label: string;
  prompt: string;
}

const TRAFFIC_DEEP_DIVE_PROMPT = `Build a traffic deep-dive dashboard. Stay under 350 lines.

TL;DR: One sentence summarizing the main traffic trend with specific numbers.

Sections (in order — cut from the bottom if budget is tight):
1. KPI row — Clicks, Impressions, Avg Position, CTR with period-over-period deltas
2. Daily traffic ComposedChart — blue bars for clicks (dataKey="c"), orange line for impressions (dataKey="i"), EVERY day plotted, interval={3} on XAxis
3. Top 5 gaining queries + top 5 declining queries in a single two-column table (position change, clicks)
4. Strategic insights — exactly 3 bullets, each citing a specific number from the data

Do NOT include conversion data. Do NOT fabricate numbers — use only <daily-gsc-data> and <live-data>.
Data source footer required.`;

const EXECUTIVE_DASHBOARD_PROMPT = `Build a boardroom-ready executive dashboard. Stay under 350 lines.

TL;DR: One sentence — overall health verdict with the single most important number.

Sections (in order — cut from the bottom if budget is tight):
1. KPI row — Clicks, Impressions, CTR, Avg Position, Conversions, Conversion Rate (use compact .map() pattern)
2. Daily traffic ComposedChart — clicks bars + impressions line, full width
3. Daily conversions ComposedChart — conv bars + rate line + pageviews line (only if <daily-conversions> present)
4. Top 5 pages table — clicks, impressions, position from <daily-gsc-data> or <content-intel>
5. Priority actions — exactly 3 items, each with expected outcome

Data source footer required. No fabricated numbers.`;

const FINDINGS_IMPACT_PROMPT = `Build a findings & impact dashboard. Stay under 350 lines.

TL;DR: One sentence naming the most critical finding and its measured impact.

Sections (in order — cut from the bottom if budget is tight):
1. Alert banner — red for critical findings, amber for warnings (check <tracking-health> first)
2. Findings cards — one card per finding with severity badge, title, evidence, and linked recommendation (use .map())
3. KPI before/after table — each metric: period-start value → period-end value → delta
4. Priority actions — exactly 3 items ranked HIGH impact + LOW effort first

Data source footer required. Cite only numbers from <analysis> findings.`;

const RECOMMENDATIONS_PROMPT = `Build a recommendations prioritization dashboard. Stay under 350 lines.

TL;DR: One sentence — total recs, how many are high priority, and the single most impactful quick win.

Sections (in order — cut from the bottom if budget is tight):
1. KPI summary row — total recs, critical count, high count, quick wins count (high impact + low effort)
2. Quick Wins section — recs with HIGH impact + LOW effort rendered as cards with expected outcome (use .map())
3. Strategic Initiatives section — HIGH impact + HIGH effort items (roadmap quarter)
4. Full recommendations table — title, priority, effort, expected impact for all remaining recs

Data source footer required. Cite only recommendations from <analysis>.recommendations.`;

function buildSuggestedPrompts(analysis: Analysis | null, mode: Mode): SuggestedPrompt[] {
  if (!analysis) {
    return DEFAULT_PROMPTS[mode].slice(0, 3).map((p) => ({ label: p, prompt: p }));
  }

  const prompts: SuggestedPrompt[] = [];
  const isStrategist = mode === "strategist";

  if (analysis.charts.length > 0) {
    prompts.push(isStrategist
      ? { label: "Traffic deep dive", prompt: TRAFFIC_DEEP_DIVE_PROMPT }
      : { label: "Show me how my traffic is trending", prompt: "Show me how my traffic is trending" });
  }
  if (analysis.kpis.length > 0) {
    prompts.push(isStrategist
      ? { label: "Executive dashboard", prompt: EXECUTIVE_DASHBOARD_PROMPT }
      : { label: "Build me a simple performance dashboard", prompt: "Build me a simple performance dashboard" });
  }
  if (analysis.findings.length > 0) {
    prompts.push(isStrategist
      ? { label: "Findings & impact analysis", prompt: FINDINGS_IMPACT_PROMPT }
      : { label: "Show me what needs my attention", prompt: "Show me what needs my attention" });
  }
  if (analysis.recommendations.length > 0) {
    prompts.push(isStrategist
      ? { label: "Prioritize recommendations", prompt: RECOMMENDATIONS_PROMPT }
      : { label: "What should I focus on first?", prompt: "What should I focus on first?" });
  }

  if (prompts.length === 0) {
    return DEFAULT_PROMPTS[mode].slice(0, 3).map((p) => ({ label: p, prompt: p }));
  }
  return prompts.slice(0, 3);
}

function buildFollowUpSuggestions(analysis: Analysis | null): string[] {
  if (!analysis) return [];
  const suggestions: string[] = [];
  if (analysis.findings.length > 0) suggestions.push("Tell me more about the findings");
  if (analysis.recommendations.length > 0) suggestions.push("What are the top recommendations?");
  if (analysis.predictions.length > 0) suggestions.push("What's the predicted outlook?");
  return suggestions.slice(0, 3);
}

// ─── Helpers ──────────────────────────────────────────────────────────────────


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

let msgId = 10;

type PageView = "chat" | "analysis";
type AnalysisRangeDays = 7 | 28 | 60 | 90;
const ANALYSIS_RANGE_OPTIONS: readonly AnalysisRangeDays[] = [7, 28, 60, 90] as const;

export default function AIStrategistPage() {
  const { brand, loading: brandLoading } = useBrand();
  const { addTask, completeTask, failTask } = useBackgroundTasks();
  const brandReady = !brandLoading && !!brand.id;
  const [pageView, setPageView]       = useState<PageView>("analysis");
  const [mode, setMode]               = useState<Mode>("strategist");
  const [input, setInput]             = useState("");
  const [isTyping, setIsTyping]       = useState(false);
  const [analysisResult, setAnalysisResult] = useState<Analysis | null>(null);
  const [analysisLoading, setAnalysisLoading] = useState(false);
  const [analysisFailed, setAnalysisFailed] = useState(false);
  const [analysisView, setAnalysisView] = useState<"artifact" | "report" | "review">("artifact");
  const [initialLoadDone, setInitialLoadDone] = useState(false);
  const [analysisRange, setAnalysisRange] = useState<AnalysisRangeDays>(28);
  const rangeRestoredRef = useRef(false);
  const [hasSiteTagData, setHasSiteTagData] = useState(true);
  const [siteTagDismissed, setSiteTagDismissed] = useState(false);
  const [enrichmentCount, setEnrichmentCount] = useState(0);
  const [siteTagAge, setSiteTagAge] = useState(0);
  const [siteTagInstalled, setSiteTagInstalled] = useState(false);
  const [siteTagInstalledAt, setSiteTagInstalledAt] = useState<string | null>(null);

  useEffect(() => {
    if (!brand.id) return;
    fetch(`/api/brands/${brand.id}/has-site-tag-data`)
      .then((r) => r.ok ? r.json() : { has: true })
      .then((d) => setHasSiteTagData(d.has !== false))
      .catch(() => {});
    fetch(`/api/brands/${brand.id}/enrichment-files`)
      .then((r) => r.ok ? r.json() : { files: [] })
      .then((d) => setEnrichmentCount((d.files || []).filter((f: { processingStatus: string }) => f.processingStatus === "ready").length))
      .catch(() => {});
    fetch(`/api/site-tag?brandId=${brand.id}`)
      .then((r) => r.ok ? r.json() : null)
      .then((d) => {
        if (!d) return;
        setSiteTagAge(d.siteTagAge ?? 0);
        setSiteTagInstalled(!!d.site);
        setSiteTagInstalledAt(d.installedAt ?? null);
      })
      .catch(() => {});
  }, [brand.id]);
  const makeWelcome = (result: Analysis | null): Message => ({
    id: 1, role: "assistant", mode: "strategist", timestamp: new Date().toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }),
    text: `Welcome back. I'm ready to help with **${brand.domain || brand.name}**.

${result ? `Your latest analysis covers **${result.period.start} to ${result.period.end}** with ${result.findings.length} finding(s) and ${result.recommendations.length} recommendation(s). Ask me about any of them.` : "Generate a **Live Analysis** first, then I can answer questions grounded in your real data."}`,
  });
  const [messages, setMessages] = useState<Message[]>([makeWelcome(null)]);

  interface SessionEntry { id: string; title: string; updatedAt: string }
  const [sessionList, setSessionList] = useState<SessionEntry[]>([]);
  const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
  const [confirmDeleteSession, setConfirmDeleteSession] = useState<string | null>(null);
  const [renamingSessionId, setRenamingSessionId] = useState<string | null>(null);
  const [renameDraft, setRenameDraft] = useState("");
  const [editingHeaderTitle, setEditingHeaderTitle] = useState(false);
  const [headerTitleDraft, setHeaderTitleDraft] = useState("");
  const autoSessionCreatedRef = useRef(false);

  const [chatTab, setChatTab] = useState<"messages" | "artifact">("messages");

  useEffect(() => {
    if (!brand.id) return;
    fetch(`/api/ai-strategist/sessions?brandId=${brand.id}`)
      .then((r) => r.ok ? r.json() : [])
      .then((data) => setSessionList(Array.isArray(data) ? data : []))
      .catch(() => {});
  }, [brand.id]);

  useEffect(() => {
    if (!brand.id || autoSessionCreatedRef.current) return;
    autoSessionCreatedRef.current = true;
    (async () => {
      try {
        const res = await fetch("/api/ai-strategist/sessions", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ brandId: brand.id }),
        });
        if (res.ok) {
          const { id } = await res.json();
          setActiveSessionId(id);
        }
      } catch { /* best-effort */ }
    })();
  }, [brand.id]);

  async function loadSession(sessionId: string) {
    try {
      const res = await fetch(`/api/ai-strategist/sessions/${sessionId}/messages`);
      if (!res.ok) return;
      const msgs = (await res.json()) as Array<{ role: string; content: string; artifacts?: unknown; createdAt: string }>;
      setActiveSessionId(sessionId);
      setMessages([
        makeWelcome(analysisResult),
        ...msgs.map((m, i) => ({
          id: i + 2,
          role: m.role as Role,
          mode: mode as Mode,
          timestamp: new Date(m.createdAt).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }),
          text: m.content,
          artifacts: m.artifacts as Artifact[] | undefined,
        })),
      ]);
    } catch { /* ignore */ }
  }

  async function deleteSession(sessionId: string) {
    await fetch(`/api/ai-strategist/sessions/${sessionId}`, { method: "DELETE" });
    setSessionList((prev) => prev.filter((s) => s.id !== sessionId));
    setConfirmDeleteSession(null);
    if (activeSessionId === sessionId) startNew();
  }

  function beginRename(s: SessionEntry) {
    setRenamingSessionId(s.id);
    setRenameDraft(s.title);
  }

  async function commitRename(sessionId: string) {
    const next = renameDraft.trim();
    setRenamingSessionId(null);
    if (!next) return;
    setSessionList((prev) => prev.map((s) => (s.id === sessionId ? { ...s, title: next } : s)));
    try {
      await fetch(`/api/ai-strategist/sessions/${sessionId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: next }),
      });
    } catch { /* best-effort */ }
  }

  const activeSessionTitle: string =
    sessionList.find((s) => s.id === activeSessionId)?.title ?? "New Chat";

  function beginHeaderEdit() {
    if (!activeSessionId) return;
    setHeaderTitleDraft(activeSessionTitle);
    setEditingHeaderTitle(true);
  }

  async function commitHeaderTitle() {
    const next = headerTitleDraft.trim();
    setEditingHeaderTitle(false);
    if (!activeSessionId || !next || next === activeSessionTitle) return;
    setSessionList((prev) => prev.map((s) => (s.id === activeSessionId ? { ...s, title: next } : s)));
    try {
      await fetch(`/api/ai-strategist/sessions/${activeSessionId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: next }),
      });
    } catch { /* best-effort */ }
  }

  function formatSessionTime(iso: string): string {
    const diff = Date.now() - new Date(iso).getTime();
    const mins = Math.floor(diff / 60000);
    if (mins < 60) return `${mins}m ago`;
    const hours = Math.floor(mins / 60);
    if (hours < 24) return `${hours}h ago`;
    const days = Math.floor(hours / 24);
    if (days === 1) return "Yesterday";
    if (days < 7) return `${days}d ago`;
    return new Date(iso).toLocaleDateString(undefined, { month: "short", day: "numeric" });
  }

  function groupSessions(list: SessionEntry[]): Array<{ label: string; items: SessionEntry[] }> {
    const today: SessionEntry[] = [];
    const yesterday: SessionEntry[] = [];
    const older: SessionEntry[] = [];
    const now = new Date();
    const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
    const startOfYesterday = startOfToday - 86_400_000;
    for (const s of list) {
      const t = new Date(s.updatedAt).getTime();
      if (t >= startOfToday) today.push(s);
      else if (t >= startOfYesterday) yesterday.push(s);
      else older.push(s);
    }
    return [
      { label: "Today", items: today },
      { label: "Yesterday", items: yesterday },
      { label: "Older", items: older },
    ].filter((g) => g.items.length > 0);
  }

  useEffect(() => {
    setMessages(prev => {
      const updated = makeWelcome(analysisResult);
      if (prev.length === 0) return [updated];
      if (prev[0].id === 1) return [updated, ...prev.slice(1)];
      return prev;
    });
  }, [analysisResult, brand.domain, brand.name]);

  const bottomRef = useRef<HTMLDivElement>(null);
  const inputRef  = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    if (!brandReady) return;
    let cancelled = false;
    setInitialLoadDone(false);
    setAnalysisResult(null);
    fetch(`/api/analysis?brandId=${brand.id}`)
      .then(res => res.ok ? res.json() : null)
      .then(data => {
        if (cancelled) return;
        if (data) {
          setAnalysisResult(data);
          if (data.period?.start && data.period?.end) {
            const days = Math.round((new Date(data.period.end).getTime() - new Date(data.period.start).getTime()) / 86400000);
            const closest = ([7, 28, 60, 90] as AnalysisRangeDays[]).reduce((best, d) => Math.abs(d - days) < Math.abs(best - days) ? d : best);
            rangeRestoredRef.current = true;
            setAnalysisRange(closest);
          }
        }
        setInitialLoadDone(true);
      })
      .catch(() => { if (!cancelled) setInitialLoadDone(true); });
    return () => { cancelled = true; };
  }, [brandReady, brand.id]);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages, isTyping]);

  useEffect(() => {
    if (!brandReady || !initialLoadDone) return;
    if (!analysisResult) return;
    if (rangeRestoredRef.current) {
      rangeRestoredRef.current = false;
      return;
    }
    runAnalysis();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [analysisRange]);

  async function runAnalysis() {
    if (!brand.id) return;
    setAnalysisLoading(true);
    setAnalysisFailed(false);
    setAnalysisResult(null);
    const taskId = addTask({ id: `analysis_${Date.now()}`, type: "ai_analysis", label: "Running AI Analysis...", brandId: brand.id, resultUrl: "/ai-strategist" });
    try {
      const end = new Date().toISOString().split("T")[0];
      const start = new Date(Date.now() - (analysisRange - 1) * 86400000).toISOString().split("T")[0];
      const res = await fetch("/api/analysis", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ brandId: brand.id, type: "seasonal_performance", period: { start, end } }),
      });
      if (res.ok) {
        const data = await res.json();
        setAnalysisResult(data);
        setPageView("analysis");
        const findings = data?.findings?.length ?? 0;
        const recs = data?.recommendations?.length ?? 0;
        completeTask(taskId, { resultUrl: "/ai-strategist", resultSummary: `Analysis complete: ${findings} findings, ${recs} recommendations` });
      } else {
        setAnalysisFailed(true);
        failTask(taskId, "Analysis failed — try a shorter date range");
      }
    } catch {
      setAnalysisFailed(true);
      failTask(taskId, "Network error — try again");
    }
    setAnalysisLoading(false);
  }

  async function send(text: string) {
    if (!text.trim() || isTyping || !brand.id) return;
    const userMsg: Message = { id: ++msgId, role: "user", mode, timestamp: now(), text: text.trim() };
    const updatedMessages = [...messages, userMsg];
    setMessages(updatedMessages);
    setInput("");
    setIsTyping(true);
    setChatTab("messages");

    const history = updatedMessages
      .filter(m => m.id > 1)
      .map(m => ({ role: m.role, content: m.text }));

    try {
      const res = await fetch("/api/ai-strategist/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          brandId: brand.id,
          message: text.trim(),
          sessionId: activeSessionId,
          history: history.slice(0, -1),
          analysis: analysisResult,
          analysisState: analysisLoading ? "running" : analysisFailed ? "failed" : analysisResult ? "complete" : "idle",
          mode,
        }),
      });
      if (res.ok) {
        const data = await res.json() as { text: string; artifacts: Artifact[]; metadata?: { dataSource?: string }; sessionId?: string };
        const hasArtifacts = !!data.artifacts?.length;
        const hasText = !!data.text?.trim();
        const bodyText = hasText
          ? data.text
          : hasArtifacts ? "" : "(No response)";
        const sourceLabel = (bodyText && data.metadata?.dataSource)
          ? `\n\n_Source: ${data.metadata.dataSource}_`
          : "";
        setMessages(prev => [...prev, {
          id: ++msgId, role: "assistant", mode, timestamp: now(),
          text: bodyText + sourceLabel,
          artifacts: hasArtifacts ? data.artifacts : undefined,
        }]);
        if (hasArtifacts) setChatTab("artifact");
        if (data.sessionId) {
          fetch(`/api/ai-strategist/sessions?brandId=${brand.id}`)
            .then((r) => r.ok ? r.json() : [])
            .then((d) => setSessionList(Array.isArray(d) ? d : []))
            .catch(() => {});
        }
      } else {
        const fallback = buildGroundedReply(text, analysisResult, mode, brand.domain || brand.name, updatedMessages);
        setMessages(prev => [...prev, { id: ++msgId, role: "assistant", mode, timestamp: now(), text: fallback }]);
      }
    } catch {
      const fallback = buildGroundedReply(text, analysisResult, mode, brand.domain || brand.name, updatedMessages);
      setMessages(prev => [...prev, { id: ++msgId, role: "assistant", mode, timestamp: now(), text: fallback }]);
    }
    setIsTyping(false);
  }

  function now() {
    return new Date().toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" });
  }

  function handleKey(e: React.KeyboardEvent) {
    if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(input); }
  }

  async function startNew() {
    setActiveSessionId(null);
    setMessages([makeWelcome(analysisResult)]);
    setInput("");
    inputRef.current?.focus();
    try {
      const res = await fetch("/api/ai-strategist/sessions", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ brandId: brand.id }),
      });
      if (res.ok) {
        const { id } = await res.json();
        setActiveSessionId(id);
        const listRes = await fetch(`/api/ai-strategist/sessions?brandId=${brand.id}`);
        if (listRes.ok) setSessionList(await listRes.json());
      }
    } catch { /* best-effort */ }
  }

  useEffect(() => {
    const main = document.querySelector("main") as HTMLElement | null;
    if (!main) return;
    const prev = main.style.overflow;
    main.style.overflow = "hidden";
    return () => { main.style.overflow = prev; };
  }, []);

  return (
    <div className="flex flex-col h-full min-h-0">

      {/* ── Top bar ─────────────────────────────────────────────────────────────── */}
      <div className="bg-white rounded-xl border border-slate-200 px-5 py-3 mb-3 flex items-center justify-between shrink-0">
        <div className="flex items-center gap-2.5">
          <div className="w-8 h-8 rounded-full bg-gradient-to-br from-brand-500 to-purple-600 flex items-center justify-center shadow-sm">
            <Sparkles className="w-4 h-4 text-white" />
          </div>
          <div>
            <p className="text-sm font-bold text-slate-800">meSEO AI Strategist</p>
            <p className="text-[10px] text-slate-400">Analysing {brand.domain || brand.name}{enrichmentCount > 0 ? ` · 📄 ${enrichmentCount} doc${enrichmentCount !== 1 ? "s" : ""} enriched` : ""}</p>
          </div>
        </div>

        <div className="flex items-center gap-1 bg-slate-100 rounded-lg p-1">
          <button onClick={() => setPageView("analysis")}
            className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-md text-xs font-semibold transition-all ${pageView === "analysis" ? "bg-white text-brand-700 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
            <Activity className="w-3.5 h-3.5" /> Live Analysis
          </button>
          <button onClick={() => setPageView("chat")}
            className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-md text-xs font-semibold transition-all ${pageView === "chat" ? "bg-white text-brand-700 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
            <MessageSquare className="w-3.5 h-3.5" /> Chat
          </button>
        </div>

        <div className="flex items-center gap-2">
          {pageView === "chat" && (
            <div className="flex items-center gap-1 bg-slate-100 rounded-lg p-1">
              <button onClick={() => setMode("strategist")}
                className={`flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[11px] font-semibold transition-all ${mode === "strategist" ? "bg-white text-brand-700 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
                <Zap className="w-3 h-3" /> Strategist
              </button>
              <button onClick={() => setMode("client")}
                className={`flex items-center gap-1.5 px-2.5 py-1 rounded-md text-[11px] font-semibold transition-all ${mode === "client" ? "bg-white text-brand-700 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
                <User className="w-3 h-3" /> Client
              </button>
            </div>
          )}
          {pageView === "analysis" && (
            <div className="flex items-center gap-1 bg-slate-100 rounded-lg p-1">
              {ANALYSIS_RANGE_OPTIONS.map(days => (
                <button
                  key={days}
                  onClick={() => setAnalysisRange(days)}
                  disabled={analysisLoading}
                  className={`px-2.5 py-1 rounded-md text-[11px] font-semibold transition-all disabled:opacity-50 disabled:cursor-not-allowed ${
                    analysisRange === days ? "bg-white text-brand-700 shadow-sm" : "text-slate-500 hover:text-slate-700"
                  }`}
                  title={`Analyse the last ${days} days`}
                >
                  {days}d
                </button>
              ))}
            </div>
          )}
          <button
            onClick={() => runAnalysis()}
            disabled={analysisLoading}
            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-brand-200 bg-brand-50 text-xs font-semibold text-brand-700 hover:bg-brand-100 disabled:opacity-50 transition-colors"
          >
            {analysisLoading ? <Loader2 className="w-3 h-3 animate-spin" /> : <BarChart3 className="w-3 h-3" />}
            {analysisLoading ? "Analyzing..." : analysisResult ? "Refresh Analysis" : "Generate Analysis"}
          </button>
        </div>
      </div>

      {!siteTagDismissed && brandReady && !hasSiteTagData && (
        <div className="flex items-center gap-3 bg-amber-50 border border-amber-200 rounded-xl px-4 py-2.5 mb-3 shrink-0">
          <AlertTriangle className="w-4 h-4 text-amber-500 shrink-0" />
          <p className="text-xs text-amber-700 flex-1">
            Some data may be limited. <Link href="/site-tag" className="font-semibold underline">Install the meSEO Site Tag</Link> for full conversion tracking, heatmaps, and behavioral insights.
          </p>
          <button onClick={() => setSiteTagDismissed(true)} className="text-amber-400 hover:text-amber-600 shrink-0">
            <X className="w-3.5 h-3.5" />
          </button>
        </div>
      )}

      {/* ── Main content area ──────────────────────────────────────────────────── */}
      <div className="flex gap-4 flex-1 min-h-0">

        {pageView === "chat" && (
          <div className="w-52 shrink-0 flex flex-col gap-2 min-h-0 hidden md:flex">
            <button onClick={startNew}
              className="flex items-center justify-center gap-2 w-full py-2.5 rounded-xl bg-brand-600 text-white text-sm font-semibold hover:bg-brand-700 transition-colors shadow-sm">
              <Plus className="w-4 h-4" /> New Chat
            </button>
            <div className="bg-white rounded-xl border border-slate-200 flex-1 overflow-y-auto min-h-0">
              {sessionList.length === 0 ? (
                <p className="px-3 py-4 text-[10px] text-slate-400 text-center">No previous chats</p>
              ) : (
                <div className="py-1">
                  {groupSessions(sessionList).map((group) => (
                    <div key={group.label} className="mb-1">
                      <p className="px-3 pt-2 pb-1 text-[9px] font-bold uppercase tracking-widest text-slate-400">{group.label}</p>
                      {group.items.map((s) => (
                        <div key={s.id} className="group relative">
                          {renamingSessionId === s.id ? (
                            <div className="px-3 py-2 flex items-center gap-1">
                              <input
                                autoFocus
                                value={renameDraft}
                                onChange={(e) => setRenameDraft(e.target.value)}
                                onKeyDown={(e) => {
                                  if (e.key === "Enter") { e.preventDefault(); commitRename(s.id); }
                                  if (e.key === "Escape") { e.preventDefault(); setRenamingSessionId(null); }
                                }}
                                onBlur={() => commitRename(s.id)}
                                className="flex-1 min-w-0 text-[11px] font-medium px-1.5 py-1 border border-brand-300 rounded bg-white focus:outline-none focus:ring-1 focus:ring-brand-500"
                              />
                              <button
                                onMouseDown={(e) => { e.preventDefault(); commitRename(s.id); }}
                                className="text-brand-600 hover:text-brand-700 shrink-0"
                              >
                                <Check className="w-3 h-3" />
                              </button>
                            </div>
                          ) : (
                            <>
                              <button
                                onClick={() => loadSession(s.id)}
                                onDoubleClick={() => beginRename(s)}
                                className={`w-full text-left px-3 py-2 pr-12 text-[11px] transition-colors ${
                                  activeSessionId === s.id ? "bg-brand-50 text-brand-700 font-semibold" : "text-slate-600 hover:bg-slate-50"
                                }`}
                              >
                                <p className="truncate font-medium">{s.title}</p>
                                <p className="text-[10px] text-slate-400 mt-0.5">{formatSessionTime(s.updatedAt)}</p>
                              </button>
                              {confirmDeleteSession === s.id ? (
                                <div className="absolute right-1 top-1.5 flex items-center gap-1">
                                  <button onClick={() => deleteSession(s.id)} className="text-[9px] font-semibold text-red-600 hover:underline">Delete</button>
                                  <button onClick={() => setConfirmDeleteSession(null)} className="text-[9px] font-semibold text-slate-400 hover:underline">Cancel</button>
                                </div>
                              ) : (
                                <div className="absolute right-2 top-2.5 flex items-center gap-1.5 opacity-0 group-hover:opacity-100 transition-opacity">
                                  <button
                                    onClick={(e) => { e.stopPropagation(); beginRename(s); }}
                                    aria-label="Rename chat"
                                    className="text-slate-300 hover:text-slate-600"
                                  >
                                    <Pencil className="w-3 h-3" />
                                  </button>
                                  <button
                                    onClick={(e) => { e.stopPropagation(); setConfirmDeleteSession(s.id); }}
                                    aria-label="Delete chat"
                                    className="text-slate-300 hover:text-red-500"
                                  >
                                    <Trash2 className="w-3 h-3" />
                                  </button>
                                </div>
                              )}
                            </>
                          )}
                        </div>
                      ))}
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        )}

        {/* ── ANALYSIS VIEW ── */}
        {pageView === "analysis" && (
          <div className="flex-1 flex flex-col min-h-0 min-w-0">
            {(!brandReady || !initialLoadDone) && (
              <div className="flex-1 flex items-center justify-center">
                <div className="text-center space-y-3">
                  <Loader2 className="w-8 h-8 text-brand-400 animate-spin mx-auto" />
                  <p className="text-sm text-slate-500">{!brandReady ? "Loading brand..." : "Loading latest analysis..."}</p>
                </div>
              </div>
            )}

            {brandReady && initialLoadDone && !analysisResult && !analysisLoading && (
              <div className="flex-1 flex items-center justify-center">
                <div className="text-center max-w-md space-y-4">
                  <div className="w-16 h-16 mx-auto rounded-2xl bg-gradient-to-br from-brand-50 to-purple-50 border border-brand-200 flex items-center justify-center">
                    <Activity className="w-8 h-8 text-brand-500" />
                  </div>
                  <div>
                    <h3 className="text-lg font-bold text-slate-800">No analysis yet</h3>
                    <p className="text-sm text-slate-500 mt-1 leading-relaxed">
                      Generate a live analysis for <strong>{brand.domain || brand.name}</strong> to see KPIs, findings, charts, predictions, and recommendations — all from your real connected data sources.
                    </p>
                  </div>
                  <button
                    onClick={() => runAnalysis()}
                    className="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-brand-600 text-white text-sm font-semibold hover:bg-brand-700 transition-colors shadow-sm"
                  >
                    <PlayCircle className="w-4 h-4" />
                    Generate Live Analysis
                  </button>
                  <p className="text-[10px] text-slate-400">Uses GSC, GA4, and Technical Audit data for the last 28 days</p>
                </div>
              </div>
            )}

            {brandReady && analysisLoading && !analysisResult && (
              <div className="flex-1 flex items-center justify-center">
                <div className="text-center space-y-3">
                  <Loader2 className="w-10 h-10 text-brand-500 animate-spin mx-auto" />
                  <div>
                    <p className="text-sm font-semibold text-slate-700">Generating analysis...</p>
                    <p className="text-xs text-slate-400 mt-1">Pulling data from connected sources and building your report</p>
                  </div>
                </div>
              </div>
            )}

            {analysisResult && (
              <>
                <div className="flex items-center gap-1 bg-slate-50 rounded-xl border border-slate-200 p-1 mb-3 shrink-0 self-start">
                  {(["artifact", "report", "review"] as const).map(v => (
                    <button key={v} onClick={() => setAnalysisView(v)}
                      className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg text-xs font-semibold transition-colors ${
                        analysisView === v ? "bg-white text-slate-900 shadow-sm" : "text-slate-500 hover:text-slate-700"
                      }`}>
                      {v === "artifact" && <Activity className="w-3 h-3" />}
                      {v === "report" && <FileText className="w-3 h-3" />}
                      {v === "review" && <ListChecks className="w-3 h-3" />}
                      {v === "artifact" ? "Live Artifact" : v === "report" ? "Written Report" : "Review Actions"}
                    </button>
                  ))}
                </div>

                <div className="flex-1 min-h-0 bg-white rounded-xl border border-slate-200 overflow-hidden">
                  {analysisView === "artifact" ? (
                    <AnalysisArtifact analysis={analysisResult} onRefresh={() => runAnalysis()} />
                  ) : analysisView === "report" ? (
                    <NarrativeReport analysis={analysisResult} />
                  ) : (
                    <ReviewPanel
                      actions={((analysisResult as unknown as { extractedActions?: ExtractedAction[] }).extractedActions) ?? []}
                      brandId={brand.id}
                      onClose={() => setAnalysisView("artifact")}
                    />
                  )}
                </div>
              </>
            )}
          </div>
        )}

        {/* ── CHAT VIEW ── */}
        {pageView === "chat" && (
          <div className="flex-1 flex flex-col min-h-0 min-w-0">

            {messages.some(m => m.artifacts && m.artifacts.length > 0) && (
              <div className="flex items-center gap-1 bg-slate-50 rounded-xl border border-slate-200 p-1 mb-3 shrink-0 self-start">
                <button onClick={() => setChatTab("messages")}
                  className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg text-xs font-semibold transition-colors ${chatTab === "messages" ? "bg-white text-slate-900 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
                  <MessageSquare className="w-3 h-3" /> Messages
                </button>
                <button onClick={() => setChatTab("artifact")}
                  className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg text-xs font-semibold transition-colors ${chatTab === "artifact" ? "bg-white text-slate-900 shadow-sm" : "text-slate-500 hover:text-slate-700"}`}>
                  <LayoutDashboard className="w-3 h-3" /> Artifact
                </button>
              </div>
            )}

            {chatTab === "artifact" && (() => {
              const lastArtifactMsg = [...messages].reverse().find(m => m.artifacts && m.artifacts.length > 0);
              const art = lastArtifactMsg?.artifacts?.[lastArtifactMsg.artifacts.length - 1];
              return art ? (
                <div className="flex-1 min-h-0 bg-white rounded-xl border border-slate-200 overflow-hidden">
                  <ArtifactRenderer title={art.title} code={art.code} renderError={art.renderError} />
                </div>
              ) : null;
            })()}

            {chatTab === "messages" && <div className="flex-1 overflow-y-auto min-h-0 space-y-4 pr-1">

              <div className="flex items-center gap-2 px-1">
                {editingHeaderTitle ? (
                  <input
                    autoFocus
                    value={headerTitleDraft}
                    onChange={(e) => setHeaderTitleDraft(e.target.value)}
                    onBlur={commitHeaderTitle}
                    onKeyDown={(e) => {
                      if (e.key === "Enter") { e.preventDefault(); commitHeaderTitle(); }
                      if (e.key === "Escape") { e.preventDefault(); setEditingHeaderTitle(false); }
                    }}
                    maxLength={100}
                    className="flex-1 min-w-0 text-sm font-bold text-slate-800 px-2 py-1 border border-brand-300 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-brand-500"
                  />
                ) : (
                  <button
                    onClick={beginHeaderEdit}
                    disabled={!activeSessionId}
                    title={activeSessionId ? "Click to rename" : "Starting new session…"}
                    className="group flex items-center gap-1.5 text-sm font-bold text-slate-800 hover:text-brand-700 disabled:text-slate-400 disabled:cursor-default transition-colors min-w-0"
                  >
                    <span className="truncate">{activeSessionTitle}</span>
                    <Pencil className="w-3 h-3 opacity-0 group-hover:opacity-100 text-slate-400 shrink-0 transition-opacity" />
                  </button>
                )}
              </div>

              <div className={`rounded-lg px-4 py-2 text-xs font-medium flex items-center gap-2 border ${
                mode === "strategist"
                  ? "bg-brand-50 text-brand-700 border-brand-200"
                  : "bg-purple-50 text-purple-700 border-purple-200"
              }`}>
                {mode === "strategist"
                  ? <><Zap className="w-3.5 h-3.5" /> <strong>Strategist mode</strong> — All data sources active</>
                  : <><User className="w-3.5 h-3.5" /> <strong>Client-Friendly mode</strong> — Plain-language analysis</>}
              </div>

              {siteTagInstalled && (
                <DataMaturityNotice
                  installedDays={siteTagAge}
                  installedAt={siteTagInstalledAt}
                  compact
                  className="px-1"
                />
              )}

              {messages.map(msg => {
                const hasArtifacts = msg.role === "assistant" && !!msg.artifacts && msg.artifacts.length > 0;
                return (
                <div key={msg.id} className="space-y-2">
                  <div className={`flex gap-3 ${msg.role === "user" ? "justify-end" : "justify-start"}`}>
                    {msg.role === "assistant" && (
                      <div className="w-7 h-7 rounded-full bg-gradient-to-br from-brand-500 to-purple-600 flex items-center justify-center shrink-0 mt-0.5 shadow-sm">
                        <Sparkles className="w-3.5 h-3.5 text-white" />
                      </div>
                    )}
                    <div className="max-w-[82%] space-y-2">
                      {(msg.role === "user" || msg.text.trim().length > 0) && (
                        <div className={`rounded-2xl px-4 py-3 ${
                          msg.role === "user"
                            ? "bg-brand-600 text-white rounded-tr-sm"
                            : "bg-white border border-slate-200 rounded-tl-sm shadow-sm"
                        }`}>
                          {msg.role === "user"
                            ? <p className="text-sm leading-relaxed text-white">{msg.text}</p>
                            : <MarkdownContent className="text-sm text-slate-700">{msg.text}</MarkdownContent>
                          }
                          <p className={`text-[10px] mt-1.5 ${msg.role === "user" ? "text-brand-200 text-right" : "text-slate-400"}`}>{msg.timestamp}</p>
                        </div>
                      )}

                      {msg.role === "assistant" && msg.id === messages[messages.length - 1]?.id && (
                        <div className="flex flex-wrap gap-1.5">
                          {buildFollowUpSuggestions(analysisResult).map((suggestion) => (
                            <button
                              key={suggestion}
                              onClick={() => send(suggestion)}
                              className="flex items-center gap-1 text-[11px] text-slate-500 bg-slate-50 border border-slate-200 hover:bg-brand-50 hover:border-brand-300 hover:text-brand-700 px-2.5 py-1 rounded-full transition-colors"
                            >
                              <ChevronRight className="w-2.5 h-2.5" />
                              {suggestion}
                            </button>
                          ))}
                        </div>
                      )}
                    </div>
                    {msg.role === "user" && (
                      <div className="w-7 h-7 rounded-full bg-slate-200 flex items-center justify-center shrink-0 mt-0.5">
                        <User className="w-3.5 h-3.5 text-slate-500" />
                      </div>
                    )}
                  </div>

                  {hasArtifacts && (
                    <div className="ml-10 space-y-3">
                      {msg.artifacts!.map((artifact, ai) => (
                        <ArtifactRenderer key={`${msg.id}-${ai}`} title={artifact.title} code={artifact.code} renderError={artifact.renderError} />
                      ))}
                    </div>
                  )}
                </div>
                );
              })}

              {isTyping && (
                <div className="flex gap-3 justify-start">
                  <div className="w-7 h-7 rounded-full bg-gradient-to-br from-brand-500 to-purple-600 flex items-center justify-center shrink-0">
                    <Sparkles className="w-3.5 h-3.5 text-white" />
                  </div>
                  <div className="bg-white border border-slate-200 rounded-2xl rounded-tl-sm px-4 py-3 shadow-sm">
                    <div className="flex items-center gap-1">
                      <span className="w-1.5 h-1.5 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: "0ms" }} />
                      <span className="w-1.5 h-1.5 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: "150ms" }} />
                      <span className="w-1.5 h-1.5 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: "300ms" }} />
                    </div>
                  </div>
                </div>
              )}
              <div ref={bottomRef} />
            </div>}

            <div className="mt-2 shrink-0">
              <div className="flex flex-wrap gap-1.5">
                {buildSuggestedPrompts(analysisResult, mode).map((p, i) => (
                  <button
                    key={i}
                    onClick={() => send(p.prompt)}
                    title={p.prompt}
                    className="text-[11px] text-slate-500 bg-slate-50 border border-slate-200 hover:bg-brand-50 hover:border-brand-300 hover:text-brand-700 px-2.5 py-1 rounded-full transition-colors"
                  >
                    {p.label}
                  </button>
                ))}
              </div>
            </div>

            <div className="mt-3 bg-white rounded-xl border border-slate-200 shadow-sm shrink-0 flex items-end gap-2 px-4 py-3">
              <textarea
                ref={inputRef}
                rows={1}
                value={input}
                onChange={e => setInput(e.target.value)}
                onKeyDown={handleKey}
                placeholder={mode === "strategist" ? "Ask about rankings, traffic, conversions, competitors…" : "Ask a question about your website…"}
                className="flex-1 resize-none text-sm text-slate-800 placeholder-slate-400 focus:outline-none leading-relaxed bg-transparent max-h-32"
              />
              <button onClick={() => send(input)} disabled={!input.trim() || isTyping}
                className="w-8 h-8 rounded-lg bg-brand-600 hover:bg-brand-700 disabled:opacity-40 disabled:cursor-not-allowed flex items-center justify-center transition-colors shrink-0">
                <Send className="w-3.5 h-3.5 text-white" />
              </button>
            </div>
          </div>
        )}

        {pageView === "chat" && (
          <div className="w-48 shrink-0 flex flex-col gap-3 min-h-0">
            {analysisResult && (
              <div className="bg-white rounded-xl border border-slate-200 overflow-hidden shrink-0 px-3 py-2.5">
                <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-1">Active Analysis</p>
                <p className="text-[11px] text-slate-600">{analysisResult.period.start} → {analysisResult.period.end}</p>
                <p className="text-[10px] text-slate-400 mt-0.5">{analysisResult.findings.length} findings · {analysisResult.recommendations.length} recs</p>
              </div>
            )}
            <div className="bg-white rounded-xl border border-slate-200 overflow-hidden shrink-0">
              <ul className="py-1">
                {SHORTCUTS.map(s => (
                  <li key={s.href}>
                    <Link href={s.href}
                      className="flex items-center gap-2 px-3 py-2 hover:bg-slate-50 transition-colors group">
                      <s.icon className="w-3.5 h-3.5 text-slate-400 group-hover:text-brand-600 transition-colors shrink-0" />
                      <span className="text-[11px] font-medium text-slate-500 group-hover:text-brand-600 transition-colors">{s.label}</span>
                    </Link>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        )}

      </div>
    </div>
  );
}
