// Shared in-memory store so Forms + Budget + Tasks stay in sync.
// Pub/sub pattern: components useStore() hook re-renders when any data changes.

(function () {
  const listeners = new Set();
  let safs = [];     // flattened SAF list across all teams
  let forms = [];    // non-SAF forms

  function notify() { listeners.forEach(fn => { try { fn(); } catch (e) {} }); }

  function init() {
    // Flatten TRANSACTIONS into a single SAF list
    const all = [];
    Object.entries(window.AppData.TRANSACTIONS).forEach(([teamId, list]) => {
      list.forEach(rec => {
        all.push({ ...rec, teamId: rec.teamId || teamId });
      });
    });
    // Sort newest first
    all.sort((a, b) => (b.submittedAt || '').localeCompare(a.submittedAt || ''));
    safs = all;
    forms = (window.AppData.FORMS || []).slice();
  }

  function getSAFs(teamId) {
    return teamId ? safs.filter(s => s.teamId === teamId) : safs;
  }

  function getForms() { return forms.slice(); }

  // Unified feed for the Forms page: SAFs appear as forms too.
  function getAllFormEntries(teamId) {
    const safEntries = (teamId ? safs.filter(s => s.teamId === teamId) : safs).map(safToFormEntry);
    const regular = teamId ? forms.filter(f => f.teamId === teamId) : forms;
    const merged = [...safEntries, ...regular];
    merged.sort((a, b) => (b.submittedAt || '').localeCompare(a.submittedAt || ''));
    return merged;
  }

  function safToFormEntry(saf) {
    // Map SAF status → form status
    let status;
    if (saf.status === 'posted') status = 'approved';
    else if (saf.status === 'val-confirmed' || saf.status === 'stoney-signed') status = 'review';
    else if (saf.status === 'returned') status = 'returned';
    else if (saf.status === 'paid') status = 'approved';
    else if (saf.status === 'approved') status = 'review';
    else status = 'submitted';

    const wf = saf.workflow || {};
    return {
      id: 'saf::' + saf.id,
      safId: saf.id,
      teamId: saf.teamId,
      team: window.AppData.TEAMS.find(t => t.id === saf.teamId)?.name || saf.team || '—',
      type: 'saf',
      isSAF: true,
      detail: `${saf.vendor?.name || saf.desc} · $${(saf.amount || 0).toLocaleString()}`,
      status,
      saf,
      submittedBy: `${saf.officer?.name || 'Officer'} · ${saf.officer?.position || ''}`,
      submittedAt: saf.submittedAt || saf.date,
      reviewer: wf.posted?.by || wf.valConfirmed?.by || wf.stoneySigned?.by || null,
      reviewedAt: (wf.posted?.at || wf.valConfirmed?.at || wf.stoneySigned?.at || '').slice(0, 10) || null,
    };
  }

  function addSAF(rec) {
    const teamId = rec.teamId;
    const id = rec.id || `${teamId}-new-${Date.now()}`;
    const full = {
      ...rec,
      id,
      teamId,
      status: rec.status || 'submitted',
      workflow: rec.workflow || {
        submitted: { at: rec.submittedAt || new Date().toISOString(), by: rec.officer?.name || 'Officer' },
        stoneySigned: null,
        valConfirmed: null,
        posted: null,
        returned: null,
      },
      submittedAt: rec.submittedAt || new Date().toISOString(),
    };
    safs = [full, ...safs];
    // Also push into TRANSACTIONS by teamId for legacy reads
    if (!window.AppData.TRANSACTIONS[teamId]) window.AppData.TRANSACTIONS[teamId] = [];
    window.AppData.TRANSACTIONS[teamId] = [full, ...window.AppData.TRANSACTIONS[teamId]];
    notify();
    return full;
  }

  function updateSAF(safId, patch) {
    safs = safs.map(s => s.id === safId ? { ...s, ...patch } : s);
    // mirror to TRANSACTIONS
    Object.keys(window.AppData.TRANSACTIONS).forEach(tid => {
      window.AppData.TRANSACTIONS[tid] = window.AppData.TRANSACTIONS[tid].map(
        s => s.id === safId ? { ...s, ...patch } : s
      );
    });
    notify();
  }

  function advanceCheck(safId, next, actor) {
    const saf = safs.find(s => s.id === safId);
    if (!saf) return;
    const now = new Date().toISOString();
    const check = saf.check || {};
    let number = check.number;
    if (next === 'requested' && !number) {
      number = '20' + String(2600 + Math.floor(Math.random() * 400));
    }
    updateSAF(safId, { check: { status: next, at: now, by: actor || 'Staff', number } });
  }

  function advanceSAF(safId, next, actor) {
    const now = new Date().toISOString();
    const saf = safs.find(s => s.id === safId);
    if (!saf) return;
    const wf = { ...(saf.workflow || {}) };
    if (next === 'stoney-signed') wf.stoneySigned = { at: now, by: actor };
    else if (next === 'val-confirmed') wf.valConfirmed = { at: now, by: actor };
    else if (next === 'posted') wf.posted = { at: now, by: actor };
    else if (next === 'returned') wf.returned = { at: now, by: actor, reason: 'Returned by ' + actor };
    updateSAF(safId, { status: next, workflow: wf });
  }

  function addForm(rec) {
    const full = {
      id: rec.id || 'f-new-' + Date.now(),
      ...rec,
      submittedAt: rec.submittedAt || new Date().toISOString().slice(0, 10),
    };
    forms = [full, ...forms];
    notify();
    return full;
  }

  function updateForm(id, patch) {
    forms = forms.map(f => f.id === id ? { ...f, ...patch } : f);
    notify();
  }

  function subscribe(fn) {
    listeners.add(fn);
    return () => listeners.delete(fn);
  }

  // React hook
  function useStore() {
    const [, setTick] = React.useState(0);
    React.useEffect(() => {
      const unsub = subscribe(() => setTick(t => t + 1));
      return unsub;
    }, []);
    return window.AppStore;
  }

  // Hot init
  init();

  window.AppStore = {
    init, getSAFs, getForms, getAllFormEntries,
    addSAF, updateSAF, advanceSAF, advanceCheck,
    addForm, updateForm,
    subscribe, useStore,
    safToFormEntry,
  };
})();
