// ---------- Daily expenses + outlet transfers · 4 boutiques + Usine · week rollup · CSV export ----------
function isoToday() {
  return new Date().toISOString().slice(0, 10);
}

function isoWeekDays(endDateStr) {
  const end = new Date(endDateStr + 'T12:00:00');
  const out = [];
  for (let i = 6; i >= 0; i--) {
    const d = new Date(end);
    d.setDate(end.getDate() - i);
    out.push(d.toISOString().slice(0, 10));
  }
  return out;
}

function parseNum(s) {
  const n = parseFloat(String(s || '').replace(',', '.'));
  return Number.isFinite(n) ? n : 0;
}

/** Ensure day + location payload exists inside map (mutates map) */
function ensureLocPayload(map, dateStr, locId) {
  if (!map[dateStr]) map[dateStr] = {};
  if (!map[dateStr][locId]) {
    map[dateStr][locId] = {
      expenseLines: [{ label: '', amount: '' }],
      payrollPeople: '',
      payrollAmount: '',
      cupRows: [
        { id: 'cr1', product: 'ice', label: 'Ice · small · 250 F', unitPrice: 250, qty: '' },
        { id: 'cr2', product: 'ice', label: 'Ice · cup · 500 F', unitPrice: 500, qty: '' },
        { id: 'cr3', product: 'yogurt', label: 'Yogurt cup', unitPrice: 500, qty: '' },
      ],
      transferIce250: '',
      transferIce500: '',
      transferYogurt: '',
    };
  }
  return map[dateStr][locId];
}

function cupRevenue(rows) {
  let t = 0;
  (rows || []).forEach((r) => {
    t += parseNum(r.unitPrice) * parseNum(r.qty);
  });
  return Math.round(t);
}

function expenseTotal(lines, payrollFcfa) {
  let e = payrollFcfa;
  (lines || []).forEach((l) => {
    e += parseNum(l.amount);
  });
  return Math.round(e);
}

function ExpensesOutlet({ role }) {
  const { t } = useT();
  const [tick, setTick] = React.useState(0);
  const bump = () => setTick((x) => x + 1);

  React.useEffect(() => {
    const h = () => bump();
    window.addEventListener('gh-admin-data', h);
    return () => window.removeEventListener('gh-admin-data', h);
  }, []);

  const locs = window.OUTLET_LOCATIONS || [];
  const [dateStr, setDateStr] = React.useState(isoToday());
  const [activeLoc, setActiveLoc] = React.useState(locs[0]?.id || 'loc_nassara');
  const [draft, setDraft] = React.useState(null);
  const [saveStatus, setSaveStatus] = React.useState('idle'); // 'idle' | 'unsaved' | 'saved'

  React.useEffect(() => { setDraft(null); setSaveStatus('idle'); }, [dateStr, activeLoc]);

  const today = isoToday();
  const isPastDay = dateStr < today;
  const canEdit = role === 'boss' || (!isPastDay && role === 'accountant');

  const map = __getDailyExpensesMap();

  React.useEffect(() => {
    if (!canEdit) return;
    const m = JSON.parse(JSON.stringify(__getDailyExpensesMap()));
    let changed = false;
    (window.OUTLET_LOCATIONS || []).forEach((L) => {
      if (!m[dateStr] || !m[dateStr][L.id]) {
        ensureLocPayload(m, dateStr, L.id);
        changed = true;
      }
    });
    if (changed) __saveDailyExpensesMap(m);
  }, [dateStr, canEdit]);

  const stageChange = (updater) => {
    if (!canEdit) return;
    const base = draft !== null ? draft : JSON.parse(JSON.stringify(__getDailyExpensesMap()));
    const next = JSON.parse(JSON.stringify(base));
    updater(next);
    setDraft(next);
    setSaveStatus('unsaved');
  };

  const saveNow = () => {
    const m = draft !== null ? draft : __getDailyExpensesMap();
    __saveDailyExpensesMap(m);
    setDraft(null);
    setSaveStatus('saved');
    bump();
    setTimeout(() => setSaveStatus('idle'), 2000);
  };

  const pl = (() => {
    const m = draft !== null ? draft : __getDailyExpensesMap();
    if (!m[dateStr] || !m[dateStr][activeLoc]) {
      const copy = JSON.parse(JSON.stringify(m));
      ensureLocPayload(copy, dateStr, activeLoc);
      return copy[dateStr][activeLoc];
    }
    return m[dateStr][activeLoc];
  })();

  const lines = pl.expenseLines || [];
  const payrollAmt = parseNum(pl.payrollAmount);
  const payrollPeople = pl.payrollPeople || '';
  const cupRows = pl.cupRows || [];
  const expTotal = expenseTotal(lines, payrollAmt);
  const cupTot = cupRevenue(cupRows);
  const transTot =
    parseNum(pl.transferIce250) * 250 + parseNum(pl.transferIce500) * 500 + parseNum(pl.transferYogurt) * 500;

  let dayExpenseAll = 0;
  let dayTransfersAll = 0;
  const dayMap = __getDailyExpensesMap()[dateStr] || {};
  locs.forEach((L) => {
    const p = dayMap[L.id];
    if (!p) return;
    dayExpenseAll += expenseTotal(p.expenseLines || [], parseNum(p.payrollAmount));
    dayTransfersAll +=
      parseNum(p.transferIce250) * 250 +
      parseNum(p.transferIce500) * 500 +
      parseNum(p.transferYogurt) * 500;
  });

  const weekDays = isoWeekDays(dateStr);
  let weekTransfers = 0;
  let weekCupEst = 0;
  weekDays.forEach((d) => {
    const p = (__getDailyExpensesMap()[d] || {})[activeLoc];
    if (!p) return;
    weekTransfers +=
      parseNum(p.transferIce250) * 250 + parseNum(p.transferIce500) * 500 + parseNum(p.transferYogurt) * 500;
    weekCupEst += cupRevenue(p.cupRows || []);
  });

  const exportCsv = (kind) => {
    const rows = [];
    const fullMap = __getDailyExpensesMap();
    const dep = window.DEPOSITS || [];
    const sales = window.SALES || [];

    const pushExpenseRows = () => {
      rows.push(['section', 'date', 'location', 'detail', 'amount_fcfa']);
      Object.keys(fullMap)
        .sort()
        .forEach((d) => {
          locs.forEach((L) => {
            const p = fullMap[d] && fullMap[d][L.id];
            if (!p) return;
            (p.expenseLines || []).forEach((x) => {
              if (!parseNum(x.amount) && !String(x.label || '').trim()) return;
              rows.push(['expense', d, L.shortName, String(x.label || '').replace(/,/g, ' '), String(parseNum(x.amount))]);
            });
            if (parseNum(p.payrollAmount) !== 0 || String(p.payrollPeople || '').trim()) {
              rows.push(['payroll', d, L.shortName, `staff · ${String(p.payrollPeople || '').replace(/,/g, ' ')}`.trim(), String(parseNum(p.payrollAmount))]);
            }
          });
        });
    };

    if (kind === 'expenses') {
      pushExpenseRows();
    } else if (kind === 'income') {
      rows.push(['section', 'date', 'bank', 'amount_fcfa', 'description']);
      dep.forEach((x) => {
        rows.push([
          'deposit',
          x.deposit_date || '',
          String(x.bank_name || '').replace(/,/g, ' '),
          String(x.amount_fcfa ?? x.amount ?? 0),
          String(x.description || x.source || '').replace(/,/g, ' '),
        ]);
      });
    } else if (kind === 'sales') {
      rows.push(['section', 'date', 'flavor', 'scoops', 'amount_fcfa']);
      sales.slice(0, 5000).forEach((s) => {
        rows.push(['sale', s.sale_date || '', String(s.flavor || '').replace(/,/g, ' '), String(s.quantity_scoops || ''), String(s.amount_fcfa || 0)]);
      });
    } else if (kind === 'all') {
      pushExpenseRows();
      rows.push([]);
      rows.push(['section', 'date', 'bank', 'amount_fcfa', 'description']);
      dep.forEach((x) => {
        rows.push([
          'deposit',
          x.deposit_date || '',
          String(x.bank_name || '').replace(/,/g, ' '),
          String(x.amount_fcfa ?? x.amount ?? 0),
          String(x.description || x.source || '').replace(/,/g, ' '),
        ]);
      });
      rows.push([]);
      rows.push(['section', 'date', 'flavor', 'scoops', 'amount_fcfa']);
      sales.slice(0, 1500).forEach((s) => {
        rows.push(['sale', s.sale_date || '', String(s.flavor || '').replace(/,/g, ' '), String(s.quantity_scoops || ''), String(s.amount_fcfa || 0)]);
      });
    }

    const csv = rows.map((r) => r.map((c) => `"${String(c).replace(/"/g, '""')}"`).join(',')).join('\n');
    const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = `gelato-export-${kind}-${isoToday()}.csv`;
    a.click();
    URL.revokeObjectURL(a.href);
  };

  const activeName = locs.find((x) => x.id === activeLoc)?.name || '';

  return (
    <div className="gh-exp-root" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <style>{`
        .gh-exp-root .gh-exp-toolbar { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; justify-content: space-between; }
        .gh-exp-root .gh-exp-pills { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
        .gh-exp-root .gh-exp-pills::-webkit-scrollbar { height: 4px; }
        .gh-exp-root .gh-exp-main { display: grid; grid-template-columns: 1fr 260px; gap: 16px; align-items: start; }
        @media (max-width: 980px) { .gh-exp-root .gh-exp-main { grid-template-columns: 1fr; } }
        .gh-exp-root .gh-exp-table { width: 100%; border-collapse: collapse; font-size: 12px; }
        .gh-exp-root .gh-exp-table th { text-align: start; padding: 6px 8px; color: var(--text-dimmer); font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; font-family: JetBrains Mono, monospace; font-size: 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
        .gh-exp-root .gh-exp-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
        .gh-exp-root .gh-exp-table input { padding: 6px 8px; font-size: 12px; min-width: 0; width: 100%; }
        .gh-exp-root .gh-exp-mini { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
        @media (max-width: 520px) { .gh-exp-root .gh-exp-mini { grid-template-columns: 1fr; } }
        .gh-exp-root .gh-exp-side { position: sticky; top: 72px; display: flex; flex-direction: column; gap: 10px; }
        @media (max-width: 980px) { .gh-exp-root .gh-exp-side { position: static; } }
      `}</style>

      <div className="gh-exp-toolbar">
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'flex-end' }}>
          <div className="field" style={{ margin: 0 }}>
            <label>Date</label>
            <input type="date" value={dateStr} onChange={(e) => setDateStr(e.target.value)} style={{ padding: '6px 10px' }} />
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-dim)', maxWidth: 360, lineHeight: 1.45 }}>{t('admin.exp_intro')}</div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          <button type="button" className="btn btn-ghost btn-sm" onClick={() => exportCsv('expenses')}><Icon.Download size={13} /> {t('admin.export_exp')}</button>
          <button type="button" className="btn btn-ghost btn-sm" onClick={() => exportCsv('income')}><Icon.Download size={13} /> {t('admin.export_inc')}</button>
          <button type="button" className="btn btn-ghost btn-sm" onClick={() => exportCsv('sales')}><Icon.Download size={13} /> {t('admin.export_sale')}</button>
          <button type="button" className="btn btn-ghost btn-sm" onClick={() => exportCsv('all')}><Icon.Download size={13} /> {t('admin.export_full')}</button>
        </div>
      </div>

      <div className="gh-exp-pills">
        {locs.map((L) => {
          const pmap = (__getDailyExpensesMap()[dateStr] || {})[L.id];
          const sub = pmap ? expenseTotal(pmap.expenseLines || [], parseNum(pmap.payrollAmount)) : 0;
          const ok = activeLoc === L.id;
          return (
            <button key={L.id} type="button" onClick={() => setActiveLoc(L.id)} className={ok ? 'btn btn-primary btn-sm' : 'btn btn-ghost btn-sm'} style={{ borderRadius: 999, flexShrink: 0 }}>
              {L.shortName} <span style={{ opacity: 0.85, fontSize: 11, marginLeft: 4 }}>{fmtNumber(sub)} F</span>
            </button>
          );
        })}
      </div>

      <div className="gh-exp-main">
        <div className="card" style={{ padding: '14px 16px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10, marginBottom: 10, flexWrap: 'wrap' }}>
            <div>
              <h3 style={{ fontSize: 15, fontWeight: 600, margin: 0 }}>{activeName}</h3>
              <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{fmtDate(dateStr)}</div>
              {isPastDay && !canEdit && <div style={{ fontSize: 11, color: 'var(--red)', marginTop: 3 }}>Past day — only boss can edit</div>}
              {isPastDay && canEdit && <div style={{ fontSize: 11, color: 'var(--gold)', marginTop: 3 }}>Past day — boss edit mode</div>}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
              <div style={{ fontFamily: 'JetBrains Mono', fontSize: 12 }}>{t('admin.exp_counters_sub')}: <strong>{fmtNumber(cupTot)}</strong></div>
              {canEdit && (
                <button
                  type="button"
                  className="btn btn-primary btn-sm"
                  onClick={saveNow}
                  disabled={saveStatus === 'idle' && draft === null}
                  style={{ minWidth: 80 }}
                >
                  {saveStatus === 'saved' ? '✓ Saved' : saveStatus === 'unsaved' ? 'Save' : 'Saved'}
                </button>
              )}
            </div>
          </div>

          <div style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-dimmer)', marginBottom: 4 }}>{t('admin.exp_out_sales')}</div>
          <table className="gh-exp-table">
            <thead>
              <tr>
                <th>Produit</th>
                <th style={{ width: 88 }}>Prix</th>
                <th style={{ width: 72 }}>Qté</th>
                <th style={{ width: 96, textAlign: 'right' }}>Sous-total</th>
              </tr>
            </thead>
            <tbody>
              {cupRows.map((row, idx) => (
                <tr key={row.id}>
                  <td style={{ color: 'var(--text-dim)' }}>{row.label}</td>
                  <td>
                    <input disabled={!canEdit} type="number" placeholder="—" value={row.unitPrice === '' || row.unitPrice == null ? '' : row.unitPrice} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).cupRows[idx].unitPrice = e.target.value; })} />
                  </td>
                  <td>
                    <input disabled={!canEdit} type="number" placeholder="—" value={row.qty === '' || row.qty == null ? '' : row.qty} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).cupRows[idx].qty = e.target.value; })} />
                  </td>
                  <td style={{ fontFamily: 'JetBrains Mono', textAlign: 'right' }}>{fmtNumber(parseNum(row.unitPrice) * parseNum(row.qty))}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {canEdit && (
            <button type="button" className="btn btn-ghost btn-sm" style={{ marginTop: 6 }} onClick={() => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).cupRows.push({ id: 'cr' + Date.now(), product: 'ice', label: t('admin.exp_custom'), unitPrice: '', qty: '' }); })}>
              + {t('admin.exp_add_line')}
            </button>
          )}

          <div style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-dimmer)', marginTop: 12, marginBottom: 6 }}>{t('admin.exp_transfer')}</div>
          <div className="gh-exp-mini">
            {[
              ['transferIce250', '×250 Ice'],
              ['transferIce500', '×500 Ice'],
              ['transferYogurt', 'Yogurt'],
            ].map(([k, lbl]) => (
              <div key={k} className="field">
                <label style={{ fontSize: 10 }}>{lbl}</label>
                <input disabled={!canEdit} type="number" placeholder="0" value={pl[k] === '' || pl[k] == null ? '' : pl[k]} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc)[k] = e.target.value; })} />
              </div>
            ))}
          </div>
          <div style={{ fontFamily: 'JetBrains Mono', fontSize: 11, marginTop: 4, marginBottom: 10 }}>
            {t('admin.exp_transfer_value')}: <strong>{fmtNumber(transTot)} FCFA</strong>
          </div>

          <div style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-dimmer)', marginBottom: 4 }}>{t('admin.exp_staff_day')}</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr minmax(100px, 120px)', gap: 8 }}>
            <div className="field">
              <label style={{ fontSize: 10 }}>{t('admin.exp_people_hours')}</label>
              <input disabled={!canEdit} placeholder={t('admin.exp_people_hours_ph')} value={payrollPeople} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).payrollPeople = e.target.value; })} />
            </div>
            <div className="field">
              <label style={{ fontSize: 10 }}>{t('admin.exp_payroll_total')}</label>
              <input disabled={!canEdit} type="number" placeholder="0" value={pl.payrollAmount === '' || pl.payrollAmount == null ? '' : pl.payrollAmount} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).payrollAmount = e.target.value; })} />
            </div>
          </div>

          <div style={{ fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-dimmer)', marginTop: 10, marginBottom: 4 }}>{t('admin.exp_misc')}</div>
          <table className="gh-exp-table">
            <tbody>
              {lines.map((ln, idx) => (
                <tr key={idx}>
                  <td>
                    <input disabled={!canEdit} placeholder={t('admin.exp_what')} value={ln.label || ''} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).expenseLines[idx].label = e.target.value; })} />
                  </td>
                  <td style={{ width: 120 }}>
                    <input disabled={!canEdit} type="number" placeholder="FCFA" value={ln.amount === '' ? '' : ln.amount} onChange={(e) => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).expenseLines[idx].amount = e.target.value; })} />
                  </td>
                  <td style={{ width: 40 }}>
                    {canEdit && <button type="button" className="btn btn-ghost btn-sm" onClick={() => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).expenseLines.splice(idx, 1); })}>×</button>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
          {canEdit && <button type="button" className="btn btn-ghost btn-sm" style={{ marginTop: 4 }} onClick={() => stageChange((m) => { ensureLocPayload(m, dateStr, activeLoc).expenseLines.push({ label: '', amount: '' }); })}>+ {t('admin.exp_add_row')}</button>}
        </div>

        <aside className="gh-exp-side">
          <div className="card" style={{ padding: 14 }}>
            <div style={{ fontSize: 10, color: 'var(--accent)', fontFamily: 'JetBrains Mono', letterSpacing: '0.08em', textTransform: 'uppercase' }}>{t('admin.exp_location_sub')}</div>
            <div style={{ fontSize: 22, fontFamily: "'Cormorant Garamond', serif", marginTop: 4 }}>{fmtNumber(expTotal)} FCFA</div>
          </div>
          <div className="card" style={{ padding: 14, display: 'grid', gap: 8 }}>
            <div>
              <div style={{ fontSize: 10, fontFamily: 'JetBrains Mono', color: 'var(--text-dim)' }}>{t('admin.exp_day_all_exp')}</div>
              <div style={{ fontSize: 18, fontFamily: "'Cormorant Garamond', serif" }}>{fmtNumber(dayExpenseAll)} FCFA</div>
            </div>
            <div>
              <div style={{ fontSize: 10, fontFamily: 'JetBrains Mono', color: 'var(--text-dim)' }}>{t('admin.exp_day_transfers_all')}</div>
              <div style={{ fontSize: 18, fontFamily: "'Cormorant Garamond', serif" }}>{fmtNumber(dayTransfersAll)} FCFA</div>
            </div>
          </div>
          <div className="card" style={{ padding: 14 }}>
            <div style={{ fontSize: 11, fontWeight: 600, marginBottom: 6 }}>{t('admin.exp_week_title')}</div>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', marginBottom: 6 }}>{locs.find((x) => x.id === activeLoc)?.shortName}</div>
            <div style={{ fontFamily: 'JetBrains Mono', fontSize: 11, display: 'flex', flexDirection: 'column', gap: 4 }}>
              <span>{t('admin.exp_week_cup')}: {fmtNumber(weekCupEst)} FCFA</span>
              <span>{t('admin.exp_week_trans')}: {fmtNumber(weekTransfers)} FCFA</span>
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
}

Object.assign(window, { ExpensesOutlet });
