/* mapscreen.jsx — Inspector, ScreensGrid, ReportView, MapScreen composition */

function lineage(nodes, edges, targetId) {
  // BFS from splash to target, return array of node ids (the path)
  const adj = {};
  edges.forEach(([a, b]) => { (adj[a] = adj[a] || []).push(b); });
  const root = nodes[0].id;
  const q = [[root]], seen = new Set([root]);
  while (q.length) {
    const p = q.shift(); const last = p[p.length - 1];
    if (last === targetId) return p;
    (adj[last] || []).forEach(n => { if (!seen.has(n)) { seen.add(n); q.push([...p, n]); } });
  }
  return [targetId];
}

function Inspector({ data, id, onSelect, onClose }) {
  const { nodes, edges, journeys } = data;
  const nodeMap = Object.fromEntries(nodes.map(n => [n.id, n]));
  const n = nodeMap[id];
  if (!n) return null;
  const j = journeys.find(x => x.id === n.journey);
  const outs = edges.filter(([a]) => a === id).map(([, b]) => nodeMap[b]).filter(Boolean);
  const ins = edges.filter(([, b]) => b === id).map(([a]) => nodeMap[a]).filter(Boolean);
  const trail = lineage(nodes, edges, id).map(x => nodeMap[x]);

  const Section = ({ label, children }) => (
    <div style={{ padding: "18px 22px", borderTop: "1px solid var(--line)" }}>
      <div className="eyebrow" style={{ marginBottom: 12 }}>{label}</div>
      {children}
    </div>
  );
  const ConnRow = ({ node, dir }) => (
    <div onClick={() => onSelect(node.id)} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 10px", borderRadius: 7, cursor: "pointer", background: "var(--panel-2)" }}
      onMouseEnter={e => e.currentTarget.style.background = "var(--hover)"} onMouseLeave={e => e.currentTarget.style.background = "var(--panel-2)"}>
      <span style={{ color: "var(--t-faint)", transform: dir === "in" ? "rotate(180deg)" : "none" }}><Icon name="arrow" s={13} /></span>
      <div style={{ width: 14, height: 28, borderRadius: 3, overflow: "hidden", flex: "none" }}><Phone arch={node.arch} accent={node.accent} shot={node.shot} w={14} /></div>
      <span style={{ fontSize: 13, color: "var(--t)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{node.name}</span>
    </div>
  );

  return (
    <div className="fade-in" style={{ width: 372, flex: "none", borderLeft: "1px solid var(--line)", background: "var(--bg-2)", display: "flex", flexDirection: "column", overflowY: "auto" }}>
      <div style={{ padding: "16px 22px", display: "flex", alignItems: "center", justifyContent: "space-between", position: "sticky", top: 0, background: "var(--bg-2)", zIndex: 2 }}>
        <span className="eyebrow" style={{ color: "var(--acc-hi)" }}>SCREEN · {String(nodes.indexOf(n) + 1).padStart(2, "0")}</span>
        <div className="icon-btn" onClick={onClose}><Icon name="x" s={14} /></div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 16, padding: "0 22px 18px" }}>
        {/* 截图按侧边栏内宽（372 − 22×2）满宽显示，更看得清 */}
        <div style={{ flex: "none", alignSelf: "center" }}><Phone arch={n.arch} accent={n.accent} shot={n.shot} w={328} active /></div>
        <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
          <span className="pill" style={{ alignSelf: "flex-start" }}>{j ? j.cat : "—"}</span>
          <div style={{ color: "var(--t-hi)", fontWeight: 600, fontSize: 18, lineHeight: 1.25 }}>{n.name}</div>
          <div style={{ display: "flex", gap: 14 }}>
            <div><div className="num" style={{ color: "var(--t-hi)", fontSize: 15 }}>{n.el}</div><div className="eyebrow" style={{ fontSize: 9 }}>元素</div></div>
            <div><div className="num" style={{ color: "var(--t-hi)", fontSize: 15 }}>{outs.length}</div><div className="eyebrow" style={{ fontSize: 9 }}>出边</div></div>
            <div><div className="num" style={{ color: "var(--t-hi)", fontSize: 15 }}>{ins.length}</div><div className="eyebrow" style={{ fontSize: 9 }}>入边</div></div>
          </div>
        </div>
      </div>

      <Section label="AI 页面作用">
        <div style={{ display: "flex", gap: 8, alignItems: "flex-start" }}>
          <span style={{ color: "var(--acc)", marginTop: 2, flex: "none" }}><Icon name="sparkle" s={14} /></span>
          <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--t)" }}>{n.role}</div>
        </div>
      </Section>

      <Section label="到达路径">
        <div style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: "6px 4px" }}>
          {trail.map((t, i) => (
            <React.Fragment key={t.id}>
              {i > 0 && <span style={{ color: "var(--t-faint)" }}><Icon name="chev" s={11} /></span>}
              <span onClick={() => onSelect(t.id)} style={{ fontFamily: "var(--mono)", fontSize: 11, padding: "3px 7px", borderRadius: 5, cursor: "pointer", whiteSpace: "nowrap",
                background: t.id === id ? "var(--acc-soft)" : "var(--panel-2)", color: t.id === id ? "var(--acc-hi)" : "var(--t-dim)", border: "1px solid var(--line)" }}>{t.name}</span>
            </React.Fragment>
          ))}
        </div>
      </Section>

      {outs.length > 0 && <Section label={`跳转至 · ${outs.length}`}><div style={{ display: "flex", flexDirection: "column", gap: 6 }}>{outs.map(o => <ConnRow key={o.id} node={o} dir="out" />)}</div></Section>}
      {ins.length > 0 && <Section label={`来源 · ${ins.length}`}><div style={{ display: "flex", flexDirection: "column", gap: 6 }}>{ins.map(o => <ConnRow key={o.id} node={o} dir="in" />)}</div></Section>}
    </div>
  );
}

function ScreensGrid({ data, selected, onSelect }) {
  const { nodes, journeys } = data;
  const jmap = Object.fromEntries(journeys.map(j => [j.id, j]));
  return (
    <div style={{ position: "absolute", inset: 0, overflowY: "auto", padding: "26px 30px" }}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 16, maxWidth: 1400, margin: "0 auto" }}>
        {nodes.map((n, i) => {
          const j = jmap[n.journey];
          const sel = n.id === selected;
          return (
            <div key={n.id} onClick={() => onSelect(n.id)} className="card" style={{ padding: 14, display: "flex", gap: 14, cursor: "pointer",
              borderColor: sel ? "var(--acc-dim)" : "var(--line)", background: sel ? "var(--panel-2)" : "var(--panel)", transition: "border-color .15s" }}
              onMouseEnter={e => { if (!sel) e.currentTarget.style.borderColor = "var(--line-2)"; }}
              onMouseLeave={e => { if (!sel) e.currentTarget.style.borderColor = "var(--line)"; }}>
              <Phone arch={n.arch} accent={n.accent} shot={n.shot} w={62} active={sel} />
              <div style={{ display: "flex", flexDirection: "column", gap: 7, minWidth: 0, flex: 1 }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                  <span className="pill">{j ? j.cat : "—"}</span>
                  <span className="num" style={{ fontSize: 10.5, color: "var(--t-faint)" }}>{String(i + 1).padStart(2, "0")}</span>
                </div>
                <div style={{ color: "var(--t-hi)", fontWeight: 600, fontSize: 14 }}>{n.name}</div>
                <div style={{ color: "var(--t-dim)", fontSize: 12, lineHeight: 1.5, display: "-webkit-box", WebkitLineClamp: 3, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{n.role}</div>
                <div className="num" style={{ marginTop: "auto", fontSize: 10.5, color: "var(--t-faint)" }}>{n.el} 元素</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ReportView({ data }) {
  const { app, stats, journeys, nodes } = data;
  const byCat = {};
  journeys.forEach(j => { byCat[j.cat] = (byCat[j.cat] || 0) + 1; });
  const Stat = ({ k, v, sub }) => (
    <div className="card" style={{ padding: "18px 20px", flex: 1 }}>
      <div className="num" style={{ fontSize: 30, color: "var(--t-hi)", fontWeight: 600 }}>{v}</div>
      <div className="eyebrow" style={{ marginTop: 4 }}>{k}</div>
      {sub && <div style={{ fontSize: 12, color: "var(--t-dim)", marginTop: 6 }}>{sub}</div>}
    </div>
  );
  return (
    <div style={{ position: "absolute", inset: 0, overflowY: "auto", padding: "32px 40px" }}>
      <div style={{ maxWidth: 920, margin: "0 auto", display: "flex", flexDirection: "column", gap: 22 }}>
        <div>
          <div className="eyebrow">分析报告</div>
          <h1 style={{ margin: "8px 0 0", fontSize: 28, color: "var(--t-hi)", fontWeight: 600 }}>{app.name} · 产品全貌</h1>
        </div>
        <div style={{ display: "flex", gap: 14 }}>
          <Stat k="屏数 SCREENS" v={stats.screens} sub="已截图并分析" />
          <Stat k="路径 PATHS" v={stats.paths} sub="用户旅程" />
          <Stat k="元素 ELEMENTS" v={stats.elements} sub="可交互控件" />
          <Stat k="变现入口" v="4" sub="订阅 / 商店 / 体力" />
        </div>
        <div className="card" style={{ padding: "22px 24px" }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>AI 定位概述</div>
          <div style={{ fontSize: 15, lineHeight: 1.7, color: "var(--t)" }}>{app.positioning}</div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginTop: 16 }}>
            {app.tags.map(t => <span key={t} className="pill" style={{ height: 24, fontSize: 11 }}>{t}</span>)}
          </div>
        </div>
        <div className="card" style={{ padding: "22px 24px" }}>
          <div className="eyebrow" style={{ marginBottom: 16 }}>关键产品机制</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {app.hooks.map(h => (
              <div key={h.k} style={{ display: "flex", gap: 16, alignItems: "baseline" }}>
                <div style={{ width: 80, flex: "none", color: "var(--acc-hi)", fontFamily: "var(--mono)", fontSize: 12 }}>{h.k}</div>
                <div style={{ fontSize: 14, color: "var(--t)", lineHeight: 1.6 }}>{h.v}</div>
              </div>
            ))}
          </div>
        </div>
        <div className="card" style={{ padding: "22px 24px" }}>
          <div className="eyebrow" style={{ marginBottom: 16 }}>旅程分类分布</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {Object.entries(byCat).sort((a, b) => b[1] - a[1]).map(([cat, n]) => (
              <div key={cat} style={{ display: "flex", alignItems: "center", gap: 14 }}>
                <span className="pill" style={{ width: 92, justifyContent: "center" }}>{cat}</span>
                <div style={{ flex: 1, height: 8, borderRadius: 4, background: "var(--raised)", overflow: "hidden" }}>
                  <div style={{ width: `${(n / journeys.length) * 100}%`, height: "100%", background: "linear-gradient(90deg, var(--acc-dim), var(--acc))" }} />
                </div>
                <span className="num" style={{ width: 24, textAlign: "right", color: "var(--t-dim)", fontSize: 12 }}>{n}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function MapScreen({ data, tab, selected, onSelect, tw }) {
  const [activeJourney, setActiveJourney] = useState(null);
  const journeyNodeIds = useMemo(() => {
    if (!activeJourney) return null;
    return new Set(data.nodes.filter(n => n.journey === activeJourney).map(n => n.id));
  }, [activeJourney, data]);

  if (tab === "report") return <ReportView data={data} />;

  const railPos = (tw && tw.layout) || "rail-left";
  const rail = tab === "map" && railPos !== "no-rail" && (
    <JourneyRail journeys={data.journeys} stats={data.stats} activeJourney={activeJourney}
      onPick={(id) => setActiveJourney(activeJourney === id ? null : id)} />
  );
  const canvas = (
    <div style={{ flex: 1, position: "relative", minWidth: 0 }}>
      {tab === "map"
        ? <GraphCanvas data={data} nodes={data.nodes} edges={data.edges} selected={selected} onSelect={onSelect}
            tw={tw} dimUnselected={tw.focusDim} visible={journeyNodeIds} onResetJourney={() => setActiveJourney(null)} />
        : <ScreensGrid data={data} selected={selected} onSelect={onSelect} />}
    </div>
  );
  const inspector = selected && <Inspector data={data} id={selected} onSelect={onSelect} onClose={() => onSelect(null)} />;

  return (
    <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
      {railPos === "rail-left" && rail}
      {canvas}
      {inspector}
      {railPos === "rail-right" && rail}
    </div>
  );
}

Object.assign(window, { Inspector, ScreensGrid, ReportView, MapScreen, lineage });
