/* page-gifts.jsx — Gifts catalog module (03-ui §2). IIFE-scoped; exports via window.
 * Deps: helpers.jsx — gift.create / gift.delete RBAC keys (landed by data agent) + _hasRbac, _go,
 *                      _notAuthorised, _useRemarks, T_MUTED
 *       mock-data.js — GIFT_ITEMS, GIFT_ITEM_BY_ID, USER_GIFTS (landed concurrently by data agent),
 *                      SB2_COUNTRY_BY_ID (currency_code), CUSTOM_OPTIONS (gift_type), SB3_AREAS, SB3_OUTLETS
 *       StatusPill kind: "gift" (active / archived) — DS tones added concurrently.
 *
 * "Draft" = UNREFERENCED item (no Exchange purchase): purchase_count === 0. There is NO draft status
 * (status is active|archived only). Hard-delete (GA) + the bulk Delete subset gate on purchase_count===0;
 * referenced items can only be archived. [Bulk rule, 03-ui §2]
 *
 * AM/OM receive only { role } (no scope prop). Their country resolves to PH (the single active
 * franchise country); they are strictly read-only — no checkboxes, bulk, create or edit.
 */
(function(){
const { useState, useMemo } = React;

// ── Cross-agent global readers (data lands concurrently — guard every read) ──
const _giftItems = () => (typeof GIFT_ITEMS !== "undefined") ? GIFT_ITEMS : (window.GIFT_ITEMS || []);
const _userGifts = () => (typeof USER_GIFTS !== "undefined") ? USER_GIFTS : (window.USER_GIFTS || []);
const _customOptions = () => (typeof CUSTOM_OPTIONS !== "undefined") ? CUSTOM_OPTIONS : (window.CUSTOM_OPTIONS || []);
const _countryById = () => (typeof SB2_COUNTRY_BY_ID !== "undefined") ? SB2_COUNTRY_BY_ID : (window.SB2_COUNTRY_BY_ID || {});

// ── Currency formatter (per DATA CONTRACT — no _money helper) ──
const _fmtMoney = (n, country_id) => {
  const c = _countryById()[country_id] || {};
  const code = c.currency_code || "";
  return `${code} ${Number(n || 0).toLocaleString()}`;
};

// ── Country flag from id ──
const _flagOf = (country_id) => (_countryById()[country_id] || {}).flag || "🏳️";

// ── gift_type label from CUSTOM_OPTIONS id ──
const _giftTypeLabel = (id) => {
  if (!id) return "—";
  const co = _customOptions().find(o => o.option_type === "gift_type" && o.id === id);
  return co ? co.label : id;
};

// ── purchase_count for an item (referenced by Exchanges) ──
const _purchaseCount = (giftItemId) => _userGifts().filter(x => x.gift_item_id === giftItemId).length;

// ── GeoScope data builder (canonical — mirrors page-rewards.jsx) ──
const _geoData = () => ({
  countries: (typeof SB2_COUNTRIES !== "undefined" ? SB2_COUNTRIES : (window.SB2_COUNTRIES || []))
    .map(c => ({ value: c.country_id, label: `${c.flag} ${c.country_name}` })),
  areas: (typeof SB3_AREAS !== "undefined" ? SB3_AREAS : (window.SB3_AREAS || []))
    .map(a => ({ value: a.id, label: a.name, country_id: a.country_id })),
  outlets: (typeof SB3_OUTLETS !== "undefined" ? SB3_OUTLETS : (window.SB3_OUTLETS || []))
    .map(o => ({ value: o.id, label: o.location, area_id: o.area_id })),
});

// ── gift_type options for the filter + form Select ──
const _giftTypeOpts = (withAll) => {
  const types = _customOptions()
    .filter(o => o.option_type === "gift_type" && o.scope === "ALL")
    .map(o => ({ value: o.id, label: o.label }));
  return withAll ? [{ value: "", label: "All types" }, ...types] : types;
};

const STATUS_FILTER_OPTS = [
  { value: "",         label: "All statuses" },
  { value: "draft",    label: "Draft"        },
  { value: "active",   label: "Active"       },
  { value: "inactive", label: "Inactive"     },
];
const STATUS_FORM_OPTS = [
  { value: "draft",    label: "Draft"    },
  { value: "active",   label: "Active"   },
  { value: "inactive", label: "Inactive" },
];
const COUNTRY_FORM_OPTS = [
  { value: "PH", label: "🇵🇭 Philippines" },
  { value: "SG", label: "🇸🇬 Singapore" },
  { value: "ID", label: "🇮🇩 Indonesia" },
  { value: "TH", label: "🇹🇭 Thailand" },
];

// ── Empty draft for create ──
const _emptyGift = (scopeCountry) => ({
  id: null,
  name: "",
  gift_type_id: "",
  value: "",
  country_id: scopeCountry || "PH",
  status: "draft",
  gift_remarks: [],
});

// ── Remarks sub-block — keeps _useRemarks (a hook) at a stable top level, not inside drawer JSX ──
function GiftRemarks({ giftId, seed, role, tz }) {
  const [remarks, addRemark, editRemark, deleteRemark] = _useRemarks("gift", giftId, seed || []);
  return (
    <RemarksSection
      entityType="gift"
      entityId={giftId}
      remarks={remarks}
      onAdd={addRemark}
      onEdit={editRemark}
      onDelete={deleteRemark}
      role={role}
      tz={tz}
      currentUser="you"
    />
  );
}

// ─────────────────────────────────────────────────────────────────────────────
/**
 * @spec GA-gifts · CM-gifts · AM-gifts · OM-gifts — Gifts catalog (role-parameterised)
 * One component for all 4 tiers. GA/CM manage (create/edit/archive/bulk); AM/OM read-only.
 */
function GiftItemsList({ role = "GA" }) {
  if (!["GA", "CM", "AM", "OM"].includes(role)) return _notAuthorised;

  const isGA = role === "GA";
  const isCM = role === "CM";
  const isAM = role === "AM";
  const isOM = role === "OM";

  // AM/OM resolve to PH (single active franchise country); CM pinned to PH.
  const scopeCountry = "PH";
  const canManage = _hasRbac(role, "gift.create");   // GA, CM
  const canHardDelete = _hasRbac(role, "gift.delete"); // GA only
  const tz = (_countryById()[scopeCountry] || {}).timezone || "Asia/Manila";

  // ── Mutable store — drawer create/edit/archive apply here ──
  const [items, setItems] = useState(() => _giftItems().map(g => ({ ...g })));

  // ── filter + pagination state ──
  const [searchQuery, setSearchQuery] = useState("");
  const [filters, setFilters]         = useState({});
  const [advFilters, setAdvFilters]   = useState({});
  const [page, setPage]               = useState(1);
  const [pageSize, setPageSize]       = useState(20);

  // ── selection (GA/CM only) ──
  const [sel, setSel] = useState({});

  // ── drawer state ──
  const [drawerFor, setDrawerFor] = useState(null);
  const [mode, setMode]           = useState("read"); // read | edit | create
  const [draft, setDraft]         = useState(null);

  // ── modal state ──
  const [deleteConfirm, setDeleteConfirm] = useState(null); // { kind:"single"|"bulk", id?, name?, ids? }

  // ── toast ──
  const [toast, setToast] = useState(null);
  const fireToast = (msg) => { setToast(msg); setTimeout(() => setToast(null), 2400); };

  // ── row scope ──
  const scopedItems = useMemo(() => {
    if (isGA) return items;
    return items.filter(g => g.country_id === scopeCountry);
  }, [items, role]);

  // ── filtered rows ──
  const rows = useMemo(() => {
    let r = scopedItems;
    if (searchQuery) {
      const q = searchQuery.toLowerCase();
      r = r.filter(g => (g.name || "").toLowerCase().includes(q));
    }
    if (filters.status)       r = r.filter(g => g.status === filters.status);
    if (filters.gift_type_id) r = r.filter(g => g.gift_type_id === filters.gift_type_id);
    if (advFilters.geo) {
      const { countries: gc } = advFilters.geo || {};
      if (gc && gc.length > 0) r = r.filter(g => gc.includes(g.country_id));
    }
    return r;
  }, [scopedItems, searchQuery, filters, advFilters]);

  const totalPages  = Math.max(1, Math.ceil(rows.length / pageSize));
  const visibleRows = rows.slice((page - 1) * pageSize, page * pageSize);

  // ── drawer helpers ──
  const drawerRow = drawerFor ? items.find(g => g.id === drawerFor) || null : null;
  const isCreate  = mode === "create";
  const isEdit    = mode === "edit";
  const isForm    = isEdit || isCreate;

  const openRead    = (row) => { setDrawerFor(row.id); setMode("read"); setDraft(null); };
  const closeDrawer = () => { setDrawerFor(null); setMode("read"); setDraft(null); };
  const startEdit   = () => { setDraft({ ...drawerRow }); setMode("edit"); };
  const startCreate = () => { setDrawerFor(null); setDraft(_emptyGift(scopeCountry)); setMode("create"); };
  const setD = (k, v) => setDraft(d => ({ ...d, [k]: v }));

  // ── save ──
  const saveForm = () => {
    if (!draft || !draft.name.trim()) return;
    const rec = { ...draft, value: Number(draft.value) || 0 };
    if (isCM) rec.country_id = "PH"; // CM locked to PH
    if (isCreate) {
      const id = `gi_NEW_${Date.now()}`;
      setItems(ps => [{ ...rec, id, gift_remarks: rec.gift_remarks || [] }, ...ps]);
      setDrawerFor(id);
      fireToast("Gift item created");
    } else {
      setItems(ps => ps.map(g => g.id === rec.id ? { ...g, ...rec } : g));
      fireToast("Gift item saved");
    }
    setMode("read");
    setDraft(null);
  };

  // ── selection (GA/CM only) ──
  const selectedIds = Object.keys(sel).filter(k => k !== "all" && sel[k]);
  const onToggleSelected = (id) => {
    if (id === "all") {
      const allOn = visibleRows.length > 0 && visibleRows.every(r => sel[r.id]);
      const next = {};
      if (!allOn) visibleRows.forEach(r => { next[r.id] = true; });
      setSel(next);
    } else {
      setSel(s => ({ ...s, [id]: !s[id] }));
    }
  };
  const selRows = items.filter(g => selectedIds.includes(g.id));
  const deletableSel = selRows.filter(g => _purchaseCount(g.id) === 0); // unreferenced "drafts"

  // ── bulk actions ──
  const doArchive = () => {
    const ids = new Set(selectedIds);
    setItems(ps => ps.map(g => ids.has(g.id) ? { ...g, status: "inactive" } : g));
    fireToast(`Archived ${selectedIds.length} gift item${selectedIds.length === 1 ? "" : "s"}.`);
    setSel({});
  };
  const doBulkDelete = () => {
    const ids = new Set(deletableSel.map(g => g.id));
    setItems(ps => ps.filter(g => !ids.has(g.id)));
    fireToast(`Deleted ${ids.size} gift item${ids.size === 1 ? "" : "s"}.`);
    setSel({});
    setDeleteConfirm(null);
  };
  const doExport = () => fireToast(`Exported ${selectedIds.length} gift item${selectedIds.length === 1 ? "" : "s"}.`);

  const bulkActions = (
    <>
      {/* CM = Archive only; GA = Archive · Delete (drafts) · Export */}
      <Btn variant="secondary" size="sm" onClick={doArchive}>Archive</Btn>
      {isGA && canHardDelete && deletableSel.length > 0 && (
        <Btn variant="danger" size="sm" onClick={() => setDeleteConfirm({ kind: "bulk", ids: deletableSel.map(g => g.id) })}>
          Delete
        </Btn>
      )}
      {isGA && <Btn variant="secondary" size="sm" onClick={doExport}>Export</Btn>}
    </>
  );

  // ── single drawer delete (GA only, unreferenced item) ──
  const executeDelete = () => {
    if (!deleteConfirm) return;
    if (deleteConfirm.kind === "bulk") return doBulkDelete();
    setItems(ps => ps.filter(g => g.id !== deleteConfirm.id));
    fireToast("Gift item deleted");
    setDeleteConfirm(null);
    closeDrawer();
  };

  // ── per-role description ──
  const desc = isGA ? "Giftable items & types."
    : isCM ? "Your country's gift items."
    : isAM ? "Your area's gift items."
    : "Gift items at your outlet.";

  // ── filter config ──
  const geo = _geoData();
  const primaryFilter = [
    { key: "status",       label: "Status", options: STATUS_FILTER_OPTS },
    { key: "gift_type_id", label: "Type",   options: _giftTypeOpts(true) },
  ];
  const advancedFilters = isOM ? [] : [
    { key: "geo", kind: "geoscope", label: "Network scope", role,
      countries: geo.countries, areas: geo.areas, outlets: geo.outlets },
  ];

  // ── columns ──
  const colChevron = { label: "", width: 36, render: () => <span style={{ color: "var(--forest)" }}>{Ic.chevR(16)}</span> };
  const columns = [
    { label: "Name",   sortable: true, sortKey: "name", render: g => <span style={{ ...T.primary() }}>{g.name}</span> },
    { label: "Type",   width: 160, sortable: true, sortKey: "gift_type_id", render: g => <span style={T_MUTED}>{_giftTypeLabel(g.gift_type_id)}</span> },
    { label: "Value",  width: 130, sortable: true, sortKey: "value", render: g => <span style={T_MUTED}>{_fmtMoney(g.value, g.country_id)}</span> },
    { label: "Status", width: 120, sortable: false, render: g => <StatusPill status={g.status} kind="gift"/> },
    { label: "Country", width: 110, sortable: true, sortKey: "country_id", render: g => <CountryChip flag={_flagOf(g.country_id)} code={g.country_id}/> },
    colChevron,
  ];

  // ── drawer form (create + edit) ──
  const formContent = draft && (
    <>
      <FormSection title="General">
        <Field label="Name" required>
          <Input value={draft.name} onChange={v => setD("name", v)} placeholder="e.g. Free signature bowl"/>
        </Field>
        <Field label="Type" required>
          <Select value={draft.gift_type_id || ""} onChange={v => setD("gift_type_id", v)}
            options={[{ value: "", label: "Choose type" }, ..._giftTypeOpts(false)]}/>
        </Field>
        <Field label="Value" required hint="Face value in the item's country currency.">
          <Input type="number" value={draft.value || ""} onChange={v => setD("value", v)} placeholder="e.g. 250"/>
        </Field>
      </FormSection>

      <FormSection title="Scope">
        <Field label="Country" hint={isCM ? "Locked to your country." : undefined}>
          <Select value={draft.country_id || "PH"} onChange={v => setD("country_id", v)}
            options={COUNTRY_FORM_OPTS} disabled={isCM}/>
        </Field>
        <Field label="Status">
          <Select value={draft.status} onChange={v => setD("status", v)} options={STATUS_FORM_OPTS}/>
        </Field>
      </FormSection>
    </>
  );

  // ── read mode drawer ──
  const readContent = !isForm && drawerRow && (() => {
    const g = drawerRow;
    const pc = _purchaseCount(g.id);
    return (
      <>
        <FormSection title="General">
          <KeyValueGrid items={[
            { label: "Name",  value: g.name },
            { label: "Type",  value: _giftTypeLabel(g.gift_type_id) },
            { label: "Value", value: _fmtMoney(g.value, g.country_id) },
          ]}/>
        </FormSection>

        <FormSection title="Scope">
          <KeyValueGrid items={[
            { label: "Country", value: <CountryChip flag={_flagOf(g.country_id)} code={g.country_id}/> },
            { label: "Status",  value: <StatusPill status={g.status} kind="gift"/> },
          ]}/>
        </FormSection>

        <FormSection title="Activity">
          <KeyValueGrid items={[
            { label: "Exchanges", value: pc.toLocaleString() },
          ]}/>
          <Btn variant="ghost" onClick={() => _go(`${role.toLowerCase()}-purchases`, { gift_item_id: g.id })}>
            View exchanges
          </Btn>
        </FormSection>

        {/* RemarksSection renders its own "Remarks" header — render direct, never inside a titled FormSection (canon: page-customers/page-loyalty) */}
        <GiftRemarks giftId={g.id} seed={g.gift_remarks} role={role} tz={tz}/>

        {canManage && (
          <DeleteSection
            entityLabel="gift item"
            soft={g.status !== "draft"}
            note={g.status === "draft"
              ? "Permanently delete this draft gift item. Blocked once it has been exchanged."
              : "Decommission (soft-delete) this gift item. Retained for historical exchanges. GA-only, blocked if it has exchanges."}
            gate={_canDelete(role, { status: g.status, isReferenced: pc > 0, rbacOk: canManage })}
            confirmBody={<div>{g.status === "draft" ? "Permanently delete" : "Decommission"} <strong>{g.name}</strong>? Writes to <strong>audit_logs</strong>.</div>}
            onDelete={() => { setItems(ps => ps.filter(x => x.id !== g.id)); closeDrawer(); }}
          />
        )}
      </>
    );
  })();

  // ── drawer actions ──
  const canDeleteDrawer = isGA && canHardDelete && drawerRow && _purchaseCount(drawerRow.id) === 0;
  const drawerActions = isForm ? (
    <>
      <Btn variant="secondary" onClick={() => { if (isCreate) closeDrawer(); else { setMode("read"); setDraft(null); } }}>Cancel</Btn>
      <Btn variant="primary" onClick={saveForm} disabled={!draft || !draft.name.trim()}>
        {isCreate ? "Create gift item" : "Save"}
      </Btn>
    </>
  ) : (
    <>
      <Btn variant="secondary" onClick={closeDrawer}>Close</Btn>
      {canManage && drawerRow && <Btn variant="primary" onClick={startEdit}>Edit</Btn>}
    </>
  );

  const drawerTitle = isCreate ? "New gift" : (drawerRow ? drawerRow.name : "");

  return (
    <div className="page-inner">
      <PageHead
        title="Gifts"
        description={desc}
        actions={
          <>
            <ExportButton role={role} variant="secondary" onClick={() => fireToast("Exporting gift items…")}/>
            {canManage && <Btn variant="primary" onClick={startCreate}>New gift</Btn>}
          </>
        }
      />

      <FilterBar
        primaryFilter={primaryFilter}
        primaryValue={filters}
        onPrimaryChange={next => { setFilters(f => ({ ...f, ...next })); setPage(1); }}
        advancedFilters={advancedFilters}
        advancedValues={advFilters}
        onAdvancedChange={(k, v) => { setAdvFilters(f => ({ ...f, [k]: v })); setPage(1); }}
        onAdvancedReset={() => { setAdvFilters({}); setPage(1); }}
        onReset={() => { setFilters({}); setAdvFilters({}); setSearchQuery(""); setPage(1); }}
        search={searchQuery}
        onSearch={q => { setSearchQuery(q); setPage(1); }}
        searchPlaceholder="Search gift items…"
      />

      {canManage && <BulkBar selectedCount={selectedIds.length} onDeselect={() => setSel({})} actions={bulkActions}/>}

      <Table
        columns={columns}
        rows={visibleRows}
        onRow={openRead}
        selected={canManage ? sel : undefined}
        onToggleSelected={canManage ? onToggleSelected : undefined}
        emptyText="No gift items match these filters."
      />

      <TableFooter
        page={page}
        totalPages={totalPages}
        onPage={setPage}
        count={pageSize}
        onCountChange={c => { setPageSize(c); setPage(1); }}
      />

      {/* ── Detail Drawer (read | edit | create) ── */}
      <DetailDrawer
        open={isCreate || !!drawerFor}
        onClose={closeDrawer}
        title={drawerTitle}
        actions={drawerActions}
        width={700}
      >
        {isForm && formContent}
        {!isForm && drawerFor && readContent}
      </DetailDrawer>

      {/* ── Delete Confirm (GA only, unreferenced items) ── */}
      {deleteConfirm && (
        <ConfirmModal
          open
          destructive
          title={deleteConfirm.kind === "bulk"
            ? `Delete ${deleteConfirm.ids.length} gift item${deleteConfirm.ids.length === 1 ? "" : "s"}?`
            : "Delete this gift item?"}
          body={deleteConfirm.kind === "bulk"
            ? <p style={T_MUTED}>Permanently delete {deleteConfirm.ids.length} unreferenced gift item{deleteConfirm.ids.length === 1 ? "" : "s"}. This cannot be undone.</p>
            : <p style={T_MUTED}>Permanently delete <strong>{deleteConfirm.name}</strong>. This cannot be undone.</p>}
          confirmLabel="Delete"
          onConfirm={executeDelete}
          onCancel={() => setDeleteConfirm(null)}
        />
      )}

      {toast && <Toast message={toast}/>}
    </div>
  );
}

Object.assign(window, { GiftItemsList });
})();
