/**
 * parseNativ — tiny, forgiving interpreter for the demo subset of .nativ.
 * Enough to make the playground preview feel live: text / button / textfield /
 * toggle / spacer, screen state, {interpolation}, and count += n actions.
 * Not the real compiler — a cosmetic stand-in for the static HTML preview that
 * `nativ preview` emits.
 */
function parseNativ(src) {
  const lines = src.split("\n");
  const state = {};
  const els = [];
  let title = "Preview";

  const parseMods = (rest) =>
    rest
      .split(",")
      .slice(1)
      .map((s) => s.trim())
      .filter(Boolean);

  for (let raw of lines) {
    const line = raw.trim();
    if (!line || line.startsWith("//")) continue;

    let m;
    if ((m = line.match(/^app\s+\w+/))) continue;
    if ((m = line.match(/^name:\s*"([^"]*)"/))) { title = m[1]; continue; }
    if ((m = line.match(/^screen\s+(\w+)/))) { title = m[1]; continue; }
    if ((m = line.match(/^state\s+(\w+)\s*=\s*(.+)$/))) {
      let v = m[2].trim();
      if (v === "[]") state[m[1]] = [];
      else if (v === "true" || v === "false") state[m[1]] = v === "true";
      else if (/^".*"$/.test(v)) state[m[1]] = v.slice(1, -1);
      else if (/^\d+$/.test(v)) state[m[1]] = parseInt(v, 10);
      else state[m[1]] = v;
      continue;
    }
    if ((m = line.match(/^text\s+"([^"]*)"(.*)$/))) {
      els.push({ kind: "text", text: m[1], mods: parseMods(m[0]) });
      continue;
    }
    if ((m = line.match(/^button\s+"([^"]*)"(.*)$/))) {
      const mods = parseMods(m[0].replace(/:$/, ""));
      els.push({ kind: "button", text: m[1], mods });
      continue;
    }
    if ((m = line.match(/^textfield\s+"([^"]*)"/))) {
      els.push({ kind: "textfield", placeholder: m[1] });
      continue;
    }
    if ((m = line.match(/^toggle\s+(.+)$/))) {
      els.push({ kind: "toggle", label: m[1].trim() });
      continue;
    }
    if (/^spacer\b/.test(line)) { els.push({ kind: "spacer" }); continue; }
  }
  return { title, state, els };
}

const interp = (text, state) =>
  text.replace(/\{(\w+)\}/g, (_, k) => (k in state ? String(state[k]) : `{${k}}`));

/**
 * NativePreview — renders the parsed screen in an iOS-flavored native look.
 * `count += 1`-style buttons actually increment; toggles flip; the field type-binds.
 */
function NativePreview({ source }) {
  const parsed = React.useMemo(() => parseNativ(source), [source]);
  const [vals, setVals] = React.useState({});
  const [toggles, setToggles] = React.useState({});
  const [field, setField] = React.useState("");

  // reset derived state when the set of state vars changes
  const stateKey = Object.keys(parsed.state).join(",");
  React.useEffect(() => setVals({ ...parsed.state }), [stateKey, source]);

  const merged = { ...parsed.state, ...vals };

  const bump = (el) => {
    // find a numeric state var to increment (demo heuristic)
    const numKey = Object.keys(parsed.state).find((k) => typeof parsed.state[k] === "number");
    if (numKey != null) setVals((v) => ({ ...v, [numKey]: (v[numKey] ?? parsed.state[numKey]) + 1 }));
  };

  return (
    <div
      style={{
        fontFamily: "-apple-system, system-ui, sans-serif",
        padding: "26px 22px",
        display: "flex",
        flexDirection: "column",
        gap: 16,
        color: "#000",
        minHeight: "100%",
      }}
    >
      {parsed.els.map((el, i) => {
        if (el.kind === "text") {
          const big = el.mods.includes("big");
          const bold = el.mods.includes("bold");
          const gray = el.mods.includes("gray") || el.mods.includes("grey");
          return (
            <div
              key={i}
              style={{
                fontSize: big ? 28 : 17,
                fontWeight: bold ? 700 : big ? 600 : 400,
                color: gray ? "#8a8a8e" : "#000",
                letterSpacing: big ? "-0.02em" : 0,
                lineHeight: 1.25,
              }}
            >
              {interp(el.text, merged)}
            </div>
          );
        }
        if (el.kind === "button") {
          const destructive = el.mods.includes("red");
          return (
            <button
              key={i}
              onClick={() => bump(el)}
              style={{
                appearance: "none",
                border: "none",
                borderRadius: 12,
                padding: "13px 18px",
                fontSize: 16,
                fontWeight: 600,
                fontFamily: "inherit",
                cursor: "pointer",
                color: "#fff",
                background: destructive ? "#ff3b30" : "#007aff",
                boxShadow: "0 1px 0 rgba(0,0,0,.04)",
              }}
            >
              {interp(el.text, merged)}
            </button>
          );
        }
        if (el.kind === "textfield") {
          return (
            <input
              key={i}
              value={field}
              placeholder={el.placeholder}
              onChange={(e) => setField(e.target.value)}
              style={{
                border: "1px solid #d1d1d6",
                borderRadius: 10,
                padding: "12px 14px",
                fontSize: 16,
                fontFamily: "inherit",
                outline: "none",
                color: "#000",
                background: "#fff",
              }}
            />
          );
        }
        if (el.kind === "toggle") {
          const on = toggles[i] ?? false;
          return (
            <div
              key={i}
              style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}
            >
              <span style={{ fontSize: 16 }}>{el.label}</span>
              <button
                onClick={() => setToggles((t) => ({ ...t, [i]: !on }))}
                style={{
                  width: 51,
                  height: 31,
                  borderRadius: 99,
                  border: "none",
                  cursor: "pointer",
                  padding: 2,
                  background: on ? "#34c759" : "#e9e9ea",
                  transition: "background .2s",
                  display: "flex",
                  justifyContent: on ? "flex-end" : "flex-start",
                }}
              >
                <span
                  style={{
                    width: 27,
                    height: 27,
                    borderRadius: "50%",
                    background: "#fff",
                    boxShadow: "0 2px 5px rgba(0,0,0,.2)",
                  }}
                />
              </button>
            </div>
          );
        }
        if (el.kind === "spacer") return <div key={i} style={{ flex: 1 }} />;
        return null;
      })}
    </div>
  );
}

Object.assign(window, { parseNativ, NativePreview });
