/**
 * @file Research Dashboard MCP App — displays competitor analysis results.
 * Receives ResearchResult via ontoolresult, renders interactive dashboard.
 * All interactivity (sort, expand, filter) is client-side.
 */
import type { App as McpApp, McpUiHostContext } from "@modelcontextprotocol/ext-apps";
import { useApp, useHostStyles } from "@modelcontextprotocol/ext-apps/react";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import {
  useState,
  useEffect,
  useCallback,
  useMemo,
  type CSSProperties,
  type ReactNode,
} from "react";
import {
  ScatterChart,
  Scatter,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  Cell,
  ZAxis,
} from "recharts";
import type {
  ResearchResult,
  CompetitorAnalysis,
  PricingInfo,
  PositionQuadrant,
} from "../../types";

/* ------------------------------------------------------------------ */
/*  Helpers                                                            */
/* ------------------------------------------------------------------ */

function parseResultData(result: CallToolResult): ResearchResult | null {
  try {
    // Try structuredContent first (expected path)
    const raw = (result as unknown as { structuredContent?: unknown }).structuredContent;
    if (raw && typeof raw === "object") return raw as ResearchResult;

    // Fallback: extract from text content
    const textParts = result.content
      ?.filter((c): c is { type: "text"; text: string } => c.type === "text")
      .map((c) => c.text)
      .join("");
    if (textParts) return JSON.parse(textParts) as ResearchResult;
  } catch {
    console.error("Failed to parse research result");
  }
  return null;
}

function formatDate(iso: string): string {
  try {
    return new Date(iso).toLocaleDateString("en-US", {
      month: "short",
      day: "numeric",
      year: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso;
  }
}

function classifyOpportunity(text: string): { icon: string; type: string } {
  const lower = text.toLowerCase();
  if (lower.includes("pricing") || lower.includes("price") || lower.includes("cost"))
    return { icon: "💰", type: "Pricing Gap" };
  if (lower.includes("feature") || lower.includes("functionality"))
    return { icon: "⚡", type: "Feature Gap" };
  if (lower.includes("content") || lower.includes("blog") || lower.includes("article"))
    return { icon: "📝", type: "Content" };
  if (lower.includes("social") || lower.includes("community"))
    return { icon: "📱", type: "Social" };
  if (lower.includes("seo") || lower.includes("search") || lower.includes("keyword"))
    return { icon: "🔎", type: "SEO" };
  return { icon: "💡", type: "Opportunity" };
}

/* ------------------------------------------------------------------ */
/*  Styles                                                             */
/* ------------------------------------------------------------------ */

const s: Record<string, CSSProperties> = {
  root: {
    fontFamily: "var(--font-sans, system-ui, -apple-system, sans-serif)",
    color: "var(--color-text-primary, #1a1a2e)",
    background: "var(--color-background-primary, #ffffff)",
    padding: "20px 20px 40px",
    lineHeight: 1.5,
    maxWidth: 900,
    margin: "0 auto",
  },

  /* Header */
  header: {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "flex-start",
    marginBottom: 24,
    flexWrap: "wrap" as const,
    gap: 12,
  },
  headerTitle: { fontSize: 22, fontWeight: 700, margin: 0 },
  headerSub: { fontSize: 13, color: "var(--color-text-secondary, #64748b)", marginTop: 2 },
  badge: {
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    padding: "3px 10px",
    fontSize: 12,
    fontWeight: 700,
    borderRadius: 999,
    background: "#3b82f6",
    color: "#fff",
    letterSpacing: 0.3,
  },
  fullscreenBtn: {
    padding: "6px 14px",
    fontSize: 12,
    fontWeight: 600,
    color: "#3b82f6",
    background: "#eff6ff",
    border: "1px solid #bfdbfe",
    borderRadius: 8,
    cursor: "pointer",
    fontFamily: "inherit",
  },

  /* Overview cards */
  cardGrid: {
    display: "grid",
    gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
    gap: 12,
    marginBottom: 24,
  },
  card: {
    background: "var(--color-background-secondary, #f8fafc)",
    border: "1px solid var(--color-border-primary, #e2e8f0)",
    borderRadius: 10,
    padding: "16px 18px",
  },
  cardLabel: {
    fontSize: 11,
    fontWeight: 600,
    textTransform: "uppercase" as const,
    letterSpacing: 0.5,
    color: "var(--color-text-secondary, #94a3b8)",
    marginBottom: 6,
  },
  cardValue: { fontSize: 22, fontWeight: 700, color: "var(--color-text-primary, #1e293b)" },

  /* Panel/section */
  panel: {
    background: "var(--color-background-secondary, #f8fafc)",
    border: "1px solid var(--color-border-primary, #e2e8f0)",
    borderRadius: 12,
    padding: "18px 20px",
    marginBottom: 20,
  },
  panelTitle: {
    fontSize: 15,
    fontWeight: 600,
    marginBottom: 14,
    display: "flex",
    alignItems: "center",
    gap: 8,
  },

  /* Comparison matrix */
  table: {
    width: "100%",
    borderCollapse: "collapse" as const,
    fontSize: 13,
  },
  th: {
    textAlign: "left" as const,
    padding: "8px 10px",
    fontWeight: 600,
    fontSize: 12,
    color: "var(--color-text-secondary, #64748b)",
    borderBottom: "2px solid var(--color-border-primary, #e2e8f0)",
    cursor: "pointer",
    userSelect: "none" as const,
    whiteSpace: "nowrap" as const,
  },
  td: {
    padding: "10px 10px",
    borderBottom: "1px solid var(--color-border-primary, #e2e8f0)",
    verticalAlign: "top" as const,
  },
  rowClickable: {
    cursor: "pointer",
    transition: "background 0.12s",
  },

  /* Strength/weakness badges */
  strengthBadge: {
    display: "inline-block",
    padding: "2px 8px",
    fontSize: 12,
    fontWeight: 500,
    borderRadius: 6,
    background: "#dcfce7",
    color: "#166534",
    margin: "2px 4px 2px 0",
  },
  weaknessBadge: {
    display: "inline-block",
    padding: "2px 8px",
    fontSize: 12,
    fontWeight: 500,
    borderRadius: 6,
    background: "#fee2e2",
    color: "#991b1b",
    margin: "2px 4px 2px 0",
  },
  neutralBadge: {
    display: "inline-block",
    padding: "2px 8px",
    fontSize: 12,
    fontWeight: 500,
    borderRadius: 6,
    background: "#fef3c7",
    color: "#92400e",
    margin: "2px 4px 2px 0",
  },

  /* Expandable card */
  expandCard: {
    border: "1px solid var(--color-border-primary, #e2e8f0)",
    borderRadius: 10,
    marginBottom: 10,
    overflow: "hidden",
    background: "var(--color-background-primary, #ffffff)",
  },
  expandHeader: {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    padding: "12px 16px",
    cursor: "pointer",
    transition: "background 0.12s",
    fontWeight: 600,
    fontSize: 14,
  },
  expandBody: {
    padding: "0 16px 16px",
    fontSize: 13,
    lineHeight: 1.6,
  },
  expandChevron: {
    fontSize: 14,
    color: "var(--color-text-secondary, #94a3b8)",
    transition: "transform 0.2s",
  },

  /* Opportunity list */
  oppItem: {
    display: "flex",
    alignItems: "flex-start",
    gap: 10,
    padding: "10px 0",
    borderBottom: "1px solid var(--color-border-primary, #f1f5f9)",
    fontSize: 13,
  },
  oppBadge: {
    display: "inline-flex",
    alignItems: "center",
    gap: 4,
    padding: "2px 8px",
    fontSize: 11,
    fontWeight: 600,
    borderRadius: 6,
    background: "#eff6ff",
    color: "#1e40af",
    whiteSpace: "nowrap" as const,
    flexShrink: 0,
  },

  /* Pricing cards */
  pricingGrid: {
    display: "grid",
    gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
    gap: 12,
  },
  pricingCard: {
    border: "1px solid var(--color-border-primary, #e2e8f0)",
    borderRadius: 10,
    padding: 16,
    background: "var(--color-background-primary, #ffffff)",
  },
  pricingCompetitor: {
    fontSize: 14,
    fontWeight: 700,
    marginBottom: 10,
    color: "var(--color-text-primary, #1e293b)",
  },
  pricingTier: {
    marginBottom: 8,
    padding: "8px 10px",
    borderRadius: 6,
    background: "var(--color-background-secondary, #f8fafc)",
    fontSize: 12,
  },
  pricingTierName: { fontWeight: 600, marginBottom: 2 },
  pricingTierPrice: { color: "#3b82f6", fontWeight: 700, marginBottom: 4, fontSize: 14 },

  /* Skeleton loading */
  skeleton: {
    height: 16,
    borderRadius: 6,
    background: "linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%)",
    backgroundSize: "200% 100%",
    animation: "shimmer 1.5s infinite",
    marginBottom: 10,
  },

  /* Center / empty states */
  center: {
    textAlign: "center" as const,
    padding: "60px 20px",
    color: "var(--color-text-secondary, #94a3b8)",
  },
};

/* ------------------------------------------------------------------ */
/*  Sub-components                                                     */
/* ------------------------------------------------------------------ */

function OverviewCards({ data }: { data: ResearchResult }) {
  const cards = [
    { label: "Competitors Analyzed", value: data.analyses.length, icon: "🎯" },
    { label: "Industry", value: data.brief.company.industry, icon: "🏢" },
    { label: "Opportunities Found", value: data.opportunities.length, icon: "💡" },
    { label: "Last Updated", value: formatDate(data.generatedAt), icon: "🕐" },
  ];
  return (
    <div style={s.cardGrid}>
      {cards.map((c) => (
        <div key={c.label} style={s.card}>
          <div style={s.cardLabel}>
            {c.icon} {c.label}
          </div>
          <div style={{ ...s.cardValue, fontSize: typeof c.value === "number" ? 28 : 16 }}>{c.value}</div>
        </div>
      ))}
    </div>
  );
}

/* -- Comparison Matrix -- */

type SortKey = "name" | "features" | "strengths" | "weaknesses";
type SortDir = "asc" | "desc";

function ComparisonMatrix({
  analyses,
  onExpandCompetitor,
}: {
  analyses: CompetitorAnalysis[];
  onExpandCompetitor: (name: string) => void;
}) {
  const [sortKey, setSortKey] = useState<SortKey>("name");
  const [sortDir, setSortDir] = useState<SortDir>("asc");

  const toggleSort = (key: SortKey) => {
    if (sortKey === key) setSortDir((d) => (d === "asc" ? "desc" : "asc"));
    else {
      setSortKey(key);
      setSortDir("asc");
    }
  };

  const sorted = useMemo(() => {
    const copy = [...analyses];
    copy.sort((a, b) => {
      let cmp = 0;
      switch (sortKey) {
        case "name":
          cmp = a.competitor.name.localeCompare(b.competitor.name);
          break;
        case "features":
          cmp = a.features.length - b.features.length;
          break;
        case "strengths":
          cmp = a.strengths.length - b.strengths.length;
          break;
        case "weaknesses":
          cmp = a.weaknesses.length - b.weaknesses.length;
          break;
      }
      return sortDir === "asc" ? cmp : -cmp;
    });
    return copy;
  }, [analyses, sortKey, sortDir]);

  const arrow = (key: SortKey) => (sortKey === key ? (sortDir === "asc" ? " ↑" : " ↓") : "");

  const countColor = (n: number, type: "good" | "bad" | "neutral") => {
    if (type === "good") return n >= 3 ? "#16a34a" : n >= 1 ? "#ca8a04" : "#94a3b8";
    if (type === "bad") return n >= 3 ? "#dc2626" : n >= 1 ? "#ca8a04" : "#16a34a";
    return "#64748b";
  };

  return (
    <div style={{ overflowX: "auto" }}>
      <table style={s.table}>
        <thead>
          <tr>
            <th style={s.th} onClick={() => toggleSort("name")}>
              Competitor{arrow("name")}
            </th>
            <th style={s.th} onClick={() => toggleSort("features")}>
              Features{arrow("features")}
            </th>
            <th style={s.th} onClick={() => toggleSort("strengths")}>
              Strengths{arrow("strengths")}
            </th>
            <th style={s.th} onClick={() => toggleSort("weaknesses")}>
              Weaknesses{arrow("weaknesses")}
            </th>
            <th style={{ ...s.th, cursor: "default" }}>SEO</th>
            <th style={{ ...s.th, cursor: "default" }}>Social</th>
          </tr>
        </thead>
        <tbody>
          {sorted.map((a) => (
            <tr
              key={a.competitor.name}
              style={s.rowClickable}
              onClick={() => onExpandCompetitor(a.competitor.name)}
              onMouseEnter={(e) =>
                ((e.currentTarget as HTMLTableRowElement).style.background =
                  "var(--color-background-secondary, #f8fafc)")
              }
              onMouseLeave={(e) =>
                ((e.currentTarget as HTMLTableRowElement).style.background = "transparent")
              }
            >
              <td style={{ ...s.td, fontWeight: 600 }}>
                {a.competitor.name}
                {a.competitor.url && (
                  <div style={{ fontSize: 11, color: "var(--color-text-secondary, #94a3b8)", fontWeight: 400 }}>
                    {a.competitor.url}
                  </div>
                )}
              </td>
              <td style={s.td}>
                <span style={{ fontWeight: 700, color: countColor(a.features.length, "neutral") }}>
                  {a.features.length}
                </span>
              </td>
              <td style={s.td}>
                <span style={{ fontWeight: 700, color: countColor(a.strengths.length, "good") }}>
                  {a.strengths.length}
                </span>
              </td>
              <td style={s.td}>
                <span style={{ fontWeight: 700, color: countColor(a.weaknesses.length, "bad") }}>
                  {a.weaknesses.length}
                </span>
              </td>
              <td style={s.td}>
                {a.seoMetrics ? (
                  <span style={s.neutralBadge}>{a.seoMetrics.domainAuthority ?? "—"}</span>
                ) : (
                  <span style={{ color: "#94a3b8" }}>—</span>
                )}
              </td>
              <td style={s.td}>
                {a.socialPresence && a.socialPresence.length > 0 ? (
                  <span style={s.neutralBadge}>{a.socialPresence.length} platforms</span>
                ) : (
                  <span style={{ color: "#94a3b8" }}>—</span>
                )}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

/* -- Strengths & Weaknesses expandable cards -- */

function StrengthsWeaknesses({
  analyses,
  expanded,
  onToggle,
}: {
  analyses: CompetitorAnalysis[];
  expanded: Set<string>;
  onToggle: (name: string) => void;
}) {
  return (
    <>
      {analyses.map((a) => {
        const open = expanded.has(a.competitor.name);
        return (
          <div key={a.competitor.name} style={s.expandCard}>
            <div
              style={s.expandHeader}
              onClick={() => onToggle(a.competitor.name)}
              onMouseEnter={(e) =>
                ((e.currentTarget as HTMLDivElement).style.background =
                  "var(--color-background-secondary, #f8fafc)")
              }
              onMouseLeave={(e) => ((e.currentTarget as HTMLDivElement).style.background = "transparent")}
            >
              <span>
                {a.competitor.name}
                <span style={{ fontWeight: 400, fontSize: 12, color: "var(--color-text-secondary, #94a3b8)", marginLeft: 8 }}>
                  {a.strengths.length}S / {a.weaknesses.length}W
                </span>
              </span>
              <span style={{ ...s.expandChevron, transform: open ? "rotate(180deg)" : "rotate(0)" }}>▼</span>
            </div>
            {open && (
              <div style={s.expandBody}>
                {a.strengths.length > 0 && (
                  <div style={{ marginBottom: 10 }}>
                    <div style={{ fontSize: 12, fontWeight: 600, color: "#16a34a", marginBottom: 6 }}>Strengths</div>
                    {a.strengths.map((str, i) => (
                      <span key={i} style={s.strengthBadge}>
                        {str}
                      </span>
                    ))}
                  </div>
                )}
                {a.weaknesses.length > 0 && (
                  <div>
                    <div style={{ fontSize: 12, fontWeight: 600, color: "#dc2626", marginBottom: 6 }}>Weaknesses</div>
                    {a.weaknesses.map((w, i) => (
                      <span key={i} style={s.weaknessBadge}>
                        {w}
                      </span>
                    ))}
                  </div>
                )}
                {a.features.length > 0 && (
                  <div style={{ marginTop: 10 }}>
                    <div style={{ fontSize: 12, fontWeight: 600, color: "#64748b", marginBottom: 6 }}>Key Features</div>
                    <div style={{ display: "flex", flexWrap: "wrap" as const, gap: 4 }}>
                      {a.features.map((f, i) => (
                        <span key={i} style={s.neutralBadge}>
                          {f}
                        </span>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}
          </div>
        );
      })}
    </>
  );
}

/* -- Market Positioning Scatter Chart -- */

const CHART_COLORS = ["#3b82f6", "#ef4444", "#f59e0b", "#10b981", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16"];

function PositioningChart({ data, companyName }: { data: PositionQuadrant[]; companyName: string }) {
  const chartData = data.map((d, i) => ({
    ...d,
    z: 120,
    fill: d.name === companyName ? "#3b82f6" : CHART_COLORS[(i + 1) % CHART_COLORS.length],
    isCompany: d.name === companyName,
  }));

  return (
    <ResponsiveContainer width="100%" height={320}>
      <ScatterChart margin={{ top: 20, right: 20, bottom: 20, left: 20 }}>
        <CartesianGrid strokeDasharray="3 3" stroke="var(--color-border-primary, #e2e8f0)" />
        <XAxis
          type="number"
          dataKey="x"
          name="Feature Richness"
          label={{ value: "Feature Richness →", position: "insideBottom", offset: -5, fontSize: 12, fill: "#94a3b8" }}
          tick={{ fontSize: 11, fill: "#94a3b8" }}
          domain={["auto", "auto"]}
        />
        <YAxis
          type="number"
          dataKey="y"
          name="Market Presence"
          label={{ value: "Market Presence →", angle: -90, position: "insideLeft", fontSize: 12, fill: "#94a3b8" }}
          tick={{ fontSize: 11, fill: "#94a3b8" }}
          domain={["auto", "auto"]}
        />
        <ZAxis type="number" dataKey="z" range={[80, 200]} />
        <Tooltip
          content={({ payload }) => {
            if (!payload?.length) return null;
            const d = payload[0].payload as (typeof chartData)[number];
            return (
              <div
                style={{
                  background: "var(--color-background-primary, #fff)",
                  border: "1px solid var(--color-border-primary, #e2e8f0)",
                  borderRadius: 8,
                  padding: "8px 12px",
                  fontSize: 13,
                  boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
                }}
              >
                <div style={{ fontWeight: 700 }}>
                  {d.name} {d.isCompany && "⭐"}
                </div>
                <div style={{ color: "#64748b", fontSize: 12 }}>
                  Features: {d.x} · Presence: {d.y}
                </div>
              </div>
            );
          }}
        />
        <Scatter name="Companies" data={chartData}>
          {chartData.map((entry, index) => (
            <Cell
              key={index}
              fill={entry.fill}
              stroke={entry.isCompany ? "#1e40af" : "transparent"}
              strokeWidth={entry.isCompany ? 3 : 0}
            />
          ))}
        </Scatter>
      </ScatterChart>
    </ResponsiveContainer>
  );
}

/* -- Opportunities Panel -- */

function OpportunitiesPanel({ opportunities }: { opportunities: string[] }) {
  return (
    <div>
      {opportunities.map((opp, i) => {
        const { icon, type } = classifyOpportunity(opp);
        return (
          <div key={i} style={s.oppItem}>
            <span style={s.oppBadge}>
              {icon} {type}
            </span>
            <span>{opp}</span>
          </div>
        );
      })}
    </div>
  );
}

/* -- Pricing Comparison -- */

function PricingComparison({ analyses }: { analyses: CompetitorAnalysis[] }) {
  const withPricing = analyses.filter((a) => a.pricing && a.pricing.tiers.length > 0);
  if (withPricing.length === 0) return null;

  return (
    <div style={s.panel}>
      <div style={s.panelTitle}>💰 Pricing Comparison</div>
      <div style={s.pricingGrid}>
        {withPricing.map((a) => (
          <div key={a.competitor.name} style={s.pricingCard}>
            <div style={s.pricingCompetitor}>{a.competitor.name}</div>
            {a.pricing!.tiers.map((tier, i) => (
              <div key={i} style={s.pricingTier}>
                <div style={s.pricingTierName}>{tier.name}</div>
                <div style={s.pricingTierPrice}>{tier.price}</div>
                {tier.features.length > 0 && (
                  <ul style={{ margin: 0, paddingLeft: 16, fontSize: 11, color: "var(--color-text-secondary, #64748b)" }}>
                    {tier.features.slice(0, 4).map((f, j) => (
                      <li key={j}>{f}</li>
                    ))}
                    {tier.features.length > 4 && <li>+{tier.features.length - 4} more</li>}
                  </ul>
                )}
              </div>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

/* -- Loading skeleton -- */

function LoadingSkeleton() {
  return (
    <div>
      <style>{`@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }`}</style>
      <div style={{ ...s.skeleton, width: "40%", height: 24, marginBottom: 8 }} />
      <div style={{ ...s.skeleton, width: "25%", height: 14, marginBottom: 24 }} />
      <div style={s.cardGrid}>
        {[1, 2, 3, 4].map((i) => (
          <div key={i} style={s.card}>
            <div style={{ ...s.skeleton, width: "60%" }} />
            <div style={{ ...s.skeleton, width: "40%", height: 28 }} />
          </div>
        ))}
      </div>
      <div style={s.panel}>
        <div style={{ ...s.skeleton, width: "30%", marginBottom: 14 }} />
        {[1, 2, 3].map((i) => (
          <div key={i} style={{ ...s.skeleton, height: 36, marginBottom: 8 }} />
        ))}
      </div>
      <div style={s.panel}>
        <div style={{ ...s.skeleton, width: "35%", marginBottom: 14 }} />
        <div style={{ ...s.skeleton, height: 200 }} />
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Main App                                                           */
/* ------------------------------------------------------------------ */

export function DashboardApp() {
  const [hostContext, setHostContext] = useState<McpUiHostContext | undefined>();
  const [data, setData] = useState<ResearchResult | null>(null);
  const [expandedCompetitors, setExpandedCompetitors] = useState<Set<string>>(new Set());
  const [appRef, setAppRef] = useState<McpApp | null>(null);

  const { app, error } = useApp({
    appInfo: { name: "Competitor Research — Dashboard", version: "1.0.0" },
    capabilities: {},
    onAppCreated: (app) => {
      app.onerror = console.error;

      app.ontoolresult = async (result: CallToolResult) => {
        const parsed = parseResultData(result);
        if (parsed) setData(parsed);
      };

      app.ontoolinput = async (input: unknown) => {
        console.info("Dashboard received tool input:", input);
      };

      app.onhostcontextchanged = (params) => {
        setHostContext((prev) => ({ ...prev, ...params }));
      };
    },
  });

  useHostStyles(app, app?.getHostContext());

  useEffect(() => {
    if (app) {
      setHostContext(app.getHostContext());
      setAppRef(app);
    }
  }, [app]);

  /* Update model context when user interacts */
  const toggleExpand = useCallback(
    (name: string) => {
      setExpandedCompetitors((prev) => {
        const next = new Set(prev);
        if (next.has(name)) {
          next.delete(name);
        } else {
          next.add(name);
          // Update model context so it knows what the user is looking at
          if (appRef && data) {
            const analysis = data.analyses.find((a) => a.competitor.name === name);
            if (analysis) {
              appRef.updateModelContext({
                context: [
                  {
                    type: "text",
                    text: `User is viewing detailed analysis for competitor: ${name}. Strengths: ${analysis.strengths.join(", ")}. Weaknesses: ${analysis.weaknesses.join(", ")}.`,
                  },
                ],
              }).catch(console.error);
            }
          }
        }
        return next;
      });
    },
    [appRef, data]
  );

  /* Fullscreen toggle */
  const requestFullscreen = useCallback(() => {
    if (appRef) {
      (appRef as unknown as { requestDisplayMode?: (mode: string) => void }).requestDisplayMode?.("fullscreen");
    }
  }, [appRef]);

  /* ---- Render states ---- */

  if (error) {
    return (
      <div style={{ ...s.root, ...s.center }}>
        <p style={{ color: "#ef4444", fontWeight: 600, fontSize: 16 }}>Connection Error</p>
        <p style={{ fontSize: 13 }}>{error.message}</p>
      </div>
    );
  }

  if (!app) {
    return (
      <div style={{ ...s.root, ...s.center }}>
        <p>Connecting…</p>
      </div>
    );
  }

  const insets = hostContext?.safeAreaInsets;

  if (!data) {
    return (
      <div
        style={{
          ...s.root,
          paddingTop: (insets?.top ?? 0) + 20,
          paddingRight: (insets?.right ?? 0) + 20,
          paddingBottom: (insets?.bottom ?? 0) + 40,
          paddingLeft: (insets?.left ?? 0) + 20,
        }}
      >
        <div style={s.header}>
          <div>
            <h1 style={s.headerTitle}>Competitor Research Dashboard</h1>
            <p style={s.headerSub}>Waiting for analysis results…</p>
          </div>
        </div>
        <LoadingSkeleton />
      </div>
    );
  }

  return (
    <div
      style={{
        ...s.root,
        paddingTop: (insets?.top ?? 0) + 20,
        paddingRight: (insets?.right ?? 0) + 20,
        paddingBottom: (insets?.bottom ?? 0) + 40,
        paddingLeft: (insets?.left ?? 0) + 20,
      }}
    >
      <style>{`@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }`}</style>

      {/* Header */}
      <div style={s.header}>
        <div>
          <h1 style={s.headerTitle}>
            {data.brief.company.name} — Competitive Landscape
          </h1>
          <p style={s.headerSub}>
            Generated {formatDate(data.generatedAt)} · {data.brief.company.industry}
          </p>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <span style={s.badge}>{data.analyses.length} competitors</span>
          <button style={s.fullscreenBtn} onClick={requestFullscreen}>
            ⛶ Fullscreen
          </button>
        </div>
      </div>

      {/* Overview Cards */}
      <OverviewCards data={data} />

      {/* Comparison Matrix */}
      <div style={s.panel}>
        <div style={s.panelTitle}>📊 Competitor Comparison</div>
        <ComparisonMatrix analyses={data.analyses} onExpandCompetitor={toggleExpand} />
      </div>

      {/* Strengths & Weaknesses */}
      <div style={s.panel}>
        <div style={s.panelTitle}>💪 Strengths &amp; Weaknesses</div>
        <StrengthsWeaknesses
          analyses={data.analyses}
          expanded={expandedCompetitors}
          onToggle={toggleExpand}
        />
      </div>

      {/* Market Positioning */}
      {data.marketPositioning.length > 0 && (
        <div style={s.panel}>
          <div style={s.panelTitle}>🗺️ Market Positioning</div>
          <PositioningChart data={data.marketPositioning} companyName={data.brief.company.name} />
        </div>
      )}

      {/* Opportunities */}
      {data.opportunities.length > 0 && (
        <div style={s.panel}>
          <div style={s.panelTitle}>💡 Opportunities ({data.opportunities.length})</div>
          <OpportunitiesPanel opportunities={data.opportunities} />
        </div>
      )}

      {/* Pricing Comparison */}
      <PricingComparison analyses={data.analyses} />
    </div>
  );
}
