// app.jsx — main application
const { useState, useEffect, useRef, useCallback } = React;

const HISTORY_KEY = "bp_history_v1";
const THEME_KEY = "bp_theme";

function loadHistory() {
  try { return JSON.parse(localStorage.getItem(HISTORY_KEY) || "[]"); }
  catch (e) { return []; }
}
function saveHistory(h) {
  try { localStorage.setItem(HISTORY_KEY, JSON.stringify(h.slice(0, 50))); } catch (e) {}
}

// ── Model chips (target + re-optimize) ───────────────────────────────────────
function ModelChips({ value, onPick, disabled, t }) {
  return (
    <div className="chips">
      {window.MODELS.map((m) => (
        <button key={m.id} type="button"
          className={"chip" + (value === m.id ? " chip--on" : "")}
          disabled={disabled}
          onClick={() => onPick(m.id)}>
          <window.ModelDot color={m.color} />
          <span>{m.id === "general" ? t.general : m.name}</span>
        </button>
      ))}
    </div>
  );
}

// ── Mode selector ────────────────────────────────────────────────────────────
function ModeSelector({ value, onPick, t }) {
  const labels = { text: t.modeText, image: t.modeImage, video: t.modeVideo, code: t.modeCode };
  const hints = { text: t.modeTextHint, image: t.modeImageHint, video: t.modeVideoHint, code: t.modeCodeHint };
  return (
    <div className="modes" role="tablist">
      {window.MODES.map((m) => (
        <button key={m.id} type="button" title={hints[m.id]}
          className={"mode" + (value === m.id ? " mode--on" : "")}
          onClick={() => onPick(m.id)}>
          <window.Icon name={m.icon} size={16} />
          <span>{labels[m.id]}</span>
        </button>
      ))}
    </div>
  );
}

// ── Composer ─────────────────────────────────────────────────────────────────
function Composer({ t, prompt, setPrompt, model, setModel, mode, setMode, loading, onSubmit }) {
  const taRef = useRef(null);
  useEffect(() => {
    const ta = taRef.current; if (!ta) return;
    ta.style.height = "auto";
    ta.style.height = Math.min(280, Math.max(96, ta.scrollHeight)) + "px";
  }, [prompt]);

  const onKey = (e) => {
    if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { e.preventDefault(); onSubmit(); }
  };

  return (
    <div className="composer-wrap">
      <div className="composer">
        <textarea ref={taRef} className="composer__ta" value={prompt}
          onChange={(e) => setPrompt(e.target.value)} onKeyDown={onKey}
          placeholder={t.placeholder} spellCheck={false} />
        <div className="composer__bar">
          <ModeSelector value={mode} onPick={setMode} t={t} />
          <div className="composer__right">
            <button className="btn-go" disabled={loading || !prompt.trim()} onClick={onSubmit}>
              {loading ? <window.Spinner size={15} /> : <window.Icon name="send" size={16} />}
              <span>{loading ? t.optimizing : t.optimize}</span>
            </button>
          </div>
        </div>
      </div>
      <div className="target">
        <span className="target__lbl">{t.target}</span>
        <ModelChips value={model} onPick={setModel} disabled={loading} t={t} />
      </div>
    </div>
  );
}

// ── Result card ──────────────────────────────────────────────────────────────
function ResultCard({ t, loading, result, model, mode, onCopy, copied, onRegen, onReoptimize }) {
  const modelObj = window.MODELS.find((m) => m.id === model) || window.MODELS[0];
  const modeLabel = { text: t.modeText, image: t.modeImage, video: t.modeVideo, code: t.modeCode }[mode];
  return (
    <div className="result">
      <div className="result__head">
        <div className="result__title">
          <window.Icon name="spark" size={15} style={{ color: "var(--accent)" }} />
          <span>{t.resultTitle}</span>
          <span className="result__badge">
            {modeLabel}
            <span style={{ opacity: .5 }}>·</span>
            <window.ModelDot color={modelObj.color} size={7} />
            {modelObj.id === "general" ? t.general : modelObj.name}
          </span>
        </div>
        <div className="result__actions">
          <button className="ghost-btn" onClick={onRegen} disabled={loading} title={t.regenerate}>
            <window.Icon name="regen" size={15} /><span>{t.regenerate}</span>
          </button>
          <button className={"copy-btn" + (copied ? " copy-btn--ok" : "")} onClick={onCopy} disabled={loading || !result}>
            <window.Icon name={copied ? "check" : "copy"} size={15} />
            <span>{copied ? t.copied : t.copy}</span>
          </button>
        </div>
      </div>
      {loading ? (
        <div className="result__body skeleton">
          <span /><span /><span /><span style={{ width: "62%" }} />
        </div>
      ) : (
        <pre className="result__body">{result}</pre>
      )}
      {!loading && result ? (
        <div className="reopt">
          <span className="reopt__lbl">{t.reoptimize}</span>
          <ModelChips value={model} onPick={onReoptimize} disabled={loading} t={t} />
        </div>
      ) : null}
    </div>
  );
}

// ── History drawer ───────────────────────────────────────────────────────────
function HistoryDrawer({ open, onClose, items, onPick, onClear, t }) {
  return (
    <>
      <div className={"drawer-scrim" + (open ? " on" : "")} onClick={onClose} />
      <aside className={"drawer" + (open ? " on" : "")}>
        <div className="drawer__head">
          <div className="drawer__title"><window.Icon name="history" size={16} /><span>{t.history}</span></div>
          <div className="drawer__head-r">
            {items.length > 0 && (
              <button className="ghost-btn sm" onClick={onClear}><window.Icon name="trash" size={14} /><span>{t.clear}</span></button>
            )}
            <button className="icon-btn" onClick={onClose} aria-label="close"><window.Icon name="close" size={16} /></button>
          </div>
        </div>
        <div className="drawer__list">
          {items.length === 0 ? (
            <p className="drawer__empty">{t.historyEmpty}</p>
          ) : items.map((it) => {
            const mo = window.MODELS.find((m) => m.id === it.model) || window.MODELS[0];
            const ml = { text: t.modeText, image: t.modeImage, video: t.modeVideo, code: t.modeCode }[it.mode];
            return (
              <button key={it.id} className="hist" onClick={() => onPick(it)}>
                <div className="hist__meta">
                  <window.ModelDot color={mo.color} size={7} />
                  <span>{mo.id === "general" ? t.general : mo.name}</span>
                  <span className="hist__dot">·</span>
                  <span>{ml}</span>
                </div>
                <div className="hist__raw">{it.raw}</div>
              </button>
            );
          })}
        </div>
      </aside>
    </>
  );
}

// ── Language menu ────────────────────────────────────────────────────────────
function LangMenu({ lang, setLang, t }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  return (
    <div className="langmenu" ref={ref}>
      <button className="icon-btn" onClick={() => setOpen((o) => !o)} title={t.selectLang}>
        <window.Icon name="globe" size={17} />
        <span className="langmenu__code">{lang.toUpperCase()}</span>
      </button>
      {open && (
        <div className="langmenu__pop">
          {window.LANGS.map((l) => (
            <button key={l} className={"langmenu__item" + (l === lang ? " on" : "")}
              onClick={() => { setLang(l); setOpen(false); }}>
              {window.I18N[l].label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ── App ──────────────────────────────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#f43f5e",
  "font": "Schibsted Grotesk",
  "density": "regular"
}/*EDITMODE-END*/;

function App() {
  const [tw, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [lang, setLangState] = useState(window.detectLang());
  const [theme, setTheme] = useState(() => {
    try { return localStorage.getItem(THEME_KEY) || "light"; } catch (e) { return "light"; }
  });
  const [prompt, setPrompt] = useState("");
  const [model, setModel] = useState("general");
  const [mode, setMode] = useState("text");
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState("");
  const [error, setError] = useState("");
  const [copied, setCopied] = useState(false);
  const [history, setHistory] = useState(loadHistory);
  const [drawer, setDrawer] = useState(false);
  // the model/mode that produced the current visible result
  const [resModel, setResModel] = useState("general");
  const [resMode, setResMode] = useState("text");

  const t = window.I18N[lang] || window.I18N.en;

  const setLang = (l) => { setLangState(l); try { localStorage.setItem("bp_lang", l); } catch (e) {} };
  const toggleTheme = () => {
    setTheme((p) => { const n = p === "dark" ? "light" : "dark"; try { localStorage.setItem(THEME_KEY, n); } catch (e) {} return n; });
  };

  const run = useCallback(async (rawArg, modelArg, modeArg) => {
    const raw = (rawArg ?? prompt).trim();
    if (!raw) { setError(t.emptyWarn); return; }
    const useModel = modelArg ?? model;
    const useMode = modeArg ?? mode;
    setError(""); setLoading(true); setCopied(false);
    setResModel(useModel); setResMode(useMode);
    try {
      const out = await window.optimizePrompt(raw, useModel, useMode);
      setResult(out);
      const entry = { id: Date.now(), ts: Date.now(), raw, result: out, model: useModel, mode: useMode };
      setHistory((h) => { const n = [entry, ...h]; saveHistory(n); return n; });
    } catch (e) {
      const code = e && e.code;
      setError(code === "NO_BACKEND" ? t.noKeyError : t.error);
    } finally {
      setLoading(false);
    }
  }, [prompt, model, mode, t]);

  const onSubmit = () => run();
  const onRegen = () => run(prompt, resModel, resMode);
  const onReoptimize = (mId) => { setModel(mId); run(prompt, mId, resMode); };

  const onCopy = async () => {
    try { await navigator.clipboard.writeText(result); }
    catch (e) {
      const ta = document.createElement("textarea"); ta.value = result;
      document.body.appendChild(ta); ta.select(); document.execCommand("copy"); document.body.removeChild(ta);
    }
    setCopied(true); setTimeout(() => setCopied(false), 1600);
  };

  const onPickHistory = (it) => {
    setPrompt(it.raw); setResult(it.result); setModel(it.model); setMode(it.mode);
    setResModel(it.model); setResMode(it.mode); setError(""); setDrawer(false);
  };
  const onClearHistory = () => { setHistory([]); saveHistory([]); };
  const onNew = () => { setPrompt(""); setResult(""); setError(""); setCopied(false); };

  const hasActivity = loading || result || error;
  const RES = (id, fb) => (window.__resources && window.__resources[id]) || fb;
  const logoSrc = theme === "dark" ? RES("logoDark", "logo-dark.png") : RES("logoLight", "logo-light.png");
  const densityClass = "den-" + tw.density;
  const fontStack = `'${tw.font}', ui-sans-serif, system-ui, -apple-system, sans-serif`;

  return (
    <div className={"app " + densityClass} data-theme={theme}
      style={{ "--accent": tw.accent, "--font-ui": fontStack }}>
      <header className="topbar">
        <button className="brand" onClick={onNew} title={t.newChat}>
          <img className="brand__logo" src={logoSrc} alt="better promt" />
        </button>
        <div className="topbar__actions">
          {(prompt || result) && (
            <button className="ghost-btn sm hide-sm" onClick={onNew}>
              <window.Icon name="plus" size={15} /><span>{t.newChat}</span>
            </button>
          )}
          <button className="icon-btn" onClick={() => setDrawer(true)} title={t.history}>
            <window.Icon name="history" size={17} />
          </button>
          <LangMenu lang={lang} setLang={setLang} t={t} />
          <button className="icon-btn" onClick={toggleTheme} title={theme === "dark" ? t.light : t.dark}>
            <window.Icon name={theme === "dark" ? "sun" : "moon"} size={17} />
          </button>
        </div>
      </header>

      <main className={"main" + (hasActivity ? " main--active" : "")}>
        {!hasActivity && (
          <div className="hero">
            <h1 className="hero__title">{t.heroTitle}</h1>
            <p className="hero__sub">{t.heroSub}</p>
          </div>
        )}

        <Composer t={t} prompt={prompt} setPrompt={setPrompt} model={model} setModel={setModel}
          mode={mode} setMode={setMode} loading={loading} onSubmit={onSubmit} />

        {error && <div className="errbox">{error}</div>}

        {(loading || result) && (
          <ResultCard t={t} loading={loading} result={result} model={resModel} mode={resMode}
            onCopy={onCopy} copied={copied} onRegen={onRegen} onReoptimize={onReoptimize} />
        )}
      </main>

      <HistoryDrawer open={drawer} onClose={() => setDrawer(false)} items={history}
        onPick={onPickHistory} onClear={onClearHistory} t={t} />

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Brand" />
        <window.TweakColor label="Accent" value={tw.accent}
          options={["#5b5bf5", "#10b981", "#f59e0b", "#f43f5e", "#0ea5e9"]}
          onChange={(v) => setTweak("accent", v)} />
        <window.TweakSection label="Type" />
        <window.TweakSelect label="Font" value={tw.font}
          options={["Schibsted Grotesk", "Hanken Grotesk", "Figtree"]}
          onChange={(v) => setTweak("font", v)} />
        <window.TweakSection label="Layout" />
        <window.TweakRadio label="Density" value={tw.density}
          options={["compact", "regular", "comfy"]}
          onChange={(v) => setTweak("density", v)} />
      </window.TweaksPanel>
    </div>
  );
}

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