// Main React app for Russian Slovo frequency reader.
const { useState, useMemo, useCallback, useRef, useEffect } = React;
const { cleanTranscript, analyze } = window.RuAnalyzer;

const TWEAK_DEFAULTS = {
  filterStopWords: true,
  minLen: 2,
  accent: "burgundy",
  density: "comfortable",
  showRank: true,
};

const ACCENTS = {
  burgundy: { value: "oklch(0.5 0.13 25)",  soft: "oklch(0.92 0.04 30)" },
  ink:      { value: "oklch(0.35 0.05 250)", soft: "oklch(0.92 0.025 250)" },
  forest:   { value: "oklch(0.45 0.08 150)", soft: "oklch(0.92 0.03 150)" },
  ochre:    { value: "oklch(0.55 0.13 75)",  soft: "oklch(0.93 0.05 80)" },
};

const DENSITIES = ["cozy", "comfortable", "compact"];

function HeaderMark() {
  return (
    <svg width="34" height="34" viewBox="0 0 34 34" aria-hidden style={{ display: "block" }}>
      <rect x="1" y="1" width="32" height="32" rx="3" stroke="currentColor" fill="none" strokeWidth="1.2" />
      <text x="17" y="23" textAnchor="middle"
        fontFamily="'PT Serif', serif" fontSize="20" fontWeight="700"
        fill="currentColor">Я</text>
    </svg>
  );
}

function TweaksToggleButton({ onClick }) {
  return (
    <button className="tweaks-toggle" onClick={onClick} aria-label="Open tweaks">
      <svg width="14" height="14" viewBox="0 0 24 24" aria-hidden>
        <path fill="currentColor" d="M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.5.5 0 0 0-.59-.22l-2.39.96a7 7 0 0 0-1.62-.94l-.36-2.54A.49.49 0 0 0 14 2h-4a.49.49 0 0 0-.49.42l-.36 2.54c-.59.24-1.13.55-1.62.94l-2.39-.96a.5.5 0 0 0-.59.22L2.63 8.48a.49.49 0 0 0 .12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94L2.75 14.13a.49.49 0 0 0-.12.61l1.92 3.32c.13.22.39.31.59.22l2.39-.96c.49.39 1.03.7 1.62.94l.36 2.54c.04.24.25.42.49.42h4a.49.49 0 0 0 .49-.42l.36-2.54c.59-.24 1.13-.55 1.62-.94l2.39.96c.2.09.46 0 .59-.22l1.92-3.32a.49.49 0 0 0-.12-.61l-2.03-1.58zM12 15.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7z"/>
      </svg>
      <span>Tweaks</span>
    </button>
  );
}

function TranscriptDisplay({ tokens, hoveredGroup }) {
  return (
    <div className="transcript-display">
      {tokens.map((tok, i) => {
        if (!tok.isWord) {
          return (
            <span key={i} className="t-gap">
              {tok.text}
            </span>
          );
        }
        let cls = "t-word";
        if (hoveredGroup) {
          if (hoveredGroup.kind === "root" && tok.stem === hoveredGroup.id) cls += " hl";
          else if (hoveredGroup.kind === "variant" && tok.lower === hoveredGroup.form) cls += " hl";
        }
        return (
          <span key={i} className={cls} data-stem={tok.stem} data-form={tok.lower}>
            {tok.text}
          </span>
        );
      })}
    </div>
  );
}

function App() {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [tweaksOpen, setTweaksOpen] = useState(false);

  const [raw, setRaw] = useState("");
  const [analysis, setAnalysis] = useState(null);
  const [hover, setHover] = useState(null);
  const [locked, setLocked] = useState(null);
  const [editMode, setEditMode] = useState(true);
  const taRef = useRef(null);

  const toggleLock = useCallback((target) => {
    setLocked((prev) => {
      if (!prev) return target;
      if (prev.kind !== target.kind) return target;
      if (prev.kind === "root" && prev.id === target.id) return null;
      if (prev.kind === "variant" && prev.form === target.form) return null;
      return target;
    });
  }, []);

  const effectiveHover = hover || locked;

  // Re-run analysis when filter tweaks change (only if we already have one).
  useEffect(() => {
    if (!analysis) return;
    const a = analyze(raw, { useStopWords: tweaks.filterStopWords, minLen: tweaks.minLen });
    setAnalysis(a);
    setLocked(null);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tweaks.filterStopWords, tweaks.minLen]);

  // Accent → CSS vars.
  useEffect(() => {
    const a = ACCENTS[tweaks.accent] || ACCENTS.burgundy;
    document.documentElement.style.setProperty("--accent", a.value);
    document.documentElement.style.setProperty("--accent-soft", a.soft);
  }, [tweaks.accent]);

  // Density / showRank → data attrs (CSS handles the rest).
  useEffect(() => {
    document.documentElement.dataset.density = tweaks.density || "comfortable";
  }, [tweaks.density]);
  useEffect(() => {
    document.documentElement.dataset.showRank = tweaks.showRank ? "1" : "0";
  }, [tweaks.showRank]);

  const onPaste = useCallback((e) => {
    e.preventDefault();
    const text = e.clipboardData.getData("text");
    const cleaned = cleanTranscript(text);
    setRaw(cleaned);
    setAnalysis(null);
    setLocked(null);
  }, []);

  const onChange = useCallback((e) => {
    setRaw(e.target.value);
    setAnalysis(null);
    setLocked(null);
  }, []);

  const doAnalyze = () => {
    if (!raw.trim()) return;
    const a = analyze(raw, { useStopWords: tweaks.filterStopWords, minLen: tweaks.minLen });
    setAnalysis(a);
    setLocked(null);
    setEditMode(false);
  };

  const doFormat = () => {
    setRaw((r) => cleanTranscript(r));
    setAnalysis(null);
    setLocked(null);
  };

  const doClear = () => {
    setRaw("");
    setAnalysis(null);
    setLocked(null);
    setEditMode(true);
    setTimeout(() => taRef.current?.focus(), 0);
  };

  const doSample = () => {
    setRaw(window.RU_SAMPLE);
    setAnalysis(null);
    setLocked(null);
    setEditMode(true);
  };

  const doEdit = () => {
    setEditMode(true);
    setAnalysis(null);
    setLocked(null);
    setTimeout(() => taRef.current?.focus(), 0);
  };

  const wordCount = useMemo(() => {
    if (!raw) return 0;
    const m = raw.match(/[Ѐ-ӿ]+/g);
    return m ? m.length : 0;
  }, [raw]);

  return (
    <div className="page">
      <header className="masthead">
        <div className="brand">
          <span className="brand-mark"><HeaderMark /></span>
          <div className="brand-text">
            <h1>Russian Slovo</h1>
            <span className="brand-sub">frequency reader · for language learners</span>
          </div>
        </div>
        <div className="masthead-meta">
          <span className="meta-stat">
            <span className="meta-num">{wordCount.toLocaleString()}</span>
            <span className="meta-lab">words pasted</span>
          </span>
          {analysis && (
            <>
              <span className="meta-stat">
                <span className="meta-num">{analysis.groups.length.toLocaleString()}</span>
                <span className="meta-lab">root forms</span>
              </span>
              <span className="meta-stat">
                <span className="meta-num">{analysis.groups.reduce((a,b)=>a+b.total,0).toLocaleString()}</span>
                <span className="meta-lab">counted</span>
              </span>
            </>
          )}
        </div>
      </header>

      <main className="main">
        <section className="transcript-card">
          <div className="card-tab">
            <span className="tab-dot" /> transcript
            {!editMode && analysis && <span className="tab-aux">— hover a word below to highlight</span>}
          </div>

          {editMode ? (
            <textarea
              ref={taRef}
              className="transcript-input"
              value={raw}
              onChange={onChange}
              onPaste={onPaste}
              spellCheck={false}
              placeholder={"Paste your podcast transcript here.\n\nTimestamps, speaker labels, and stage directions will be cleaned automatically.\n\nThen click Analyze ↘"}
            />
          ) : (
            <TranscriptDisplay
              tokens={analysis.tokens}
              hoveredGroup={effectiveHover}
            />
          )}

          <div className="card-actions">
            <div className="actions-left">
              {editMode ? (
                <>
                  <button className="btn ghost" onClick={doSample} disabled={!!raw}>
                    Try sample
                  </button>
                  <button className="btn ghost" onClick={doFormat} disabled={!raw}>
                    Re-format
                  </button>
                  <button className="btn ghost danger" onClick={doClear} disabled={!raw}>
                    Clear
                  </button>
                </>
              ) : (
                <button className="btn ghost" onClick={doEdit}>
                  ← Edit transcript
                </button>
              )}
            </div>
            <div className="actions-right">
              {editMode && (
                <button
                  className="btn primary"
                  onClick={doAnalyze}
                  disabled={!raw.trim()}
                >
                  Analyze
                  <span className="btn-arrow">↓</span>
                </button>
              )}
            </div>
          </div>
        </section>

        <section className="list-section">
          <div className="list-head">
            <h2>Word Frequency</h2>
            <div className="list-head-rule" />
          </div>
          <window.WordList
            groups={analysis ? analysis.groups : []}
            hover={hover}
            locked={locked}
            onHover={setHover}
            onLock={toggleLock}
          />
        </section>
      </main>

      <footer className="foot">
        <span>Stems via Porter (Snowball) algorithm for Russian. Common stop-words and 1-letter tokens filtered.</span>
      </footer>

      {!tweaksOpen && <TweaksToggleButton onClick={() => setTweaksOpen(true)} />}

      <window.TweaksPanel open={tweaksOpen} onClose={() => setTweaksOpen(false)} title="Tweaks">
        <window.TweakSection label="Filtering">
          <window.TweakToggle
            label="Filter common stop-words"
            value={tweaks.filterStopWords}
            onChange={(v) => setTweak("filterStopWords", v)}
          />
          <window.TweakSlider
            label="Minimum word length"
            min={1} max={5} step={1}
            value={tweaks.minLen}
            onChange={(v) => setTweak("minLen", v)}
          />
        </window.TweakSection>
        <window.TweakSection label="Display">
          <window.TweakColor
            label="Highlight accent"
            options={Object.keys(ACCENTS).map((k) => ACCENTS[k].value)}
            value={ACCENTS[tweaks.accent].value}
            onChange={(v) => {
              const key = Object.keys(ACCENTS).find((k) => ACCENTS[k].value === v);
              if (key) setTweak("accent", key);
            }}
          />
          <window.TweakSelect
            label="Density"
            options={DENSITIES}
            value={tweaks.density}
            onChange={(v) => setTweak("density", v)}
          />
          <window.TweakToggle
            label="Show rank numbers"
            value={tweaks.showRank}
            onChange={(v) => setTweak("showRank", v)}
          />
        </window.TweakSection>
      </window.TweaksPanel>
    </div>
  );
}

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