// =====================================================================
// 京剧剧本可视分析 — Main App
// Coordinates 6 panels through shared state ("linked brushing")
// =====================================================================

const DATA = window.JJ_DATA;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "vermillion",
  "density": "comfortable",
  "showAnnotations": true,
  "networkLayout": "force",
  "dimNonSelected": true
}/*EDITMODE-END*/;

function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // ---- shared state -------------------------------------------------
  const [activeGenres, setActiveGenres] = useState(new Set(["history","family","court"]));
  const [eraRange, setEraRange] = useState([1800, 1950]);
  const [selectedPlay, setSelectedPlay] = useState(null);
  const [selectedRole, setSelectedRole] = useState(null);     // "sheng" or "sheng:老生"
  const [selectedChar, setSelectedChar] = useState(null);     // char id within play, or play:char key cross-play
  const [selectedCharData, setSelectedCharData] = useState(null);
  const [hoverChar, setHoverChar] = useState(null);
  const [themeFilter, setThemeFilter] = useState(null);
  const [hoverGenre, setHoverGenre] = useState(null);

  // ---- derived: visible plays --------------------------------------
  const visiblePlays = useMemo(() => {
    return DATA.plays.filter(p =>
      activeGenres.has(p.genre) && p.era >= eraRange[0] && p.era <= eraRange[1]
    );
  }, [activeGenres, eraRange]);

  // ensure selected play is still visible
  useEffect(() => {
    if (selectedPlay && !visiblePlays.find(p => p.id === selectedPlay)) {
      setSelectedPlay(null);
      setSelectedChar(null);
      setSelectedCharData(null);
    }
  }, [visiblePlays, selectedPlay]);

  const focusPlayData = selectedPlay ? DATA.plays.find(p => p.id === selectedPlay) : null;

  function toggleGenre(g) {
    const n = new Set(activeGenres);
    if (n.has(g)) n.delete(g); else n.add(g);
    if (n.size === 0) { n.add(g); return; } // never empty
    setActiveGenres(n);
  }

  function handleSelectPlay(id) {
    if (selectedPlay === id) {
      setSelectedPlay(null);
      setSelectedChar(null);
      setSelectedCharData(null);
    } else {
      setSelectedPlay(id);
      setSelectedChar(null);
      setSelectedCharData(null);
    }
  }

  function handleSelectChar(charKey, nodeData) {
    if (!charKey) {
      setSelectedChar(null);
      setSelectedCharData(null);
      return;
    }
    setSelectedChar(charKey);
    setSelectedCharData(nodeData);
  }

  // when hover from outside, set hoverChar
  // ------------------------------------------------------------------

  return (
    <div className="stage">
      <Header
        activeGenres={activeGenres}
        onToggleGenre={toggleGenre}
        eraRange={eraRange}
        onEraChange={setEraRange}
        selectedPlay={focusPlayData}
      />
      <div className="grid">
        {/* LEFT COLUMN: play list (top) + sunburst (bottom) ----------- */}
        <div className="col col-left">
          <PlayRail
            plays={DATA.plays}
            selectedPlay={selectedPlay}
            onSelect={handleSelectPlay}
            activeGenres={activeGenres}
            eraRange={eraRange}
            hoverGenre={hoverGenre}
            onHoverGenre={setHoverGenre}
          />
          <RoleSunburst
            plays={visiblePlays}
            focusPlay={selectedPlay}
            selectedRole={selectedRole}
            onSelectRole={setSelectedRole}
            hoverChar={hoverChar}
            characterIndex={DATA.characterIndex}
          />
        </div>

        {/* CENTER COLUMN: network (top) + narrative (bottom) ---------- */}
        <div className="col col-center">
          <NetworkView
            plays={visiblePlays}
            focusPlay={selectedPlay}
            selectedRole={selectedRole}
            selectedChar={selectedChar}
            onSelectChar={handleSelectChar}
            themeFilter={themeFilter}
            hoverChar={hoverChar}
            onHoverChar={setHoverChar}
            layoutKind={tweaks.networkLayout}
          />
          <NarrativeArc
            plays={visiblePlays}
            focusPlay={selectedPlay}
            selectedChar={selectedChar}
            selectedCharData={selectedCharData}
            hoverChar={hoverChar}
            themeFilter={themeFilter}
          />
        </div>

        {/* RIGHT COLUMN: themes (top) + detail (bottom) -------------- */}
        <div className="col col-right">
          <ThemePanel
            plays={visiblePlays}
            allPlays={DATA.plays}
            allThemes={DATA.THEMES}
            focusPlay={selectedPlay}
            themeFilter={themeFilter}
            onSetThemeFilter={setThemeFilter}
            selectedRole={selectedRole && selectedRole.includes(":") ? selectedRole.split(":")[0] : selectedRole}
            onSelectRole={setSelectedRole}
            roleThemeMatrix={DATA.roleThemeMatrix}
          />
          <DetailPanel
            selectedCharData={selectedCharData}
            focusPlayData={focusPlayData}
            hoverChar={hoverChar}
            allThemes={DATA.THEMES}
            themeFilter={themeFilter}
            onSetThemeFilter={setThemeFilter}
            plays={visiblePlays}
            eraRange={eraRange}
            activeGenres={activeGenres}
          />
        </div>
      </div>

      {/* FOOTER ----------------------------------------------------- */}
      <Footer
        selectedPlay={focusPlayData}
        selectedCharData={selectedCharData}
        themeFilter={themeFilter}
        allThemes={DATA.THEMES}
        visibleCount={visiblePlays.length}
      />

      {/* Tweaks panel (controlled by toolbar toggle) */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="视觉风格">
          <TweakRadio
            label="主色"
            value={tweaks.palette}
            options={[{value:"vermillion",label:"朱红"},{value:"ink",label:"墨蓝"},{value:"gold",label:"鎏金"}]}
            onChange={v => setTweak("palette", v)}
          />
          <TweakRadio
            label="密度"
            value={tweaks.density}
            options={[{value:"compact",label:"紧凑"},{value:"comfortable",label:"舒展"}]}
            onChange={v => setTweak("density", v)}
          />
          <TweakToggle label="说明性注释" value={tweaks.showAnnotations} onChange={v => setTweak("showAnnotations", v)} />
          <TweakToggle label="弱化未选中" value={tweaks.dimNonSelected} onChange={v => setTweak("dimNonSelected", v)} />
        </TweakSection>
        <TweakSection label="图表">
          <TweakRadio
            label="网络布局"
            value={tweaks.networkLayout}
            options={[{value:"force",label:"力导"},{value:"circular",label:"环形"},{value:"hierarchical",label:"分层"}]}
            onChange={v => setTweak("networkLayout", v)}
          />
        </TweakSection>
      </TweaksPanel>

      {/* apply tweaks side-effects */}
      <TweakApply tweaks={tweaks} />
    </div>
  );
}

function Footer({ selectedPlay, selectedCharData, themeFilter, allThemes, visibleCount }) {
  const themeName = themeFilter ? allThemes.find(t => t.id === themeFilter)?.name : null;
  return (
    <div className="footer">
      <div className="footer-l">
        <div><span className="dot"/>LINKED&nbsp;BRUSHING&nbsp;ACTIVE</div>
        <div>剧目 <span className="acc">{visibleCount}</span></div>
        <div>聚焦 <span className="acc">{selectedPlay ? selectedPlay.title : "全部"}</span></div>
        <div>人物 <span className="acc">{selectedCharData ? selectedCharData.name : "—"}</span></div>
        <div>主题 <span className="acc">{themeName || "—"}</span></div>
      </div>
      <div className="footer-r">
        <div>CHINAVIS · 2026</div>
        <div>京剧剧本可视分析系统&nbsp;v0.1</div>
      </div>
    </div>
  );
}

// Apply palette/density tweaks at the root
function TweakApply({ tweaks }) {
  useEffect(() => {
    const root = document.documentElement;
    if (tweaks.palette === "ink") {
      root.style.setProperty("--vermillion", "#3a5a6e");
      root.style.setProperty("--vermillion-2", "#5078a0");
      root.style.setProperty("--gold", "#b8c8d8");
      root.style.setProperty("--gold-dim", "#5a7080");
    } else if (tweaks.palette === "gold") {
      root.style.setProperty("--vermillion", "#8a6a2e");
      root.style.setProperty("--vermillion-2", "#d4a24c");
      root.style.setProperty("--gold", "#e8c468");
      root.style.setProperty("--gold-dim", "#8a6a2e");
    } else {
      root.style.setProperty("--vermillion", "#c8341c");
      root.style.setProperty("--vermillion-2", "#e04a2a");
      root.style.setProperty("--gold", "#d4a24c");
      root.style.setProperty("--gold-dim", "#8a6a2e");
    }
  }, [tweaks.palette]);

  useEffect(() => {
    document.body.style.fontSize = tweaks.density === "compact" ? "12px" : "13px";
  }, [tweaks.density]);

  return null;
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
