"use client";

/**
 * Industry Intel — AI market intelligence dashboard. Daily briefings
 * correlating external events with brand performance.
 */

import { useCallback, useEffect, useState } from "react";
import { useBrand } from "@/context/brand-context";
import { useBackgroundTasks } from "@/lib/stores/task-store";
import FeatureGate from "@/components/plan/feature-gate";
import { Globe, RefreshCw, Loader2, Clock, ChevronDown } from "lucide-react";

import BriefingSummary from "@/components/industry-intel/briefing-summary";
import EventsTimeline from "@/components/industry-intel/events-timeline";
import CorrelationChart from "@/components/industry-intel/correlation-chart";
import MarketTrends from "@/components/industry-intel/market-trends";
import SeasonalInsights from "@/components/industry-intel/seasonal-insights";
import SearchTrends from "@/components/industry-intel/search-trends";
import BenchmarksPanel from "@/components/industry-intel/benchmarks-panel";
import PredictionsPanel from "@/components/industry-intel/predictions-panel";
import VisitorGeography from "@/components/industry-intel/visitor-geography";

interface Briefing {
  id: string; industry: string; locations: unknown; summary: string | null;
  marketTrends: unknown; externalEvents: unknown; seasonalInsights: unknown;
  searchTrends: unknown; performanceCorrelation: unknown; predictions: unknown;
  competitorActivity: unknown; generatedAt: string;
  // `sources` is a free-form Json field on IndustryBriefing — server
  // stuffs additional context in here without schema migrations
  // (gsc/ga4/ai/competitors/gbp/siteTag flags + the new
  // visitorCountries / serviceLocations / geoTrackingEnabled
  // payload). Typed as `unknown` so we narrow defensively at the
  // render site instead of pretending the shape is guaranteed.
  sources?: unknown;
}
interface HistoryEntry { id: string; summary: string | null; generatedAt: string }

const LOADING_MSGS = ["AI is researching your market...", "Analyzing industry trends...", "Correlating with your performance...", "Building strategic predictions..."];

// Industry Intelligence is an Agency+ feature. Wrapping the
// default export in FeatureGate catches direct navigations that
// bypass the sidebar's locked-click handler.
export default function IndustryIntelPageGated() {
  return (
    <FeatureGate feature="industry_intel">
      <IndustryIntelPage />
    </FeatureGate>
  );
}

function IndustryIntelPage() {
  const { brand } = useBrand();
  const { addTask, completeTask, failTask } = useBackgroundTasks();
  const [briefing, setBriefing] = useState<Briefing | null>(null);
  const [history, setHistory] = useState<HistoryEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [generating, setGenerating] = useState(false);
  const [loadingMsg, setLoadingMsg] = useState("");
  const [historyOpen, setHistoryOpen] = useState(false);
  // Scope toggle. Default is "local" because that matches the cron's
  // default and is the higher-value view for multi-location brands.
  // Switching scope re-fetches /latest with a scope filter so the
  // page swaps between cached local + national briefings without a
  // generate trigger.
  const [scope, setScope] = useState<"local" | "national">("local");
  const [generateError, setGenerateError] = useState<string | null>(null);

  const loadLatest = useCallback(async () => {
    if (!brand?.id) return;
    setLoading(true);
    const [bRes, hRes] = await Promise.all([
      fetch(`/api/industry-intel/latest?brandId=${brand.id}&scope=${scope}`),
      fetch(`/api/industry-intel/history?brandId=${brand.id}&limit=10`),
    ]);
    if (bRes.ok) { const d = await bRes.json(); setBriefing(d.briefing ?? null); }
    if (hRes.ok) { const d = await hRes.json(); setHistory(d.briefings ?? []); }
    setLoading(false);
  }, [brand.id, scope]);

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

  async function generate() {
    setGenerating(true);
    setGenerateError(null);
    let msgIdx = 0;
    setLoadingMsg(LOADING_MSGS[0]);
    const interval = setInterval(() => { msgIdx = (msgIdx + 1) % LOADING_MSGS.length; setLoadingMsg(LOADING_MSGS[msgIdx]); }, 3000);
    const taskId = addTask({ id: `briefing_${Date.now()}`, type: "industry_briefing", label: `Generating ${scope === "local" ? "Local" : "National"} Briefing...`, brandId: brand.id, resultUrl: "/industry-intel" });
    try {
      const res = await fetch("/api/industry-intel/generate", {
        method: "POST", headers: { "Content-Type": "application/json" },
        // force=true bypasses the 24h cache so "Generate Fresh"
        // actually does so. Without it, the route returns the cached
        // row and the user sees no UI change.
        body: JSON.stringify({ brandId: brand.id, scope, force: true }),
      });
      if (res.ok) { const d = await res.json(); setBriefing(d.briefing ?? null); await loadLatest(); completeTask(taskId, { resultUrl: "/industry-intel", resultSummary: `${scope === "local" ? "Local" : "National"} briefing generated` }); }
      else {
        const errBody = await res.json().catch(() => ({}));
        const msg = (errBody as { error?: string }).error ?? "Briefing generation failed";
        setGenerateError(msg);
        failTask(taskId, msg);
      }
    } catch { setGenerateError("Network error — please try again"); failTask(taskId, "Network error"); }
    clearInterval(interval); setGenerating(false);
  }

  async function loadBriefing(id: string) {
    setLoading(true);
    // Fetch the specific briefing from the latest endpoint won't work for historical—
    // fallback to checking history data. In a real implementation, there'd be a GET by ID.
    // For now, generate fresh or use cached.
    const entry = history.find((h) => h.id === id);
    if (entry) {
      const res = await fetch(`/api/industry-intel/latest?brandId=${brand.id}`);
      if (res.ok) { const d = await res.json(); if (d.briefing) setBriefing(d.briefing); }
    }
    setHistoryOpen(false);
    setLoading(false);
  }

  const arr = (v: unknown): unknown[] => Array.isArray(v) ? v : [];
  // Locations field used to be string[] (e.g. ["Houston, TX"]) and is
  // now BrandLocation[] (e.g. [{ label, city, state, source }]) for
  // local-scope briefings. Normalise both shapes to a plain string[]
  // so the UI doesn't need to care which version produced the row.
  const locs = (v: unknown): string[] => {
    if (!Array.isArray(v)) return [];
    return v
      .map((x) => {
        if (typeof x === "string") return x;
        if (x && typeof x === "object" && "label" in x && typeof (x as { label: unknown }).label === "string") {
          return (x as { label: string }).label;
        }
        return null;
      })
      .filter((s): s is string => !!s);
  };

  if (loading) return <div className="flex items-center justify-center h-64"><div className="w-8 h-8 border-4 border-brand-100 border-t-brand-600 rounded-full animate-spin" /></div>;

  // Empty state
  if (!briefing) {
    return (
      <div className="space-y-6 max-w-5xl">
        <div className="flex items-start justify-between">
          <div>
            <h1 className="text-2xl font-bold text-slate-900">Industry Intel</h1>
            <p className="text-slate-500 text-sm mt-1">AI-powered market intelligence for {brand.domain}</p>
          </div>
          {/* Scope toggle even on empty state so the user picks
              before generating — local uses GBP + brand profile,
              national uses the broad industry view. */}
          <div className="inline-flex rounded-lg border border-slate-200 bg-white p-0.5">
            <button
              onClick={() => setScope("local")}
              className={`px-3 py-1.5 rounded-md text-[11px] font-semibold transition-colors ${scope === "local" ? "bg-brand-600 text-white" : "text-slate-600 hover:bg-slate-50"}`}
            >
              🏠 Local
            </button>
            <button
              onClick={() => setScope("national")}
              className={`px-3 py-1.5 rounded-md text-[11px] font-semibold transition-colors ${scope === "national" ? "bg-brand-600 text-white" : "text-slate-600 hover:bg-slate-50"}`}
            >
              🌐 National
            </button>
          </div>
        </div>
        <div className="bg-white rounded-xl border border-slate-200 p-12 text-center">
          <Globe className="w-14 h-14 text-slate-200 mx-auto mb-4" />
          <h2 className="text-lg font-bold text-slate-900 mb-1">Generate Your First {scope === "local" ? "Local" : "National"} Briefing</h2>
          <p className="text-sm text-slate-500 max-w-md mx-auto mb-6">
            {scope === "local"
              ? "The AI will research what's happening in your specific cities — local weather, healthcare news, regulatory shifts, community events, and competitor activity — then map it to your business."
              : "The AI will research market trends, external events, seasonal patterns, and competitor activity — then correlate everything with your performance data."}
          </p>
          <button onClick={generate} disabled={generating} className="inline-flex items-center gap-2 px-6 py-3 bg-brand-600 text-white text-sm font-semibold rounded-xl hover:bg-brand-700 disabled:opacity-50">
            {generating ? <><Loader2 className="w-4 h-4 animate-spin" /> {loadingMsg}</> : <><Globe className="w-4 h-4" /> Generate {scope === "local" ? "Local" : "National"} Briefing</>}
          </button>
          {generateError && (
            <p className="mt-3 text-sm text-red-600 font-medium">Generation failed: {generateError}</p>
          )}
        </div>
      </div>
    );
  }

  const industry = briefing.industry;
  const locations = locs(briefing.locations);
  const events = arr(briefing.externalEvents) as Array<Record<string, unknown>>;
  const trends = arr(briefing.marketTrends) as Array<Record<string, unknown>>;
  const seasonal = arr(briefing.seasonalInsights) as Array<Record<string, unknown>>;
  const search = arr(briefing.searchTrends) as Array<Record<string, unknown>>;
  const correlations = arr(briefing.performanceCorrelation) as Array<Record<string, unknown>>;
  const predictions = arr(briefing.predictions) as Array<Record<string, unknown>>;

  return (
    <div className="space-y-6 max-w-6xl">
      {/* Header */}
      <div className="flex items-start justify-between">
        <div>
          <h1 className="text-2xl font-bold text-slate-900">Industry Intel</h1>
          <p className="text-slate-500 text-sm mt-1">
            {industry} · {locations.length > 0 ? locations.join(", ") : "United States"}
            <span className="ml-2 text-[10px] font-bold uppercase tracking-widest text-slate-400">
              {scope === "local" ? "Local view" : "National view"}
            </span>
          </p>
        </div>
        <div className="flex items-center gap-2">
          {/* Scope toggle — segmented control. Switching loads the
              cached briefing for the new scope; "Generate Fresh"
              actually regenerates it (with force=true on the API). */}
          <div className="inline-flex rounded-lg border border-slate-200 bg-white p-0.5">
            <button
              onClick={() => setScope("local")}
              className={`px-3 py-1.5 rounded-md text-[11px] font-semibold transition-colors ${scope === "local" ? "bg-brand-600 text-white" : "text-slate-600 hover:bg-slate-50"}`}
              aria-pressed={scope === "local"}
            >
              🏠 Local
            </button>
            <button
              onClick={() => setScope("national")}
              className={`px-3 py-1.5 rounded-md text-[11px] font-semibold transition-colors ${scope === "national" ? "bg-brand-600 text-white" : "text-slate-600 hover:bg-slate-50"}`}
              aria-pressed={scope === "national"}
            >
              🌐 National
            </button>
          </div>

          {/* History dropdown */}
          {history.length > 1 && (
            <div className="relative">
              <button onClick={() => setHistoryOpen(!historyOpen)} className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 text-xs font-semibold text-slate-600 hover:bg-slate-50">
                <Clock className="w-3.5 h-3.5" /> History <ChevronDown className="w-3 h-3" />
              </button>
              {historyOpen && (
                <>
                  <div className="fixed inset-0 z-30" onClick={() => setHistoryOpen(false)} />
                  <div className="absolute right-0 top-full mt-1 bg-white border border-slate-200 rounded-xl shadow-xl z-40 min-w-[240px] py-1">
                    {history.map((h) => (
                      <button key={h.id} onClick={() => loadBriefing(h.id)} className="w-full text-left px-3 py-2 hover:bg-slate-50 text-xs">
                        <span className="font-semibold text-slate-700">{new Date(h.generatedAt).toLocaleDateString("en-US", { month: "short", day: "numeric" })}</span>
                        {h.summary && <p className="text-slate-500 line-clamp-1 mt-0.5">{h.summary}</p>}
                      </button>
                    ))}
                  </div>
                </>
              )}
            </div>
          )}
          <div className="flex flex-col items-end gap-1">
            <button onClick={generate} disabled={generating} className="flex items-center gap-1.5 px-4 py-2 bg-brand-600 text-white text-xs font-semibold rounded-lg hover:bg-brand-700 disabled:opacity-50">
              {generating ? <><Loader2 className="w-3.5 h-3.5 animate-spin" /> {loadingMsg}</> : <><RefreshCw className="w-3.5 h-3.5" /> Generate Fresh</>}
            </button>
            {generateError && (
              <p className="text-xs text-red-600 font-medium max-w-[240px] text-right">Generation failed: {generateError}</p>
            )}
          </div>
        </div>
      </div>

      {/* Executive summary */}
      {briefing.summary && (
        <BriefingSummary summary={briefing.summary} industry={industry} locations={locations}
          trendCount={trends.length} eventCount={events.length} predictionCount={predictions.length}
          generatedAt={briefing.generatedAt} />
      )}

      {/* Where Your Visitors Come From — surfaces the
          visitorCountries + serviceLocations the server stashes in
          `briefing.sources`. Renders ONLY for local-scope briefings
          (national doesn't have geo context to begin with). Empty-
          state copy nudges the user toward installing the Site Tag
          when geoTrackingEnabled is false. */}
      <VisitorGeography sources={briefing.sources} scope={scope} />

      {/* External events timeline */}
      <EventsTimeline events={events as []} />

      {/* Performance correlations */}
      <CorrelationChart correlations={correlations as []} brandId={brand.id} />

      {/* Market trends */}
      <MarketTrends trends={trends as []} />

      {/* Seasonal insights */}
      <SeasonalInsights insights={seasonal as []} />

      {/* Search trends */}
      <SearchTrends trends={search as []} brandId={brand.id} />

      {/* Industry benchmarks */}
      <BenchmarksPanel industry={industry} />

      {/* Predictions */}
      <PredictionsPanel predictions={predictions as []} />
    </div>
  );
}
