/* ============================================================================
   DIVONCI WORLD — FOUNDRY PACKET DRAWER
   "Create Project" on the surface; "Create Foundry Packet" the moment it opens.
   Foundry decides and prepares — it does NOT approve, deploy, or claim ready.
   Every new project begins as a governed draft packet whose unknowns become
   visible decisions/TODOs, never silent guesses.
   ========================================================================== */
const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP } = React;

/* ---- persistence: draft packets survive nav + reload ------------------- */
const PacketStore = (() => {
  const KEY = "dw_foundry_packets_v1";
  let list = [];
  try { list = JSON.parse(localStorage.getItem(KEY)) || []; } catch (e) { list = []; }
  const subs = new Set();
  const persist = () => { try { localStorage.setItem(KEY, JSON.stringify(list)); } catch (e) {} };
  const emit = () => subs.forEach(fn => fn(list.slice()));
  return {
    all: () => list.slice(),
    add(p) { list = [p, ...list]; persist(); emit(); },
    subscribe(fn) { subs.add(fn); return () => subs.delete(fn); },
  };
})();
window.PacketStore = PacketStore;

/* ---- helpers ----------------------------------------------------------- */
function slugify(s) {
  return (s || "").toLowerCase().trim()
    .replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
}
function splitLines(s) {
  return (s || "").split(/\n|,/).map(x => x.trim()).filter(Boolean);
}
const STAGES = ["Idea", "Doctrine", "Design", "Build", "Test", "Deploy"];
const AUTH_MODELS = ["", "None (public)", "Email + password", "Magic link", "OAuth (Google/GitHub)", "SSO / org", "Wallet"];
const ADMIN_MODELS = ["", "Single owner", "Role-based (RBAC)", "Council-gated", "No admin surface"];
const MON_MODELS = ["", "Free / internal", "Subscription", "Usage-based", "One-time licence", "Ad-supported"];

/* AppBlueprint contract — unknowns stay "TODO"/[] rather than fabricated. */
function buildBlueprint(f) {
  const TODO = "TODO";
  return {
    app_name:            f.name.trim()       || TODO,
    app_slug:            (f.slug || slugify(f.name)) || TODO,
    one_line_purpose:    f.purpose.trim()    || TODO,
    target_users:        splitLines(f.users),
    core_user_journeys:  splitLines(f.journeys),
    core_data_objects:   splitLines(f.dataObjects),
    auth_model:          f.auth              || TODO,
    admin_model:         f.admin             || TODO,
    monetisation_model:  f.monetisation      || TODO,
    required_screens:    splitLines(f.screens),
    pwa_required:        !!f.pwa,
    capacitor_required:  !!f.capacitor,
    media_pack_required: !!f.media,
  };
}

/* Open decisions: every empty / uncertain field becomes a visible TODO row. */
function computeDecisions(f) {
  const d = [];
  if (!f.name.trim())                       d.push("Project name not set");
  if (!f.purpose.trim())                    d.push("One-line purpose unclear");
  if (splitLines(f.users).length === 0)     d.push("Target users undefined");
  if (splitLines(f.journeys).length === 0)  d.push("Core user journeys incomplete");
  if (splitLines(f.dataObjects).length === 0) d.push("Core data objects incomplete");
  if (!f.auth)                              d.push("Auth model not confirmed");
  if (!f.admin)                             d.push("Admin model not confirmed");
  if (!f.monetisation)                      d.push("Monetisation model unclear");
  if (splitLines(f.screens).length === 0)   d.push("Required screens incomplete");
  if (f.media && !f.mediaApproved)          d.push("Media source of truth not approved");
  return d;
}

/* Foundry gates — fixed governance checklist. Build/deploy stay blocked. */
function computeGates(f, decisions) {
  const intakeOk = !!(f.raw.trim() && f.name.trim() && f.purpose.trim());
  return [
    { label: "Intake captured",            state: intakeOk ? "clear" : "caution", note: intakeOk ? "Command + purpose logged" : "Needs raw idea + purpose" },
    { label: "Doctrine TODOs created",      state: "active",  note: decisions.length + " open" },
    { label: "Open decisions listed",       state: decisions.length ? "caution" : "clear", note: decisions.length ? decisions.length + " to resolve" : "none open" },
    { label: "Media / design pack required", state: f.media ? "caution" : "standby", note: f.media ? (f.mediaApproved ? "approved" : "awaiting source of truth") : "not required" },
    { label: "Claude design prompt required", state: "caution", note: "pending generation" },
    { label: "Build packet generated",      state: "standby", note: "not generated yet" },
    { label: "QA / Playwright packet required", state: "caution", note: "pending" },
    { label: "Studio handoff",              state: "crisis",  note: "blocked until approval" },
  ];
}

/* readiness: low by design — a fresh packet must never look "ready". */
function readinessOf(f, decisions) {
  const fields = [f.name, f.purpose, f.users, f.journeys, f.dataObjects, f.auth, f.admin, f.monetisation, f.screens];
  const filled = fields.filter(x => (x || "").toString().trim()).length;
  return Math.min(34, Math.round((filled / fields.length) * 34)); // capped low; draft never > 34
}

function blankForm() {
  return {
    raw: "", name: "", slug: "", purpose: "", owner: "viiera", stage: "Idea",
    users: "", journeys: "", dataObjects: "", auth: "", admin: "", monetisation: "",
    screens: "", pwa: true, capacitor: false, media: true, mediaApproved: false,
  };
}

/* ---- small form atoms -------------------------------------------------- */
function Fld({ label, hint, children }) {
  return (
    <label className="pkt-fld">
      <span className="pkt-fld-l">{label}{hint && <em>{hint}</em>}</span>
      {children}
    </label>
  );
}
function SecHead({ n, title, right }) {
  return (
    <div className="pkt-sechead">
      <span className="pkt-secn">{n}</span>
      <span className="pkt-sect">{title}</span>
      <span className="pkt-secline" />
      {right}
    </div>
  );
}

/* ---- the drawer -------------------------------------------------------- */
function FoundryPacketDrawer({ open, onClose, nav }) {
  const [f, setF] = useStateP(blankForm);
  const set = (k, v) => setF(p => ({ ...p, [k]: v }));

  // reset to a clean packet each time the drawer is opened
  useEffectP(() => { if (open) setF(blankForm()); }, [open]);

  // esc to close
  useEffectP(() => {
    if (!open) return;
    const h = e => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open, onClose]);

  const slug = f.slug || slugify(f.name);
  const decisions = useMemoP(() => computeDecisions(f), [f]);
  const blueprint = useMemoP(() => buildBlueprint(f), [f]);
  const gates = useMemoP(() => computeGates(f, decisions), [f, decisions]);

  // enabled only when at least one substantive field is captured
  const hasAny = [f.name, f.slug, f.purpose, f.users, f.journeys, f.dataObjects, f.auth, f.admin, f.monetisation, f.screens]
    .some(x => (x || "").trim());

  function save() {
    if (!hasAny) return;
    const dec = computeDecisions(f);
    const packet = {
      id: "pk_" + Date.now().toString(36),
      name: f.name.trim() || "Untitled packet",
      slug, purpose: f.purpose.trim(),
      stage: f.stage, owner: f.owner,
      state: "standby",                 // draft never reads as live/ready
      draft: true, packet: true,
      health: readinessOf(f, dec),      // readiness, capped low
      risk: "tbd", progress: 0, status: "draft",
      decisions: dec,
      gates: computeGates(f, dec),
      blueprint: buildBlueprint(f),
      created: new Date().toISOString(),
    };
    PacketStore.add(packet);
    onClose();
  }

  const agents = DW.AGENTS;

  return (
    <div className={"pkt-root" + (open ? " open" : "")} aria-hidden={!open}>
      <div className="pkt-backdrop" onClick={onClose} />
      <aside className="pkt-drawer" role="dialog" aria-modal="true" aria-label="Create Foundry Packet">
        {/* header */}
        <header className="pkt-head">
          <div className="pkt-head-l">
            <span className="pkt-eyebrow"><Icon name="foundry" className="glyph" style={{ width: 13, height: 13 }} /> Foundry · prepare</span>
            <h2 className="pkt-title">Create Foundry Packet</h2>
            <p className="pkt-sub">Foundry decides and prepares. Studio executes. Every project begins as a governed packet — unknowns become decisions, nothing here approves or deploys.</p>
          </div>
          <button className="pkt-x focusable" onClick={onClose} aria-label="Close">✕</button>
        </header>

        {/* scrolling body */}
        <div className="pkt-body comms-scroll">
          {/* 1 — INTAKE */}
          <section className="pkt-sec">
            <SecHead n="01" title="Intake" />
            <Fld label="Raw idea / command" hint="what you told the Council">
              <textarea className="pkt-ctrl" rows={3} value={f.raw} onChange={e => set("raw", e.target.value)}
                placeholder="“Build a relay console that lets approved admins request changes from Telegram…”" />
            </Fld>
            <div className="pkt-grid2">
              <Fld label="Project name">
                <input className="pkt-ctrl" value={f.name} onChange={e => set("name", e.target.value)} placeholder="Foundry Control" />
              </Fld>
              <Fld label="Slug" hint="auto">
                <div className="pkt-slug">
                  <span>/{slug || "—"}</span>
                  <button className="minilink" type="button" onClick={() => set("slug", "")}>reset</button>
                </div>
              </Fld>
            </div>
            <Fld label="One-line purpose">
              <input className="pkt-ctrl" value={f.purpose} onChange={e => set("purpose", e.target.value)} placeholder="Controlled change-requests with safe validation + deploy gates." />
            </Fld>
            <div className="pkt-grid2">
              <Fld label="Commanding agent">
                <select className="pkt-ctrl" value={f.owner} onChange={e => set("owner", e.target.value)}>
                  {agents.map(a => <option key={a.id} value={a.id}>{a.name} · {a.domain}</option>)}
                </select>
              </Fld>
              <Fld label="Starting stage">
                <div className="pkt-seg">
                  {STAGES.map(s => (
                    <button key={s} type="button" className={f.stage === s ? "on" : ""} onClick={() => set("stage", s)}>{s}</button>
                  ))}
                </div>
              </Fld>
            </div>
            <div className="pkt-note">
              <Led state="standby" size={7} />
              Health &amp; risk are <b>synthetic draft defaults</b> — set to standby / low until gates resolve.
            </div>
          </section>

          {/* 2 — BLUEPRINT */}
          <section className="pkt-sec">
            <SecHead n="02" title="Blueprint" right={<span className="pkt-secright">AppBlueprint</span>} />
            <Fld label="Target users" hint="one per line">
              <textarea className="pkt-ctrl" rows={2} value={f.users} onChange={e => set("users", e.target.value)} placeholder={"Approved admins\nCouncil operators"} />
            </Fld>
            <Fld label="Core user journeys" hint="one per line">
              <textarea className="pkt-ctrl" rows={2} value={f.journeys} onChange={e => set("journeys", e.target.value)} placeholder={"Submit change request\nReview preview deploy\nApprove production publish"} />
            </Fld>
            <Fld label="Core data objects" hint="one per line">
              <textarea className="pkt-ctrl" rows={2} value={f.dataObjects} onChange={e => set("dataObjects", e.target.value)} placeholder={"ChangeRequest\nValidationResult\nDeployRecord"} />
            </Fld>
            <div className="pkt-grid2">
              <Fld label="Auth model">
                <select className="pkt-ctrl" value={f.auth} onChange={e => set("auth", e.target.value)}>
                  {AUTH_MODELS.map(m => <option key={m} value={m}>{m || "— not confirmed —"}</option>)}
                </select>
              </Fld>
              <Fld label="Admin model">
                <select className="pkt-ctrl" value={f.admin} onChange={e => set("admin", e.target.value)}>
                  {ADMIN_MODELS.map(m => <option key={m} value={m}>{m || "— not confirmed —"}</option>)}
                </select>
              </Fld>
            </div>
            <Fld label="Monetisation model">
              <select className="pkt-ctrl" value={f.monetisation} onChange={e => set("monetisation", e.target.value)}>
                {MON_MODELS.map(m => <option key={m} value={m}>{m || "— unclear —"}</option>)}
              </select>
            </Fld>
            <Fld label="Required screens" hint="one per line">
              <textarea className="pkt-ctrl" rows={2} value={f.screens} onChange={e => set("screens", e.target.value)} placeholder={"Dashboard\nNew request\nRequest detail\nDeploy history\nSettings"} />
            </Fld>
            <div className="pkt-toggles">
              {[["pwa", "PWA required"], ["capacitor", "Capacitor required"], ["media", "Media pack required"]].map(([k, lbl]) => (
                <button key={k} type="button" className={"pkt-toggle" + (f[k] ? " on" : "")} onClick={() => set(k, !f[k])}>
                  <span className="pkt-toggle-box">{f[k] && <Icon name="check" className="glyph" style={{ width: 12, height: 12 }} />}</span>{lbl}
                </button>
              ))}
            </div>
          </section>

          {/* 3 — FOUNDRY GATES */}
          <section className="pkt-sec">
            <SecHead n="03" title="Foundry gates" />
            <div className="pkt-gates">
              {gates.map((g, i) => (
                <div key={i} className="pkt-gate">
                  <Led state={g.state} size={8} />
                  <span className="pkt-gate-l">{g.label}</span>
                  <span className="pkt-gate-n" data-state={g.state}>{g.note}</span>
                </div>
              ))}
            </div>
          </section>

          {/* 4 — OPEN DECISIONS */}
          <section className="pkt-sec">
            <SecHead n="04" title="Open decisions" right={<span className="pkt-count" data-on={decisions.length > 0}>{decisions.length}</span>} />
            {decisions.length === 0 ? (
              <div className="pkt-clear"><Led state="clear" size={7} /> No open decisions — every required field captured.</div>
            ) : (
              <div className="pkt-decs">
                {decisions.map((d, i) => (
                  <div key={i} className="pkt-dec">
                    <Icon name="risk" className="glyph" style={{ width: 14, height: 14 }} />
                    <span>{d}</span>
                    <em>TODO</em>
                  </div>
                ))}
              </div>
            )}
          </section>

          {/* 5 — PREVIEW */}
          <section className="pkt-sec">
            <SecHead n="05" title="Blueprint preview" right={<span className="pkt-secright">{decisions.length ? "draft · incomplete" : "draft · complete"}</span>} />
            <pre className="pkt-json comms-scroll">{JSON.stringify(blueprint, null, 2)}</pre>
          </section>
        </div>

        {/* footer actions */}
        <footer className="pkt-foot">
          <button className="btn ghost" onClick={onClose}>Cancel</button>
          <button className="btn" onClick={() => { nav && nav("foundry"); }}>Open in Foundry →</button>
          <button className="btn primary" disabled={!hasAny} onClick={save}>Save draft packet</button>
        </footer>
      </aside>
    </div>
  );
}

Object.assign(window, { FoundryPacketDrawer, PacketStore });
