/* eslint-disable */
// ============================================================
// ADMIN — in-place "Edit configuration" panel for a single ActionPayload.
//
// Edits MergedParams (no per-role copies; the spec is one config per action).
// RBAC visibility is exposed as a separate per-role pill row.
//
// Pattern matches the spec: PUT /api/rbac/payload/{actionId}/config when
// user saves; toggling RBAC fires PUT /api/rbac/role/{role}/access.
// ============================================================

const { useState: useAd_S, useEffect: useAd_E, useMemo: useAd_M, useRef: useAd_R } = React;

// ---- Column editor row ----
const ColumnRow = ({ col, idx, total, onChange, onMove }) => (
  <div className="card-flat overflow-hidden">
    <div className="flex items-center gap-2 px-2.5 py-2" style={{ background: "var(--surface-2)", borderBottom: "1px solid var(--border)" }}>
      <span style={{ color: "var(--subtle)" }}><Icon name="grip" size={14} /></span>
      <Check checked={col.Visible} onChange={(v) => onChange({ ...col, Visible: v })} />
      <div className="flex-1 min-w-0">
        <div className="text-[13px] font-medium truncate" style={{ color: "var(--ink)" }}>{col.Label || col.PropertyName}</div>
        <div className="text-[10.5px] truncate font-mono" style={{ color: "var(--subtle)" }}>{col.PropertyName} · {col.DataType}</div>
      </div>
      <div className="flex items-center gap-0.5">
        <button disabled={idx === 0} onClick={() => onMove(idx, -1)} className="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-[var(--surface)] disabled:opacity-30" style={{ color: "var(--muted)" }}><Icon name="chevronUp" size={14} /></button>
        <button disabled={idx === total - 1} onClick={() => onMove(idx, 1)} className="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-[var(--surface)] disabled:opacity-30" style={{ color: "var(--muted)" }}><Icon name="chevronDown" size={14} /></button>
      </div>
    </div>
    <div className="grid grid-cols-2 gap-3 p-3">
      <Field label="Display label">
        <TextInput value={col.Label} onChange={(v) => onChange({ ...col, Label: v })} />
      </Field>
      <Field label="Width">
        <TextInput value={col.Width || ""} onChange={(v) => onChange({ ...col, Width: v })} placeholder="auto or 140px" />
      </Field>
      <Field label="Format" hint={col.DataType === "datetime" ? "e.g. {0:MMM d, yyyy}" : col.DataType === "int" ? "e.g. {0:#,##0}" : "Optional"} className="col-span-2">
        <TextInput value={col.Format || ""} onChange={(v) => onChange({ ...col, Format: v || null })} />
      </Field>
      <div className="col-span-2 flex flex-wrap gap-x-4 gap-y-1.5">
        <Check checked={col.Sortable}  onChange={(v) => onChange({ ...col, Sortable: v })}  label="Sortable" />
        <Check checked={col.Filterable} onChange={(v) => onChange({ ...col, Filterable: v })} label="Filterable" />
        <Check checked={col.Groupable} onChange={(v) => onChange({ ...col, Groupable: v })} label="Groupable" />
        <Check checked={col.ReadOnly === false} onChange={(v) => onChange({ ...col, ReadOnly: !v })} label="Editable inline" />
        {col.DataType === "string" && (
          <Check checked={!!col.IsHtml} onChange={(v) => onChange({ ...col, IsHtml: v })} label="Render HTML" />
        )}
      </div>
      {col.OptionSet && (
        <div className="col-span-2 flex items-center gap-2 text-[11.5px] py-1.5 px-2 rounded" style={{ background: "var(--surface-2)", color: "var(--muted)" }}>
          <Icon name="tag" size={11} />
          OptionSet: <span className="font-mono" style={{ color: "var(--ink-2)" }}>{col.OptionSet}</span>
          {col.Template && <><span style={{ color: "var(--faint)" }}>·</span> Template: <span className="font-mono" style={{ color: "var(--ink-2)" }}>{col.Template}</span></>}
        </div>
      )}
    </div>
  </div>
);

// ---- Collapsible section ----
const Section = ({ icon, title, subtitle, children, defaultOpen = true }) => {
  const [open, setOpen] = useAd_S(defaultOpen);
  return (
    <div className="card overflow-hidden">
      <button onClick={() => setOpen((v) => !v)} className="w-full flex items-center gap-3 px-4 py-3 hover:bg-[var(--surface-2)] text-left">
        <div className="h-7 w-7 inline-flex items-center justify-center rounded-md" style={{ background: "var(--primary-bg)", color: "var(--primary)" }}>
          <Icon name={icon} size={13} />
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-[13px] font-semibold" style={{ color: "var(--ink)" }}>{title}</div>
          {subtitle && <div className="text-[11.5px]" style={{ color: "var(--muted)" }}>{subtitle}</div>}
        </div>
        <Icon name={open ? "chevronUp" : "chevronDown"} size={16} style={{ color: "var(--subtle)" }} />
      </button>
      {open && <div className="p-4 border-t" style={{ borderColor: "var(--border)" }}>{children}</div>}
    </div>
  );
};

// ---- JSON panel ----
const JsonPanel = ({ value, onApply, onToast }) => {
  const [text, setText] = useAd_S(JSON.stringify(value, null, 2));
  const [dirty, setDirty] = useAd_S(false);
  const [error, setError] = useAd_S(null);

  useAd_E(() => { if (!dirty) setText(JSON.stringify(value, null, 2)); }, [value, dirty]);

  const tryApply = () => {
    try {
      const parsed = JSON.parse(text);
      onApply(parsed);
      setDirty(false);
      setError(null);
      onToast?.({ kind: "ok", text: "JSON applied" });
    } catch (e) { setError(e.message); onToast?.({ kind: "err", text: "Invalid JSON" }); }
  };
  const copy = async () => {
    try { await navigator.clipboard.writeText(text); onToast?.({ kind: "ok", text: "Copied" }); }
    catch { onToast?.({ kind: "err", text: "Copy failed" }); }
  };

  return (
    <div className="flex flex-col h-full min-h-0 rounded-xl overflow-hidden" style={{ background: "#0c1014", border: "1px solid var(--border)" }}>
      <div className="flex items-center gap-2 px-3 py-2 border-b" style={{ background: "#171b22", borderColor: "rgba(255,255,255,0.06)" }}>
        <Icon name="code" size={13} style={{ color: "#9095a3" }} />
        <span className="text-[12px] font-medium" style={{ color: "#d6d1c4" }}>MergedParams</span>
        {dirty && <span className="text-[11px]" style={{ color: "#f0c060" }}>• modified</span>}
        <div className="flex-1" />
        <button onClick={copy} className="inline-flex items-center gap-1 h-7 px-2 rounded text-[12px]" style={{ color: "#a0a4b0" }}>
          <Icon name="copy" size={11} /> Copy
        </button>
        <button onClick={tryApply} disabled={!dirty} className="inline-flex items-center gap-1 h-7 px-2.5 rounded text-[12px] font-medium" style={{ background: dirty ? "var(--primary)" : "rgba(255,255,255,0.06)", color: "white", opacity: dirty ? 1 : 0.4 }}>
          Apply
        </button>
      </div>
      <div className="flex-1 min-h-0 relative">
        <pre
          aria-hidden="true"
          className="absolute inset-0 m-0 p-3 text-[11.5px] font-mono leading-[1.55] overflow-auto scrollbar-thin pointer-events-none whitespace-pre-wrap break-words"
          style={{ color: "#d6d1c4" }}
          dangerouslySetInnerHTML={{ __html: highlightJson(text) }}
        />
        <textarea
          value={text}
          onChange={(e) => { setText(e.target.value); setDirty(true); setError(null); }}
          spellCheck="false"
          className="absolute inset-0 w-full h-full p-3 bg-transparent text-transparent caret-white font-mono text-[11.5px] leading-[1.55] resize-none outline-none scrollbar-thin whitespace-pre-wrap break-words"
        />
      </div>
      {error && (
        <div className="px-3 py-2 text-[11px] flex items-center gap-2" style={{ background: "rgba(185,28,28,0.15)", borderTop: "1px solid rgba(185,28,28,0.4)", color: "#f5a3a3" }}>
          <Icon name="alert" size={11} /> {error}
        </div>
      )}
    </div>
  );
};

// ============================================================
// ROLE ACCESS PILL ROW — single-action RBAC
// ============================================================
const RoleAccessPill = ({ actionId, rbac, setRbac, onToast }) => {
  return (
    <div className="flex items-center flex-wrap gap-2 p-3 rounded-lg" style={{ background: "var(--surface-2)", border: "1px solid var(--border)" }}>
      <div className="flex items-center gap-2 mr-1">
        <Icon name="shield" size={13} style={{ color: "var(--primary)" }} />
        <span className="text-[11.5px] uppercase tracking-wider font-semibold" style={{ color: "var(--muted)" }}>RBAC · who can see this</span>
      </div>
      {ROLES.map((r) => {
        const has = rbac[r.id]?.has(actionId);
        return (
          <button
            key={r.id}
            onClick={async () => {
              const next = { ...rbac, [r.id]: new Set(rbac[r.id] || []) };
              if (has) next[r.id].delete(actionId); else next[r.id].add(actionId);
              setRbac(next);
              await mockApi.putRoleAccess(r.id, actionId, !has);
              onToast({ kind: "ok", text: `${has ? "Hid" : "Showed"} action ${actionId} for ${r.id}` });
            }}
            className="inline-flex items-center gap-1.5 px-2 h-7 rounded-md text-[12px] font-medium transition-all"
            style={{
              background: has ? "var(--primary-bg)" : "var(--surface)",
              color: has ? "var(--primary)" : "var(--muted)",
              border: `1px solid ${has ? "var(--primary-ring)" : "var(--border)"}`,
            }}
          >
            <Icon name={has ? "eye" : "eyeOff"} size={11} />
            {r.id}
          </button>
        );
      })}
    </div>
  );
};

// ============================================================
// ADMIN EDITOR — the full inline editor surface
// ============================================================
const AdminEditor = ({ action, onChange, onToast, rbac, setRbac }) => {
  const mp = action.MergedParams;
  const setMP = (patch) => onChange({ ...action, MergedParams: { ...mp, ...patch } });
  const setColAt = (idx, next) => {
    const cols = [...mp.Columns];
    cols[idx] = next;
    setMP({ Columns: cols });
  };
  const moveCol = (idx, dir) => {
    const cols = [...mp.Columns].sort((a, b) => a.ColOrder - b.ColOrder);
    const target = idx + dir;
    if (target < 0 || target >= cols.length) return;
    const tmp = cols[idx].ColOrder;
    cols[idx].ColOrder = cols[target].ColOrder;
    cols[target].ColOrder = tmp;
    setMP({ Columns: cols.sort((a, b) => a.ColOrder - b.ColOrder) });
  };

  const sortedCols = useAd_M(
    () => [...mp.Columns].sort((a, b) => a.ColOrder - b.ColOrder),
    [mp.Columns]
  );

  const visibleCount = mp.Columns.filter((c) => c.Visible !== false).length;

  return (
    <div className="space-y-3">
      <RoleAccessPill actionId={action.ActionId} rbac={rbac} setRbac={setRbac} onToast={onToast} />

      <Section icon="layout" title="Page" subtitle="Action title shown above the grid">
        <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
          <Field label="Action title">
            <TextInput value={action.ActionTitle || ""} onChange={(v) => onChange({ ...action, ActionTitle: v })} />
          </Field>
          <Field label="Action name (internal)">
            <TextInput value={action.ActionName || ""} onChange={(v) => onChange({ ...action, ActionName: v })} />
          </Field>
        </div>
      </Section>

      <Section icon="columns" title="Columns" subtitle={`${visibleCount} of ${mp.Columns.length} visible · ↑↓ to reorder`}>
        <div className="space-y-2">
          {sortedCols.map((c, idx) => (
            <ColumnRow
              key={c.PropertyName}
              col={c}
              idx={idx}
              total={sortedCols.length}
              onChange={(next) => setColAt(mp.Columns.findIndex((x) => x.PropertyName === c.PropertyName), next)}
              onMove={moveCol}
            />
          ))}
        </div>
      </Section>

      <Section icon="arrowUpDown" title="Default sort" subtitle="Initial sort applied when the grid loads">
        <div className="grid grid-cols-1 sm:grid-cols-[1fr_140px] gap-3">
          <Field label="Column">
            <Select
              value={mp.Sort?.[0]?.PropertyName || ""}
              onChange={(v) => setMP({ Sort: v ? [{ PropertyName: v, ColOrder: "10", SortDirection: mp.Sort?.[0]?.SortDirection || "1", Grouping: "0" }] : [] })}
              options={[{ value: "", label: "(none)" }, ...mp.Columns.map((c) => ({ value: c.PropertyName, label: c.Label }))]}
            />
          </Field>
          <Field label="Direction">
            <Select
              value={mp.Sort?.[0]?.SortDirection || "1"}
              onChange={(v) => { const s = mp.Sort?.[0]; if (!s) return; setMP({ Sort: [{ ...s, SortDirection: v }] }); }}
              options={[{ value: "1", label: "Ascending" }, { value: "0", label: "Descending" }]}
            />
          </Field>
        </div>
      </Section>

      <Section icon="bookOpen" title="Pagination" subtitle="Page size & enabled state">
        <div className="grid grid-cols-1 sm:grid-cols-3 gap-3 items-end">
          <div className="flex items-center justify-between rounded-md px-3 py-2 sm:col-span-2" style={{ background: "var(--surface-2)" }}>
            <span className="text-[13px]" style={{ color: "var(--ink-2)" }}>Enable pagination</span>
            <Toggle checked={mp.Pagination?.Enabled !== false} onChange={(v) => setMP({ Pagination: { ...mp.Pagination, Enabled: v } })} />
          </div>
          <Field label="Page size">
            <NumberInput value={mp.Pagination?.PageSize ?? 10} min={1} onChange={(v) => setMP({ Pagination: { ...mp.Pagination, PageSize: Math.max(1, Number(v) || 1) } })} />
          </Field>
        </div>
      </Section>

      <Section icon="link" title="Detail action" subtitle="actionId opened on row double-click">
        <Select
          value={mp.DetailActionId || ""}
          onChange={(v) => setMP({ DetailActionId: v ? Number(v) : null })}
          options={[
            { value: "", label: "(none — no master-detail)" },
            ...Object.values(mockApi.state.getAllActions()).filter((a) => a.PartialView === "Detail").map((a) => ({ value: a.ActionId, label: `${a.ActionId} · ${a.ActionTitle || a.ActionName}` })),
          ]}
        />
      </Section>
    </div>
  );
};

Object.assign(window, { AdminEditor, RoleAccessPill, JsonPanel, Section });
