/* ============================================================
   Dependent fields prototype — Method 8
   ============================================================
   Q1: Do we have this in a process / system?  (Yes / No / N/A)
     - Q1=Yes  → Q2: Do we have evidence?      (Yes / No / N/A)
                  - Q2=Yes → Other comments (optional)
                  - Q2=No  → Finding details (required) + 1 Action (required)
                  - Q2=N/A → Other comments (optional)
     - Q1=No   → Finding details (required) + 1 Action (required)
     - Q1=N/A  → (nothing extra)
   ============================================================ */

const { useState, useEffect, useRef, useMemo } = React;

/* ---------- Tweak defaults (persisted to disk by the host) ---------- */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "anim": "slide",
  "requiredStyle": "asterisk",
  "actionStyle": "card",
  "showDebug": true,
  "showValidation": false
}/*EDITMODE-END*/;

/* ---------- Tiny icons ---------- */
const I = {
  check: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6 9 17l-5-5"/></svg>,
  x: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>,
  dash: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M5 12h14"/></svg>,
  plus: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>,
  warn: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg>,
  user: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>,
  flag: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 22V4a2 2 0 0 1 2-2h11l-2 4 2 4H6"/></svg>,
  calendar: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>,
  tag: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20.59 13.41 13.41 20.59a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"/><circle cx="7" cy="7" r="1.5" fill="currentColor"/></svg>,
};

/* ---------- YNA segmented control ---------- */
function YNA({ value, onChange, name }) {
  const opts = [
    { v: "yes", label: "Yes", cls: "sel-yes", icon: I.check },
    { v: "no",  label: "No",  cls: "sel-no",  icon: I.x },
    { v: "na",  label: "N/A", cls: "sel-na",  icon: I.dash },
  ];
  return (
    <div className="yna-row" role="radiogroup" aria-label={name}>
      {opts.map(o => (
        <button
          key={o.v}
          type="button"
          role="radio"
          aria-checked={value === o.v}
          className={"yna" + (value === o.v ? " " + o.cls : "")}
          onClick={() => onChange(o.v)}
        >
          {value === o.v ? o.icon : null}
          {o.label}
        </button>
      ))}
    </div>
  );
}

/* ---------- Reveal wrapper with auto-measured height for smooth slide ---------- */
function Reveal({ shown, anim, children }) {
  const ref = useRef(null);
  const [h, setH] = useState(0);

  useEffect(() => {
    if (!ref.current) return;
    const update = () => {
      // measure scrollHeight of inner
      const inner = ref.current.firstElementChild;
      if (inner) setH(inner.scrollHeight);
    };
    update();
    // observe size changes inside (textareas growing, nested reveals)
    const ro = new ResizeObserver(update);
    if (ref.current.firstElementChild) ro.observe(ref.current.firstElementChild);
    return () => ro.disconnect();
  }, [children]);

  return (
    <div
      className="reveal"
      data-anim={anim}
      data-shown={shown ? "true" : "false"}
      ref={ref}
      style={{ "--reveal-h": (h + 8) + "px" }}
      aria-hidden={!shown}
    >
      <div className="reveal-inner">{children}</div>
    </div>
  );
}

/* ---------- Action: simple inline button OR full Jira-style card ---------- */
function ActionStub({ required, onClick }) {
  return (
    <button type="button" className={"action-stub" + (required ? " required" : "")} onClick={onClick}>
      {I.plus} Add one action {required && <span style={{ color: "var(--text-tertiary)", fontWeight: 400, marginLeft: 4 }}>· required</span>}
    </button>
  );
}

function ActionCard({ value, onChange, onRemove, keyId }) {
  const prioMap = { high: "High", med: "Medium", low: "Low" };
  return (
    <div className="action-card">
      <div className="action-card-head">
        <span className="key">{keyId}</span>
        <span className="domain"><span className="dot"></span>Action</span>
        <button type="button" className="close" aria-label="Remove action" onClick={onRemove}>{I.x}</button>
      </div>
      <div className="action-card-body">
        <input
          type="text"
          className="title"
          placeholder="Action title — e.g. Document the policy and circulate"
          value={value.title}
          onChange={e => onChange({ ...value, title: e.target.value })}
        />
        <textarea
          className="desc"
          placeholder="Short description — what needs to happen, and why."
          value={value.desc}
          onChange={e => onChange({ ...value, desc: e.target.value })}
        />
        <div className="meta-row">
          <button
            type="button"
            className="meta-pill"
            data-empty={value.owner ? "false" : "true"}
            onClick={() => onChange({ ...value, owner: value.owner ? "" : "Sarah Mensah" })}
          >
            <span className="ico">{I.user}</span>
            <span className="label">Owner</span>
            <span className="val">{value.owner || "Unassigned"}</span>
          </button>
          <button
            type="button"
            className="meta-pill"
            data-priority={value.priority}
            onClick={() => {
              const order = ["low", "med", "high"];
              const next = order[(order.indexOf(value.priority) + 1) % order.length];
              onChange({ ...value, priority: next });
            }}
          >
            <span className="ico">{I.flag}</span>
            <span className="label">Priority</span>
            <span className="val">{prioMap[value.priority]}</span>
          </button>
          <button
            type="button"
            className="meta-pill"
            data-empty={value.due ? "false" : "true"}
            onClick={() => onChange({ ...value, due: value.due ? "" : "Jun 14, 2026" })}
          >
            <span className="ico">{I.calendar}</span>
            <span className="label">Due</span>
            <span className="val">{value.due || "No due date"}</span>
          </button>
        </div>
      </div>
    </div>
  );
}

/* ---------- Findings + action sub-block (reused for Q1=No and Q2=No) ---------- */
function FindingsAndAction({ keyId, t, state, set, showValidation, branchVariant }) {
  const findingsEmpty = !state.findings.trim();
  const actionInvalid = !state.action || !state.action.title.trim();

  return (
    <div className={"nested " + branchVariant}>
      <div className="field-block">
        <label className="field-label" htmlFor={keyId + "-findings"}>
          Finding details
          {t.requiredStyle === "asterisk" && <span className="req">*</span>}
          {t.requiredStyle === "label" && <span className="req">Required</span>}
        </label>
        <div className="field-help">Explain what's missing or why this control isn't met.</div>
        <textarea
          id={keyId + "-findings"}
          className={"field" + (showValidation && findingsEmpty ? " invalid" : "")}
          placeholder="e.g. Walks happen ad-hoc. No formal cadence, no follow-up register."
          value={state.findings}
          onChange={e => set({ findings: e.target.value })}
        />
        {showValidation && findingsEmpty && (
          <div className="err-msg">{I.warn} Finding details are required when this is "No".</div>
        )}
      </div>

      <div className="field-block">
        <label className="field-label">
          Action
          {t.requiredStyle === "asterisk" && <span className="req">*</span>}
          {t.requiredStyle === "label" && <span className="req">Required</span>}
          <span className="opt">· only one</span>
        </label>

        {!state.action && (
          <div>
            {t.actionStyle === "stub"
              ? <ActionStub required onClick={() => set({ action: emptyAction() })} />
              : <ActionStub required onClick={() => set({ action: emptyAction() })} />
            }
            {showValidation && (
              <div className="err-msg" style={{ marginTop: 6 }}>{I.warn} One action is required when this is "No".</div>
            )}
          </div>
        )}

        {state.action && (
          t.actionStyle === "card"
            ? <ActionCard
                value={state.action}
                onChange={v => set({ action: v })}
                onRemove={() => set({ action: null })}
                keyId={keyId}
              />
            : <SimpleActionRow
                value={state.action}
                onChange={v => set({ action: v })}
                onRemove={() => set({ action: null })}
                showValidation={showValidation}
              />
        )}
      </div>
    </div>
  );
}

function SimpleActionRow({ value, onChange, onRemove, showValidation }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <input
        type="text"
        className={"field" + (showValidation && !value.title.trim() ? " invalid" : "")}
        placeholder="Action title — e.g. Document the policy and circulate"
        value={value.title}
        onChange={e => onChange({ ...value, title: e.target.value })}
      />
      <button
        type="button"
        onClick={onRemove}
        style={{
          alignSelf: "flex-start",
          background: "transparent", border: "none", padding: 0,
          color: "var(--text-tertiary)",
          font: "500 12px/16px var(--font-sans)",
          cursor: "pointer", textDecoration: "underline",
        }}
      >Remove action</button>
    </div>
  );
}

function emptyAction() {
  return { title: "", desc: "", owner: "", priority: "med", due: "" };
}

/* ---------- Other comments (optional) ---------- */
function OtherComments({ value, onChange }) {
  return (
    <div className="field-block">
      <label className="field-label" htmlFor="other-comments">
        Other comments <span className="opt">Optional</span>
      </label>
      <textarea
        id="other-comments"
        className="field"
        placeholder="What can be improved? What are we doing well?"
        value={value}
        onChange={e => onChange(e.target.value)}
      />
    </div>
  );
}

/* ---------- Main app ---------- */
function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  // Form state
  const [q1, setQ1] = useState(null);              // 'yes' | 'no' | 'na' | null
  const [q2, setQ2] = useState(null);
  const [otherComments, setOtherComments] = useState("");

  // Per-branch state (kept separately so toggling preserves work)
  const [q1NoBranch, setQ1NoBranch] = useState({ findings: "", action: null });
  const [q2NoBranch, setQ2NoBranch] = useState({ findings: "", action: null });

  // When Q1 changes away from yes, reset Q2 so the form doesn't carry hidden state
  useEffect(() => { if (q1 !== "yes") setQ2(null); }, [q1]);

  // Derive what's visible
  const showQ2          = q1 === "yes";
  const showQ1NoBlock   = q1 === "no";
  const showQ2NoBlock   = q1 === "yes" && q2 === "no";
  const showOtherC      = (q1 === "yes" && (q2 === "yes" || q2 === "na"));

  // Required-but-empty check for validation/submit-enable
  const errors = useMemo(() => {
    const e = [];
    if (q1 === null) e.push("Answer Q1");
    else if (q1 === "yes" && q2 === null) e.push("Answer Q2");
    if (showQ1NoBlock) {
      if (!q1NoBranch.findings.trim()) e.push("Findings required");
      if (!q1NoBranch.action || !q1NoBranch.action.title.trim()) e.push("Action required");
    }
    if (showQ2NoBlock) {
      if (!q2NoBranch.findings.trim()) e.push("Findings required");
      if (!q2NoBranch.action || !q2NoBranch.action.title.trim()) e.push("Action required");
    }
    return e;
  }, [q1, q2, showQ1NoBlock, showQ2NoBlock, q1NoBranch, q2NoBranch]);

  const canSubmit = errors.length === 0;

  const handleSubmit = () => {
    if (canSubmit) {
      // success — flash
      setTweak("showValidation", false);
      alert("Saved.\n\nQ1: " + q1 + "\nQ2: " + (q2 || "—"));
    } else {
      setTweak("showValidation", true);
    }
  };

  const reset = () => {
    setQ1(null); setQ2(null); setOtherComments("");
    setQ1NoBranch({ findings: "", action: null });
    setQ2NoBranch({ findings: "", action: null });
    setTweak("showValidation", false);
  };

  return (
    <>
      <div className="qcard">
        <div className="qcard-head">
          <div className="qcard-eyebrow">2.2.1 · High priority</div>
          <h2 className="qcard-q">A current, approved Sustainability Policy exists and is communicated to personnel. The policy must include a commitment to the improvement of safety.</h2>
          <div className="qcard-example">Example of evidence: signed policy, revision history, distribution list, induction materials.</div>
        </div>

        <div className="qcard-body">

          {/* Q1 */}
          <div className="field-block">
            <label className="field-label">
              Do we have this in a process / system?
              {t.requiredStyle === "asterisk" && <span className="req">*</span>}
              {t.requiredStyle === "label" && <span className="req">Required</span>}
            </label>
            <YNA value={q1} onChange={setQ1} name="Q1" />
          </div>

          {/* Q1 = Yes → reveal Q2 */}
          <Reveal shown={showQ2} anim={t.anim}>
            <div className={"nested nested-yes"}>
              <div className="field-block">
                <label className="field-label">
                  Do we have evidence?
                  {t.requiredStyle === "asterisk" && <span className="req">*</span>}
                  {t.requiredStyle === "label" && <span className="req">Required</span>}
                </label>
                <YNA value={q2} onChange={setQ2} name="Q2" />
              </div>

              {/* Q2 = No → findings + action */}
              <Reveal shown={showQ2NoBlock} anim={t.anim}>
                <FindingsAndAction
                  keyId="ACT-EVID"
                  t={t}
                  state={q2NoBranch}
                  set={p => setQ2NoBranch(s => ({ ...s, ...p }))}
                  showValidation={t.showValidation}
                  branchVariant="nested-no"
                />
              </Reveal>
            </div>
          </Reveal>

          {/* Q1 = No → findings + action */}
          <Reveal shown={showQ1NoBlock} anim={t.anim}>
            <FindingsAndAction
              keyId="ACT-PROC"
              t={t}
              state={q1NoBranch}
              set={p => setQ1NoBranch(s => ({ ...s, ...p }))}
              showValidation={t.showValidation}
              branchVariant="nested-no"
            />
          </Reveal>

          {/* Q1=Yes & Q2 in {yes, na} → Other comments */}
          <Reveal shown={showOtherC} anim={t.anim}>
            <OtherComments value={otherComments} onChange={setOtherComments} />
          </Reveal>

        </div>

        <div className="qcard-footer">
          <span className="footer-hint">
            {q1 === null && <>Answer Q1 to continue.</>}
            {q1 === "na" && <>N/A recorded — <b>no further input needed</b>.</>}
            {q1 === "yes" && q2 === null && <>Answer Q2 to continue.</>}
            {q1 === "yes" && (q2 === "yes" || q2 === "na") && <>Optional comment, then save.</>}
            {((q1 === "no") || (q1 === "yes" && q2 === "no")) && (
              canSubmit
                ? <>All required fields complete.</>
                : <>{errors.length} field{errors.length === 1 ? "" : "s"} need attention.</>
            )}
          </span>
          <span className="footer-spacer"></span>
          <button className="btn btn-secondary" onClick={reset}>Reset</button>
          <button
            className="btn btn-primary"
            onClick={handleSubmit}
            aria-disabled={!canSubmit && q1 !== null}
          >Save answer</button>
        </div>
      </div>

      {/* Debug overlay */}
      {t.showDebug && (
        <div className="debug">
          <h5><span className="dot"></span>Form state</h5>
          <DebugRow k="Q1 — process / system" v={q1} />
          <DebugRow k="Q2 — evidence" v={showQ2 ? q2 : "—"} />
          <DebugRow k="Findings (Q1=No)" v={showQ1NoBlock ? (q1NoBranch.findings ? "filled" : "empty") : "—"} />
          <DebugRow k="Action (Q1=No)" v={showQ1NoBlock ? (q1NoBranch.action ? "set" : "empty") : "—"} />
          <DebugRow k="Findings (Q2=No)" v={showQ2NoBlock ? (q2NoBranch.findings ? "filled" : "empty") : "—"} />
          <DebugRow k="Action (Q2=No)" v={showQ2NoBlock ? (q2NoBranch.action ? "set" : "empty") : "—"} />
          <DebugRow k="Other comments" v={showOtherC ? (otherComments ? "filled" : "empty") : "—"} />
          <button className="reset" onClick={reset}>Reset all answers</button>
        </div>
      )}

      {/* Tweaks panel */}
      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Reveal animation" />
        <window.TweakRadio
          label="Style" value={t.anim}
          options={[
            { value: "slide", label: "Slide" },
            { value: "fade",  label: "Fade" },
            { value: "snap",  label: "Instant" },
          ]}
          onChange={v => setTweak("anim", v)}
        />

        <window.TweakSection label="Required indicator" />
        <window.TweakRadio
          label="Show as" value={t.requiredStyle}
          options={[
            { value: "asterisk", label: "*" },
            { value: "label",    label: "Required" },
            { value: "none",     label: "None" },
          ]}
          onChange={v => setTweak("requiredStyle", v)}
        />

        <window.TweakSection label="Action treatment" />
        <window.TweakRadio
          label="Layout" value={t.actionStyle}
          options={[
            { value: "card", label: "Full card" },
            { value: "row",  label: "Single row" },
          ]}
          onChange={v => setTweak("actionStyle", v)}
        />

        <window.TweakSection label="Debug" />
        <window.TweakToggle
          label="State overlay" value={t.showDebug}
          onChange={v => setTweak("showDebug", v)}
        />
        <window.TweakToggle
          label="Validation errors" value={t.showValidation}
          onChange={v => setTweak("showValidation", v)}
        />
      </window.TweaksPanel>
    </>
  );
}

function DebugRow({ k, v }) {
  const isStatus = v === "yes" || v === "no" || v === "na";
  const display = v == null ? "—" : (v === "—" ? "—" : v);
  const cls = isStatus ? v : (v === "—" || v == null ? "dash" : "");
  return (
    <div className="debug-row">
      <span className="k">{k}</span>
      <span className={"v " + cls}>{display}</span>
    </div>
  );
}

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