// Dialog primitives — proper, themed modals replacing browser prompt/confirm.
// Promise-based API:
//   await window.dialog.confirm({ title, body, danger, confirmLabel, cancelLabel })
//   await window.dialog.form({ title, body, fields, submitLabel })
//
// `fields` is an array of { name, label, type, placeholder, required, value, options }.

(function () {
  const channel = new EventTarget();
  let nextId = 1;
  const queue = [];

  function open(spec, resolve) {
    queue.push({ id: nextId++, spec, resolve });
    channel.dispatchEvent(new CustomEvent("change"));
  }
  function close(id, value) {
    const idx = queue.findIndex((q) => q.id === id);
    if (idx < 0) return;
    const [{ resolve }] = queue.splice(idx, 1);
    resolve(value);
    channel.dispatchEvent(new CustomEvent("change"));
  }

  window.dialog = {
    confirm: (spec) => new Promise((resolve) => open({ kind: "confirm", ...spec }, resolve)),
    form: (spec) => new Promise((resolve) => open({ kind: "form", ...spec }, resolve)),
  };
  window.dialog._channel = channel;
  window.dialog._queue = () => queue.slice();
  window.dialog._close = close;
})();

function useDialogQueue() {
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    const cb = () => force();
    window.dialog._channel.addEventListener("change", cb);
    return () => window.dialog._channel.removeEventListener("change", cb);
  }, []);
  return window.dialog._queue();
}

function ConfirmDialog({ id, spec }) {
  const { title, body, danger, confirmLabel = "Confirm", cancelLabel = "Cancel" } = spec;
  const close = (v) => window.dialog._close(id, v);
  return (
    <div className="cstl-dialog-scrim" onClick={() => close(false)}>
      <div className="cstl-dialog" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true">
        <div className="cstl-dialog-head">
          <h3 className="cstl-dialog-title">{title}</h3>
          <button className="cstl-dialog-close" onClick={() => close(false)} aria-label="Close">×</button>
        </div>
        <div className="cstl-dialog-body">
          {typeof body === "string" ? <p>{body}</p> : body}
        </div>
        <div className="cstl-dialog-foot">
          <button className="btn ghost" onClick={() => close(false)}>{cancelLabel}</button>
          <button
            className={"btn " + (danger ? "danger" : "primary")}
            onClick={() => close(true)}
            autoFocus
          >
            {confirmLabel}
          </button>
        </div>
      </div>
    </div>
  );
}

function FormDialog({ id, spec }) {
  const { title, body, fields = [], submitLabel = "Create", cancelLabel = "Cancel", danger = false } = spec;
  const close = (v) => window.dialog._close(id, v);
  const [values, setValues] = React.useState(() => {
    const out = {};
    for (const f of fields) out[f.name] = f.value ?? "";
    return out;
  });
  const set = (n, v) => setValues((s) => ({ ...s, [n]: v }));
  const canSubmit = fields.every((f) => !f.required || (values[f.name] != null && String(values[f.name]).trim() !== ""));
  const submit = (e) => {
    e?.preventDefault?.();
    if (!canSubmit) return;
    close(values);
  };
  const firstRef = React.useRef(null);
  React.useEffect(() => { firstRef.current?.focus(); }, []);

  return (
    <div className="cstl-dialog-scrim" onClick={() => close(null)}>
      <form
        className="cstl-dialog cstl-dialog-form"
        onClick={(e) => e.stopPropagation()}
        onSubmit={submit}
        onKeyDown={(e) => {
          if (e.key === "Escape") close(null);
          if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) submit(e);
        }}
        role="dialog"
        aria-modal="true"
      >
        <div className="cstl-dialog-head">
          <h3 className="cstl-dialog-title">{title}</h3>
          <button type="button" className="cstl-dialog-close" onClick={() => close(null)} aria-label="Close">×</button>
        </div>
        <div className="cstl-dialog-body">
          {body && <div className="cstl-dialog-body-text">{body}</div>}
          {fields.map((f, i) => (
            <div key={f.name} className="cstl-field">
              <label className="cstl-field-label">{f.label}{f.required && <span className="cstl-field-req">*</span>}</label>
              {f.type === "textarea" ? (
                <textarea
                  ref={i === 0 ? firstRef : undefined}
                  className="cfg-textarea"
                  placeholder={f.placeholder || ""}
                  value={values[f.name] || ""}
                  onChange={(e) => set(f.name, e.target.value)}
                  rows={f.rows || 3}
                />
              ) : f.type === "select" ? (
                <select
                  ref={i === 0 ? firstRef : undefined}
                  className="cstl-select"
                  value={values[f.name] || ""}
                  onChange={(e) => set(f.name, e.target.value)}
                >
                  {(f.options || []).map((o) => (
                    <option key={o.value} value={o.value}>{o.label}</option>
                  ))}
                </select>
              ) : f.type === "agent" ? (
                <div className="cstl-agent-grid">
                  <button
                    type="button"
                    className={"cstl-agent-tile" + (values[f.name] === "" || values[f.name] == null ? " on" : "")}
                    onClick={() => set(f.name, "")}
                  >
                    <span className="cstl-agent-tile-avatar" style={{ background: "var(--bg-sunken)", color: "var(--text-muted)" }}>·</span>
                    <span className="cstl-agent-tile-label">unassigned</span>
                  </button>
                  {(f.options || []).map((opt) => (
                    <button
                      key={opt.value}
                      type="button"
                      className={"cstl-agent-tile" + (values[f.name] === opt.value ? " on" : "")}
                      onClick={() => set(f.name, opt.value)}
                    >
                      <window.Avatar who={opt.value} size={20} />
                      <span className="cstl-agent-tile-label">{opt.label}</span>
                    </button>
                  ))}
                </div>
              ) : (
                <input
                  ref={i === 0 ? firstRef : undefined}
                  className="cfg-input"
                  type={f.type || "text"}
                  placeholder={f.placeholder || ""}
                  value={values[f.name] || ""}
                  onChange={(e) => set(f.name, e.target.value)}
                  required={!!f.required}
                />
              )}
              {f.hint && <div className="cstl-field-hint">{f.hint}</div>}
            </div>
          ))}
        </div>
        <div className="cstl-dialog-foot">
          <button type="button" className="btn ghost" onClick={() => close(null)}>{cancelLabel}</button>
          <button
            type="submit"
            className={"btn " + (danger ? "danger" : "primary")}
            disabled={!canSubmit}
          >
            {submitLabel}
          </button>
        </div>
      </form>
    </div>
  );
}

function DialogHost() {
  const queue = useDialogQueue();
  if (queue.length === 0) return null;
  return (
    <>
      {queue.map(({ id, spec }) => (
        spec.kind === "confirm"
          ? <ConfirmDialog key={id} id={id} spec={spec} />
          : <FormDialog key={id} id={id} spec={spec} />
      ))}
    </>
  );
}

window.DialogHost = DialogHost;
