/* AIWine CRM — App payments.
   Every dollar the app or website takes: Connoisseur memberships and wine
   orders. Reads the `payments` table (crm/supabase/14-app-payments.sql).
   A captured membership row flips that consumer to Connoisseur in the same
   transaction (DB trigger), so the member's 10% appears on web and app
   without anyone touching a flag by hand. */
function Payments({ country }) {
  const store = window.UI.useStore();
  const { Badge, CTag, Ic, Search, Seg, StatTile, Empty, Modal, Field, KV, money, fmtDate, rel } = window.UI;
  const T = window.AIWTIERS;

  const [q, setQ] = React.useState('');
  const [kind, setKind] = React.useState('ALL');
  const [range, setRange] = React.useState('30');
  const [adding, setAdding] = React.useState(false);
  const [open, setOpen] = React.useState(null);

  const all = (store.t('payments') || []).filter((p) => window.UI.inCountry(p, country));
  const since = range === 'ALL' ? 0 : Date.now() - (+range) * 86400000;
  const ql = q.trim().toLowerCase();
  const rows = all
    .filter((p) => (kind === 'ALL' || p.kind === kind))
    .filter((p) => !since || new Date(p.paidAt || p.createdAt).getTime() >= since)
    .filter((p) => !ql || (p.email || '').toLowerCase().includes(ql) || (p.description || '').toLowerCase().includes(ql) || (p.stripeId || '').toLowerCase().includes(ql))
    .sort((a, b) => String(b.paidAt || b.createdAt).localeCompare(String(a.paidAt || a.createdAt)));

  const captured = rows.filter((p) => p.status === 'captured');
  const memberships = captured.filter((p) => p.kind === 'membership');
  const wine = captured.filter((p) => p.kind === 'wine');
  const sum = (arr, f) => arr.reduce((n, p) => n + (+(f ? p[f] : p.amount) || 0), 0);
  const failed = rows.filter((p) => p.status === 'failed' || p.status === 'pending');

  // membership base: consumers currently on Connoisseur (normalised — never counts a legacy id twice)
  const consumers = (store.t('consumers') || []).filter((c) => window.UI.inCountry(c, country));
  const members = consumers.filter((c) => T.isMember(c.plan));
  const mrr = members.length * T.TIERS.connoisseur.monthly;

  function record(form) {
    const email = (form.email || '').trim().toLowerCase();
    if (!email) { window.UI.toast('An email is required — it is the join key'); return; }
    const consumer = consumers.find((c) => (c.email || '').toLowerCase() === email);
    const amount = +form.amount || 0;
    const row = {
      email, country: form.country || (country === 'ALL' ? 'NZ' : country),
      consumerId: consumer ? consumer.id : null,
      kind: form.kind, description: form.description || (form.kind === 'membership' ? 'AIWine membership' : 'Wine order'),
      plan: form.kind === 'membership' ? 'connoisseur' : null,
      months: form.kind === 'membership' ? (+form.months || 1) : null,
      amount, currency: (form.country === 'AU' ? 'AUD' : 'NZD'),
      memberDiscount: +form.memberDiscount || 0,
      source: 'crm', status: 'captured',
      paidAt: new Date().toISOString(),
    };
    store.insert('payments', row);
    // In demo mode there is no DB trigger, so mirror what the trigger does.
    if (store.mode !== 'live' && consumer && form.kind === 'membership') {
      store.update('consumers', consumer.id, {
        plan: 'connoisseur',
        renewsAt: new Date(Date.now() + (+form.months || 1) * 30 * 86400000).toISOString(),
        ltv: (+consumer.ltv || 0) + amount,
      });
    }
    store.audit('Recorded ' + form.kind + ' payment · ' + email, 'payment');
    window.UI.toast(form.kind === 'membership' ? 'Payment recorded — member set to AIWine Member' : 'Payment recorded');
    setAdding(false);
  }

  const sel = open ? all.find((p) => p.id === open) : null;
  const selConsumer = sel ? consumers.find((c) => (c.email || '').toLowerCase() === (sel.email || '').toLowerCase()) : null;

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="label" style={{ marginBottom: 6 }}>Memberships &amp; wine · app and web, one ledger</div>
          <h1 className="page-title">App payments</h1>
        </div>
        <button className="btn btn-primary" onClick={() => setAdding(true)}><Ic name="plus" w={14} /> Record a payment</button>
      </div>

      <div className="stat-grid" style={{ marginBottom: 18 }}>
        <StatTile label="Membership revenue" num={money(sum(memberships), country)} delta={memberships.length + ' payments'} />
        <StatTile label="Wine revenue" num={money(sum(wine), country)} delta={wine.length + ' orders'} />
        <StatTile label="AIWine Members" num={members.length} delta={money(mrr, country) + ' / month'} deltaClass="up" />
        <StatTile label="Member 10% funded" num={money(sum(captured, 'memberDiscount'), country)} delta="from our commission" />
      </div>

      <div className="filters">
        <Search value={q} onChange={setQ} placeholder="Search email, description or Stripe id…" />
        <Seg options={[{ value: 'ALL', label: 'All' }, { value: 'membership', label: 'Memberships' }, { value: 'wine', label: 'Wine' }, { value: 'refund', label: 'Refunds' }]} value={kind} onChange={setKind} />
        <Seg mono options={[{ value: '30', label: '30d' }, { value: '90', label: '90d' }, { value: '365', label: '12m' }, { value: 'ALL', label: 'All' }]} value={range} onChange={setRange} />
      </div>

      {failed.length > 0 && (
        <div className="callout" style={{ marginBottom: 14 }}>
          <b>{failed.length} payment{failed.length === 1 ? '' : 's'} not captured.</b> Pending or failed rows never change a member's tier — the tier only moves on a captured payment.
        </div>
      )}

      <div className="tbl-wrap">
        <table className="tbl">
          <thead><tr><th>Paid</th><th>Member</th><th></th><th>Kind</th><th>Description</th><th className="num">Amount</th><th className="num">Our 10%</th><th>Status</th><th>Via</th></tr></thead>
          <tbody>
            {rows.map((p) => (
              <tr key={p.id} className="rowlink" onClick={() => setOpen(p.id)}>
                <td className="mono" style={{ fontSize: 11 }}>{fmtDate(p.paidAt || p.createdAt)}</td>
                <td className="main-cell">{p.email}</td>
                <td><CTag c={p.country} /></td>
                <td><Badge v={p.kind === 'membership' ? 'complete' : p.kind === 'refund' ? 'open' : 'scheduled'}>{p.kind}</Badge></td>
                <td>{p.description || '—'}{p.months > 1 ? ' · ' + p.months + ' months' : ''}</td>
                <td className="num">{money(p.amount, p.country)}</td>
                <td className="num">{p.memberDiscount ? money(p.memberDiscount, p.country) : '—'}</td>
                <td><Badge v={p.status === 'captured' ? 'complete' : p.status === 'failed' ? 'open' : 'pending'} dot={p.status !== 'captured'}>{p.status}</Badge></td>
                <td className="mono" style={{ fontSize: 10.5 }}>{p.source}</td>
              </tr>
            ))}
            {rows.length === 0 && (
              <tr><td colSpan="9"><Empty msg="No payments in this window" hint="Stripe writes here automatically once the webhook is live. Until then, record one by hand — a captured membership payment sets the member to Connoisseur." /></td></tr>
            )}
          </tbody>
        </table>
      </div>

      {sel && (
        <Modal title={money(sel.amount, sel.country) + ' · ' + sel.kind} sub={sel.email} onClose={() => setOpen(null)}
          foot={<React.Fragment>
            {selConsumer && <button className="btn btn-ghost btn-sm" style={{ marginRight: 'auto' }} onClick={() => window.go('consumers', selConsumer.id)}>Open member →</button>}
            {sel.status === 'captured' && sel.kind !== 'refund' && (
              <button className="btn btn-ghost btn-sm" onClick={() => {
                store.insert('payments', Object.assign({}, sel, { id: undefined, kind: 'refund', amount: -Math.abs(sel.amount), description: 'Refund · ' + (sel.description || sel.kind), status: 'captured', source: 'crm', stripeId: null, paidAt: new Date().toISOString() }));
                store.update('payments', sel.id, { status: 'refunded' });
                store.audit('Refunded payment ' + sel.id, 'payment');
                window.UI.toast('Refund recorded');
                setOpen(null);
              }}>Record refund</button>
            )}
          </React.Fragment>}>
          <KV rows={[
            ['Paid', fmtDate(sel.paidAt || sel.createdAt) + ' · ' + rel(sel.paidAt || sel.createdAt)],
            ['Kind', sel.kind + (sel.plan ? ' · ' + T.label(sel.plan) : '')],
            ['Amount', money(sel.amount, sel.country) + ' ' + (sel.currency || '')],
            ['Processor fee', sel.fee ? money(sel.fee, sel.country) : '—'],
            ['Member discount we funded', sel.memberDiscount ? money(sel.memberDiscount, sel.country) : '—'],
            ['Bottles', sel.bottles || '—'],
            ['Winery', sel.wineryId ? (store.get('wineries', sel.wineryId) || {}).name || sel.wineryId : '—'],
            ['Order', sel.orderId || '—'],
            ['Source', sel.source],
            ['Stripe id', sel.stripeId || '—'],
            ['Member tier now', selConsumer ? T.label(selConsumer.plan) : 'No consumer record yet'],
            ['Renews', selConsumer && selConsumer.renewsAt ? fmtDate(selConsumer.renewsAt) : '—'],
          ]} />
        </Modal>
      )}

      {adding && <RecordPayment onClose={() => setAdding(false)} onSave={record} country={country} />}
    </div>
  );
}

function RecordPayment({ onClose, onSave, country }) {
  const { Modal, Field, Seg } = window.UI;
  const T = window.AIWTIERS;
  const [f, setF] = React.useState({ kind: 'membership', email: '', amount: String(T.TIERS.connoisseur.monthly), months: '1', country: country === 'AU' ? 'AU' : 'NZ', description: '', memberDiscount: '' });
  const set = (k) => (e) => setF(Object.assign({}, f, { [k]: e.target.value }));
  return (
    <Modal title="Record a payment" sub="Use this for a payment taken outside Stripe, or to comp a membership." onClose={onClose}
      foot={<React.Fragment>
        <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
        <button className="btn btn-primary btn-sm" onClick={() => onSave(f)}>Record payment</button>
      </React.Fragment>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <Field label="Kind">
          <Seg options={[{ value: 'membership', label: 'Membership' }, { value: 'wine', label: 'Wine order' }]} value={f.kind} onChange={(v) => setF(Object.assign({}, f, { kind: v, amount: v === 'membership' ? String(T.TIERS.connoisseur.monthly) : f.amount }))} />
        </Field>
        <Field label="Member email"><input className="inp" value={f.email} onChange={set('email')} placeholder="name@example.co.nz" /></Field>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <Field label="Amount (incl GST)"><input className="inp" value={f.amount} onChange={set('amount')} inputMode="decimal" /></Field>
          <Field label="Market">
            <Seg mono options={[{ value: 'NZ', label: 'NZ' }, { value: 'AU', label: 'AU' }]} value={f.country} onChange={(v) => setF(Object.assign({}, f, { country: v }))} />
          </Field>
        </div>
        {f.kind === 'membership' ? (
          <Field label="Months covered"><input className="inp" value={f.months} onChange={set('months')} inputMode="numeric" /></Field>
        ) : (
          <Field label="Member 10% we funded on this order"><input className="inp" value={f.memberDiscount} onChange={set('memberDiscount')} inputMode="decimal" placeholder="0" /></Field>
        )}
        <Field label="Description"><input className="inp" value={f.description} onChange={set('description')} placeholder={f.kind === 'membership' ? 'AIWine membership' : 'Wine order'} /></Field>
        {f.kind === 'membership' && (
          <div className="callout">A captured membership payment sets that member to an <b>AIWine Member</b> and extends their renewal date. Their 10% then applies in the app and on the website cart immediately.</div>
        )}
      </div>
    </Modal>
  );
}

window.Payments = Payments;
