// portal-screens.jsx — read-mostly screens: Dashboard, Members list, Profile, Reports, Audit log

// ═══════════════════════════════════════════════════════════════
// DASHBOARD
// ═══════════════════════════════════════════════════════════════

function PageHeader({ title, eyebrow, children, sub }) {
  return (
    <div className="pt-row" style={{ justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 22, gap: 12, flexWrap: 'wrap' }}>
      <div className="pt-col" style={{ gap: 4 }}>
        {eyebrow && <div className="pt-eyebrow">{eyebrow}</div>}
        <h1 className="pt-h1">{title}</h1>
        {sub && <div className="pt-mute" style={{ fontSize: 14 }}>{sub}</div>}
      </div>
      <div className="pt-row" style={{ gap: 8, flexWrap: 'wrap' }}>{children}</div>
    </div>
  );
}

function Stat({ label, value, accent, sub, icon }) {
  return (
    <Card flat style={{ flex: 1, minWidth: 0 }}>
      <div className="pt-row" style={{ justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div className="pt-eyebrow">{label}</div>
        {icon && <div style={{ opacity: 0.5, fontSize: 16 }}>{icon}</div>}
      </div>
      <div className="pt-display pt-num" style={{ fontSize: 36, marginTop: 6, color: accent || T.text, lineHeight: 1 }}>{value}</div>
      {sub && <div className="pt-faint" style={{ fontSize: 12, marginTop: 6 }}>{sub}</div>}
    </Card>
  );
}

function BarChart({ data, height = 180, accent = T.gold }) {
  const max = Math.max(...data.map(d => d.value), 1);
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height, paddingTop: 10 }}>
      {data.map((d, i) => {
        const h = (d.value / max) * (height - 26);
        return (
          <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, minWidth: 0 }}>
            <div className="pt-num" style={{ fontSize: 10, color: T.textFaint, opacity: 0.8 }}>{d.value > 0 ? (d.value >= 1000 ? (d.value / 1000).toFixed(0) + 'k' : d.value) : ''}</div>
            <div style={{
              width: '100%',
              height: Math.max(2, h),
              background: i === data.length - 1 ? `linear-gradient(180deg, ${T.goldBright}, ${T.gold})` : `linear-gradient(180deg, ${T.surface3}, ${T.surface2})`,
              borderTop: '2px solid ' + (i === data.length - 1 ? T.goldBright : T.border),
              borderRadius: '4px 4px 0 0',
              transition: 'height .3s',
            }} />
            <div style={{ fontSize: 10, color: T.textFaint }}>{d.label}</div>
          </div>
        );
      })}
    </div>
  );
}

function DonutChart({ segments, size = 140 }) {
  const total = segments.reduce((a, b) => a + b.value, 0) || 1;
  const r = size / 2 - 14;
  const cx = size / 2;
  let acc = 0;
  const C = 2 * Math.PI * r;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={cx} cy={cx} r={r} fill="none" stroke={T.borderSoft} strokeWidth="14" />
      {segments.map((s, i) => {
        const len = (s.value / total) * C;
        const offset = (acc / total) * C;
        acc += s.value;
        return (
          <circle key={i} cx={cx} cy={cx} r={r} fill="none"
            stroke={s.color}
            strokeWidth="14"
            strokeDasharray={`${len} ${C - len}`}
            strokeDashoffset={-offset}
            transform={`rotate(-90 ${cx} ${cx})`}
            strokeLinecap="butt"
          />
        );
      })}
      <text x={cx} y={cx - 4} textAnchor="middle" fill={T.text} style={{ font: '600 22px Cormorant Garamond, serif' }}>{total}</text>
      <text x={cx} y={cx + 14} textAnchor="middle" fill={T.textMute} style={{ font: '500 10px Manrope, sans-serif', letterSpacing: '0.1em', textTransform: 'uppercase' }}>members</text>
    </svg>
  );
}

function DashboardScreen() {
  const allMembers = useStore(s => s.members);
  const audit = useStore(s => s.audit);
  const session = useStore(s => s.session);
  const user = useStore(s => s.users.find(u => u.id === s.currentUserId));
  const role = user && user.role;

  // Role-tailored views:
  //   - Associate: big "Redeem now" hero, today's actions, upcoming birthdays only
  //   - Manager:   revenue + mix + top spenders + birthdays
  //   - Super Admin: everything (default)
  const isAssoc = role === 'Associate';
  const isManager = role === 'Manager';

  const members = allMembers.filter(m => !m.deleted);
  const inProperty = members.filter(m => true);
  const active = inProperty.filter(m => m.status === 'active');
  const expired = inProperty.filter(m => m.status === 'expired');
  const silvers = active.filter(m => m.type === 'silver');
  const wellness = active.filter(m => m.type === 'wellness');
  const totalRevenue = inProperty.reduce((sum, m) => sum + sumSpend(m.spend), 0);
  const totalDiscount = inProperty.reduce((sum, m) => sum + (m.spend.discount || 0), 0);
  const topSpenders = [...inProperty].sort((a, b) => sumSpend(b.spend) - sumSpend(a.spend)).slice(0, 5);

  // Upcoming birthdays/anniversaries (within 30 days)
  const today = new Date();
  const upcoming = [];
  inProperty.forEach(m => {
    if (m.dob) {
      const [y, mo, d] = m.dob.split('-').map(Number);
      const next = new Date(today.getFullYear(), mo - 1, d);
      if (next < today) next.setFullYear(today.getFullYear() + 1);
      const days = Math.round((next - today) / 86400000);
      if (days <= 30) upcoming.push({ kind: 'birthday', date: next, days, member: m });
    }
    if (m.anniversary && m.type === 'wellness') {
      const parts = m.anniversary.split('-');
      if (parts.length === 2) {
        const next = new Date(today.getFullYear(), Number(parts[0]) - 1, Number(parts[1]));
        if (next < today) next.setFullYear(today.getFullYear() + 1);
        const days = Math.round((next - today) / 86400000);
        if (days <= 30) upcoming.push({ kind: 'anniversary', date: next, days, member: m });
      }
    }
  });
  upcoming.sort((a, b) => a.days - b.days);

  // Build last 12 months revenue (synthetic from current totals)
  const monthLabels = ['Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May'];
  const chartData = monthLabels.map((m, i) => ({
    label: m,
    value: Math.round(totalRevenue * (0.04 + (i / 12) * 0.12) * (0.6 + Math.sin(i * 1.2) * 0.3 + 0.4)),
  }));

  const todayActions = audit.filter(a => {
    const d = new Date(a.ts);
    const now = new Date();
    return d.toDateString() === now.toDateString();
  });

  // ─── Associate-only dashboard: action-first, minimal stats ─────
  if (isAssoc) {
    const myActions = audit.filter(a => a.who === user.name).slice(0, 8);
    return (
      <div>
        <PageHeader
          eyebrow={`${new Date().toLocaleDateString('en-GB', { weekday: 'long', day: '2-digit', month: 'long' })}`}
          title={`Hi ${(session.staff || '').split(' ')[0] || 'there'}.`}
          sub={`${session.role} · ${session.property} · log redemptions & enroll new members`} />

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginBottom: 20 }}>
          <Card gold style={{ padding: 22 }}>
            <div className="pt-eyebrow">Most common</div>
            <h2 className="pt-h2" style={{ marginTop: 6 }}>Redeem a benefit</h2>
            <div className="pt-mute" style={{ fontSize: 13, marginTop: 4 }}>Comp room · F&B discount · pool · gym · cake</div>
            <Button variant="gold" size="lg" style={{ marginTop: 14, width: '100%' }} onClick={() => navigate('redeem')}>✓ Open Redeem →</Button>
          </Card>
          <Card style={{ padding: 22 }}>
            <div className="pt-eyebrow">New today</div>
            <h2 className="pt-h2" style={{ marginTop: 6 }}>Enroll a member</h2>
            <div className="pt-mute" style={{ fontSize: 13, marginTop: 4 }}>3-minute flow · printed card ready after save</div>
            <Button variant="gold" size="lg" style={{ marginTop: 14, width: '100%' }} onClick={() => navigate('enroll')}>+ Add member →</Button>
          </Card>
          <Card style={{ padding: 22 }}>
            <div className="pt-eyebrow">F&B desk</div>
            <h2 className="pt-h2" style={{ marginTop: 6 }}>Apply discount</h2>
            <div className="pt-mute" style={{ fontSize: 13, marginTop: 4 }}>From Aegis bill · 10% silver · 20% wellness</div>
            <Button variant="gold" size="lg" style={{ marginTop: 14, width: '100%' }} onClick={() => navigate('fnb')}>% Apply discount →</Button>
          </Card>
        </div>

        <Card flat>
          <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 12 }}>
            <h3 className="pt-h3">Your recent activity</h3>
            <Badge>{todayActions.length} today across team</Badge>
          </div>
          {myActions.length === 0 ? (
            <div className="pt-faint" style={{ padding: 18, textAlign: 'center' }}>Nothing logged yet today — start with Redeem or Enroll above.</div>
          ) : (
            <div className="pt-col" style={{ gap: 0 }}>
              {myActions.map((a, i) => (
                <div key={a.id} style={{ padding: '10px 0', borderBottom: i < myActions.length - 1 ? '1px solid ' + T.borderSoft : 'none', fontSize: 13 }}>
                  <div className="pt-row" style={{ justifyContent: 'space-between' }}>
                    <div>{a.action}</div>
                    <div className="pt-faint pt-num" style={{ fontSize: 11 }}>{fmtDateTime(a.ts)}</div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </Card>
      </div>
    );
  }

  return (
    <div>
      <PageHeader
        eyebrow={`${new Date().toLocaleDateString('en-GB', { weekday: 'long', day: '2-digit', month: 'long' })}`}
        title="Welcome back."
        sub={`${session.staff} · ${session.role} · ${session.property}`}
      >
        <Button onClick={() => navigate('redeem')}>✓ Redeem benefit</Button>
        <Button variant="gold" onClick={() => navigate('enroll')}>+ New member</Button>
      </PageHeader>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginBottom: 18 }}>
        <Stat label="Active members" value={active.length} sub={`${expired.length} expired`} icon="◆" />
        <Stat label="Wellness · Silver" value={`${wellness.length} · ${silvers.length}`} sub="paying · free tier" icon="◇" />
        <Stat label="Member revenue · YTD" value={fmtNPR(totalRevenue).replace('₨ ', '₨')} accent={T.gold} sub={`${fmtNPR(totalDiscount)} discount given`} icon="₨" />
        <Stat label="Actions today" value={todayActions.length} sub="across both properties" icon="↻" />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr', gap: 14, marginBottom: 18 }}>
        <Card>
          <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 4 }}>
            <div className="pt-col">
              <h3 className="pt-h3">Member revenue</h3>
              <div className="pt-faint" style={{ fontSize: 12 }}>last 12 months · all sources</div>
            </div>
            <Badge variant="gold">↑ trending</Badge>
          </div>
          <BarChart data={chartData} />
        </Card>
        <Card>
          <h3 className="pt-h3">Mix</h3>
          <div className="pt-row" style={{ gap: 18, alignItems: 'center', marginTop: 10 }}>
            <DonutChart segments={[
              { value: silvers.length, color: T.silver },
              { value: wellness.length, color: T.gold },
            ]} />
            <div className="pt-col" style={{ gap: 10, flex: 1 }}>
              <div className="pt-row" style={{ gap: 8 }}>
                <span className="pt-dot" style={{ background: T.gold, width: 10, height: 10 }} />
                <div className="pt-col" style={{ lineHeight: 1.2 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>Wellness · {wellness.length}</div>
                  <div className="pt-faint" style={{ fontSize: 11 }}>NPR 50,000 / yr</div>
                </div>
              </div>
              <div className="pt-row" style={{ gap: 8 }}>
                <span className="pt-dot" style={{ background: T.silver, width: 10, height: 10 }} />
                <div className="pt-col" style={{ lineHeight: 1.2 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>Silver · {silvers.length}</div>
                  <div className="pt-faint" style={{ fontSize: 11 }}>free tier</div>
                </div>
              </div>
            </div>
          </div>
        </Card>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card>
          <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 12 }}>
            <h3 className="pt-h3">★ Top spenders</h3>
            <span className="pt-link" onClick={() => navigate('members')} style={{ fontSize: 12 }}>see all</span>
          </div>
          <div className="pt-col" style={{ gap: 0 }}>
            {topSpenders.map((m, i) => (
              <div key={m.id} onClick={() => navigate('members/' + m.id)} style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: '10px 0',
                borderBottom: i < topSpenders.length - 1 ? '1px solid ' + T.borderSoft : 'none',
                cursor: 'pointer',
              }}>
                <span className="pt-display pt-num pt-mute" style={{ fontSize: 20, width: 22 }}>{i + 1}</span>
                <Avatar name={m.name} type={m.type} photo={m.photo} size={36} />
                <div className="pt-col" style={{ flex: 1, lineHeight: 1.2, minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{m.name}</div>
                  <div className="pt-faint pt-num" style={{ fontSize: 11 }}>{m.id} · {m.property}</div>
                </div>
                <TierBadge type={m.type} />
                <div className="pt-display pt-num pt-gold" style={{ fontSize: 19, fontWeight: 600 }}>{fmtNPR(sumSpend(m.spend))}</div>
              </div>
            ))}
            {topSpenders.length === 0 && <div className="pt-faint" style={{ padding: 18, textAlign: 'center' }}>No members yet — enroll the first one.</div>}
          </div>
        </Card>

        <Card>
          <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 12 }}>
            <h3 className="pt-h3">🎂 Coming up · 30 days</h3>
            <span className="pt-link" style={{ fontSize: 12 }}>plan all</span>
          </div>
          <div className="pt-col" style={{ gap: 0 }}>
            {upcoming.slice(0, 5).map((u, i) => (
              <div key={u.member.id + u.kind} onClick={() => navigate('members/' + u.member.id)} style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: '10px 0',
                borderBottom: i < Math.min(upcoming.length, 5) - 1 ? '1px solid ' + T.borderSoft : 'none',
                cursor: 'pointer',
              }}>
                <div style={{ width: 44, textAlign: 'center' }}>
                  <div className="pt-display pt-num" style={{ fontSize: 22, fontWeight: 600, color: u.days < 3 ? T.gold : T.text, lineHeight: 1 }}>{u.days}</div>
                  <div className="pt-faint" style={{ fontSize: 10 }}>{u.days === 0 ? 'today' : u.days === 1 ? 'day' : 'days'}</div>
                </div>
                <span style={{ fontSize: 20 }}>{u.kind === 'birthday' ? '🎂' : '💍'}</span>
                <div className="pt-col" style={{ flex: 1, lineHeight: 1.2 }}>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{u.member.name}</div>
                  <div className="pt-faint" style={{ fontSize: 11 }}>
                    {u.kind === 'birthday' ? 'birthday' : 'anniversary'} · {fmtDate(u.date)}
                    {u.member.type === 'wellness' && ' · cake comp due'}
                  </div>
                </div>
                <TierBadge type={u.member.type} />
              </div>
            ))}
            {upcoming.length === 0 && <div className="pt-faint" style={{ padding: 18, textAlign: 'center' }}>No birthdays in the next 30 days.</div>}
          </div>
        </Card>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// MEMBERS LIST
// ═══════════════════════════════════════════════════════════════

function MembersScreen() {
  const allMembers = useStore(s => s.members);
  const toast = useToast();
  const [q, setQ] = React.useState('');
  const [tier, setTier] = React.useState('all');
  const [prop, setProp] = React.useState('all');
  const [status, setStatus] = React.useState('all');
  const [showDeleted, setShowDeleted] = React.useState(false);
  const [importing, setImporting] = React.useState(false);

  // Soft-deleted members are hidden by default. Super admins can toggle them.
  const members = showDeleted ? allMembers : allMembers.filter(m => !m.deleted);

  const filtered = members.filter(m => {
    if (tier !== 'all' && m.type !== tier) return false;
    if (prop !== 'all' && m.property !== prop) return false;
    if (status !== 'all' && m.status !== status) return false;
    if (q) {
      const needle = q.toLowerCase();
      if (!(m.name.toLowerCase().includes(needle)
        || m.id.toLowerCase().includes(needle)
        || (m.cardNumber || '').toLowerCase().includes(needle)
        || (m.phone || '').includes(needle)
        || (m.email || '').toLowerCase().includes(needle))) return false;
    }
    return true;
  });

  const deletedCount = allMembers.filter(m => m.deleted).length;

  return (
    <div>
      <PageHeader title="Members" eyebrow="Database" sub={`${members.length} active · ${filtered.length} shown${deletedCount ? ` · ${deletedCount} deleted` : ''}`}>
        {Store.can('enroll') && <Button onClick={() => {
          const template = [
            'id,name,phone,type,email,gender,dob,anniversary,address,property,startDate,paymentAmount',
            'NW-001234,Anita Shrestha,+977 98-1119-8732,wellness,anita@example.com,F,1988-05-18,07-14,Biratnagar,Biratchowk,2026-05-01,50000',
            'SIL-000999,Bikash Rai,+977 98-2299-7711,silver,bikash@example.com,M,1981-03-22,,,Damak,2026-05-01,0',
            'GLD-000050,Priya Karki,+977 98-2310-4421,gold,priya@example.com,F,1992-09-04,12-18,,Biratchowk,2026-05-01,25000',
          ].join('\n');
          downloadCSV('members-template.csv', template);
          toast.show('Template downloaded · fill it in and re-upload via Import CSV');
        }}>⤓ Template</Button>}
        {Store.can('enroll') && <Button onClick={() => setImporting(true)}>⤒ Import CSV</Button>}
        {Store.can('delete') && deletedCount > 0 && (
          <Button onClick={() => setShowDeleted(v => !v)}>
            {showDeleted ? 'Hide deleted' : `Show deleted (${deletedCount})`}
          </Button>
        )}
        <Button variant="gold" onClick={() => navigate('enroll')}>+ New member</Button>
      </PageHeader>
      <CsvImportModal open={importing} onClose={() => setImporting(false)}
        onDone={(ok, fail) => toast.show(`Imported ${ok} · failed ${fail}`)} />

      <Card flat style={{ marginBottom: 14 }}>
        <div className="pt-row" style={{ gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
          <div style={{ flex: 1, minWidth: 240, position: 'relative' }}>
            <input
              className="pt-input"
              placeholder="Search name · card no · phone · email"
              value={q}
              onChange={e => setQ(e.target.value)}
              style={{ paddingLeft: 36 }}
            />
            <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: T.textFaint }}>⌕</span>
          </div>
          <select className="pt-select" value={tier} onChange={e => setTier(e.target.value)} style={{ width: 180 }}>
            <option value="all">All tiers</option>
            <option value="wellness">Wellness only</option>
            <option value="silver">Silver only</option>
          </select>
          <select className="pt-select" value={prop} onChange={e => setProp(e.target.value)} style={{ width: 180 }}>
            <option value="all">Both properties</option>
            <option value="Biratchowk">Biratchowk</option>
            <option value="Damak">Damak</option>
          </select>
          <select className="pt-select" value={status} onChange={e => setStatus(e.target.value)} style={{ width: 160 }}>
            <option value="all">All status</option>
            <option value="active">Active</option>
            <option value="expired">Expired</option>
          </select>
        </div>
      </Card>

      <Card flat style={{ padding: 0, overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table className="pt-table">
            <thead>
              <tr>
                <th>Card no</th>
                <th>Member</th>
                <th>Tier</th>
                <th>Property</th>
                <th>Joined</th>
                <th>Expiry</th>
                <th style={{ textAlign: 'right' }}>YTD spend</th>
                <th>Status</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(m => (
                <tr key={m.id} className="pt-row-link" onClick={() => navigate('members/' + m.id)}>
                  <td className="pt-num" style={{ fontWeight: 600, color: m.type === 'wellness' ? T.gold : T.silver }}>{m.id}</td>
                  <td>
                    <div className="pt-row" style={{ gap: 10 }}>
                      <Avatar name={m.name} type={m.type} photo={m.photo} size={32} />
                      <div className="pt-col" style={{ lineHeight: 1.2 }}>
                        <div style={{ fontWeight: 600 }}>{m.name}</div>
                        <div className="pt-faint pt-num" style={{ fontSize: 11 }}>{m.phone}</div>
                      </div>
                    </div>
                  </td>
                  <td><TierBadge type={m.type} /></td>
                  <td className="pt-mute">{m.property}</td>
                  <td className="pt-mute">{fmtDate(m.startDate)}</td>
                  <td className="pt-mute">{fmtDate(m.expiryDate)}</td>
                  <td className="pt-num pt-gold" style={{ textAlign: 'right', fontWeight: 600 }}>{fmtNPR(sumSpend(m.spend))}</td>
                  <td><StatusBadge status={m.status} /></td>
                </tr>
              ))}
              {filtered.length === 0 && (
                <tr><td colSpan={8} style={{ textAlign: 'center', padding: 40, color: T.textFaint }}>
                  No members match these filters. <span className="pt-link" onClick={() => navigate('enroll')}>Enroll a new member →</span>
                </td></tr>
              )}
            </tbody>
          </table>
        </div>
      </Card>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// REPORTS
// ═══════════════════════════════════════════════════════════════

// Date-range helper. Returns { from: Date, to: Date } for a preset key.
// All ranges are computed against Nepal local time (NPT, UTC+5:45) so
// "Today / Yesterday / This month" align with how the staff perceive dates.
function dateRange(preset, custom) {
  // Convert "now" to NPT by reading wall-clock time in Asia/Kathmandu and
  // building a Date from it.
  const nowStr = new Date().toLocaleString('en-US', { timeZone: 'Asia/Kathmandu' });
  const now = new Date(nowStr);
  const startOfDay = d => { const x = new Date(d); x.setHours(0, 0, 0, 0); return x; };
  const endOfDay = d => { const x = new Date(d); x.setHours(23, 59, 59, 999); return x; };
  switch (preset) {
    case 'today': return { from: startOfDay(now), to: endOfDay(now) };
    case 'yesterday': {
      const y = new Date(now); y.setDate(y.getDate() - 1);
      return { from: startOfDay(y), to: endOfDay(y) };
    }
    case 'last7': {
      const f = new Date(now); f.setDate(f.getDate() - 6);
      return { from: startOfDay(f), to: endOfDay(now) };
    }
    case 'last30': {
      const f = new Date(now); f.setDate(f.getDate() - 29);
      return { from: startOfDay(f), to: endOfDay(now) };
    }
    case 'thismonth': {
      const f = new Date(now.getFullYear(), now.getMonth(), 1);
      const t = new Date(now.getFullYear(), now.getMonth() + 1, 0);
      return { from: startOfDay(f), to: endOfDay(t) };
    }
    case 'lastmonth': {
      const f = new Date(now.getFullYear(), now.getMonth() - 1, 1);
      const t = new Date(now.getFullYear(), now.getMonth(), 0);
      return { from: startOfDay(f), to: endOfDay(t) };
    }
    case 'thisyear': {
      const f = new Date(now.getFullYear(), 0, 1);
      const t = new Date(now.getFullYear(), 11, 31);
      return { from: startOfDay(f), to: endOfDay(t) };
    }
    case 'custom':
      return {
        from: custom && custom.from ? startOfDay(new Date(custom.from)) : startOfDay(new Date(now.getFullYear(), now.getMonth(), 1)),
        to: custom && custom.to ? endOfDay(new Date(custom.to)) : endOfDay(now),
      };
    default: return { from: startOfDay(new Date(now.getFullYear(), 0, 1)), to: endOfDay(now) };
  }
}

function inRange(tsIso, range) {
  if (!tsIso) return false;
  const t = new Date(tsIso).getTime();
  return t >= range.from.getTime() && t <= range.to.getTime();
}

function ReportsScreen() {
  const members = useStore(s => s.members.filter(m => !m.deleted));
  const audit = useStore(s => s.audit);
  const bills = useStore(s => s.bills || []);
  const toast = useToast();

  const [preset, setPreset] = React.useState('last30');
  const [propertyF, setPropertyF] = React.useState('all');
  const [tierF, setTierF] = React.useState('all');
  const [customFrom, setCustomFrom] = React.useState('');
  const [customTo, setCustomTo] = React.useState('');
  const [memberSearch, setMemberSearch] = React.useState('');     // by name OR ID OR card #

  const range = dateRange(preset, { from: customFrom, to: customTo });

  // ─── Filter source data ────────────────────────────────────
  const inProp = (m) => propertyF === 'all' || (m.property === propertyF);
  const inTier = (m) => tierF === 'all' || (m.type === tierF);
  const inMemberSearch = (m) => {
    if (!memberSearch.trim()) return true;
    const n = memberSearch.toLowerCase();
    return (m.name || '').toLowerCase().includes(n)
      || (m.id || '').toLowerCase().includes(n)
      || (m.cardNumber || '').toLowerCase().includes(n)
      || (m.phone || '').includes(memberSearch)
      || (m.email || '').toLowerCase().includes(n);
  };
  const memFiltered = members.filter(m => inProp(m) && inTier(m) && inMemberSearch(m));
  const matchedIds = new Set(memFiltered.map(m => m.id));

  const enrolmentsInRange = memFiltered.filter(m => m.createdAt && inRange(m.createdAt, range));

  // Aggregate redemptions across all filtered members within date range
  const redemptionsInRange = [];
  memFiltered.forEach(m => (m.redemptions || []).forEach(r => {
    if (inRange(r.ts, range) && (propertyF === 'all' || r.property === propertyF)) {
      redemptionsInRange.push({ ...r, memberId: m.id, memberName: m.name, memberType: m.type });
    }
  }));

  // Bills filtered by date + property + the member-search filter (so you can
  // see bills for ONE specific member by typing their name/ID/card #).
  const billsInRange = bills.filter(b =>
    inRange(b.ts, range)
    && (propertyF === 'all' || b.property === propertyF)
    && (!memberSearch.trim() || matchedIds.has(b.memberId))
  );

  // ─── Derived metrics ───────────────────────────────────────
  const revenueByOutlet = {};
  billsInRange.forEach(b => {
    const k = b.outletName || b.outletId || 'unknown';
    if (!revenueByOutlet[k]) revenueByOutlet[k] = { property: b.property, gross: 0, discount: 0, vat: 0, net: 0, count: 0 };
    revenueByOutlet[k].gross += b.gross || 0;
    revenueByOutlet[k].discount += b.discount || 0;
    revenueByOutlet[k].vat += b.vatAfter || b.vat || 0;
    revenueByOutlet[k].net += b.netAfterPoints || b.net || 0;
    revenueByOutlet[k].count += 1;
  });

  const topSpenders = [...memFiltered]
    .map(m => ({ ...m, _ytd: sumSpend(m.spend || {}) }))
    .sort((a, b) => b._ytd - a._ytd)
    .slice(0, 20);

  const churnRisk = memFiltered.filter(m => {
    if (!m.redemptions || m.redemptions.length === 0) return false;
    const lastVisit = new Date(m.redemptions[0].ts).getTime();
    return (Date.now() - lastVisit) > 60 * 86400000;  // 60+ days no activity
  });

  const vatTotal = billsInRange.reduce((a, b) => a + (b.vatAfter || b.vat || 0), 0);
  const discountTotal = billsInRange.reduce((a, b) => a + (b.discount || 0), 0);
  const grossTotal = billsInRange.reduce((a, b) => a + (b.gross || 0), 0);

  // ─── Anti-fraud detector ───────────────────────────────────
  const fraudFlags = [];
  // Same card used at 2 properties within 30 minutes
  memFiltered.forEach(m => {
    const sorted = [...(m.redemptions || [])].sort((a, b) => new Date(a.ts) - new Date(b.ts));
    for (let i = 1; i < sorted.length; i++) {
      const prev = sorted[i - 1], cur = sorted[i];
      const dt = (new Date(cur.ts) - new Date(prev.ts)) / 60000; // minutes
      if (dt <= 30 && prev.property && cur.property && prev.property !== cur.property) {
        fraudFlags.push({
          type: 'cross-property', member: m.name, memberId: m.id,
          detail: `${prev.property} (${new Date(prev.ts).toLocaleTimeString()}) → ${cur.property} (${new Date(cur.ts).toLocaleTimeString()}) in ${Math.round(dt)} min`,
        });
      }
    }
  });
  // Discount overrides
  billsInRange.forEach(b => {
    const expected = b.memberType === 'wellness' ? 20 : 10;
    if (b.discountPct && b.discountPct > expected) {
      fraudFlags.push({
        type: 'discount-override', member: b.staff, memberId: b.memberId,
        detail: `Bill ${b.id} applied ${b.discountPct}% (tier max ${expected}%)`,
      });
    }
  });

  // ─── CSV export helpers ────────────────────────────────────
  function exportCSV(kind) {
    const rngTag = `${range.from.toISOString().slice(0,10)}_${range.to.toISOString().slice(0,10)}`;
    if (kind === 'enrolments') {
      const csv = toCSV(enrolmentsInRange, [
        { key: 'id', label: 'Member ID' }, { key: 'cardNumber', label: 'Card #' },
        { key: 'name', label: 'Name' }, { key: 'type', label: 'Tier' },
        { key: 'phone', label: 'Phone' }, { key: 'email', label: 'Email' },
        { key: 'property', label: 'Property' }, { key: 'startDate', label: 'Joined' },
        { key: 'expiryDate', label: 'Expiry' }, { key: 'paymentAmount', label: 'Paid · NPR' },
        { key: 'salesRep', label: 'Sales rep' },
      ]);
      return downloadCSV(`enrolments_${rngTag}.csv`, csv);
    }
    if (kind === 'redemptions') {
      const csv = toCSV(redemptionsInRange, [
        { key: 'ts', label: 'When' }, { key: 'memberId', label: 'Member ID' },
        { key: 'memberName', label: 'Member' }, { key: 'kind', label: 'Type' },
        { key: 'label', label: 'Description' }, { key: 'amount', label: 'Saved · NPR' },
        { key: 'property', label: 'Property' }, { key: 'staff', label: 'Staff' },
      ]);
      return downloadCSV(`redemptions_${rngTag}.csv`, csv);
    }
    if (kind === 'bills') {
      const csv = toCSV(billsInRange, [
        { key: 'id', label: 'Bill #' }, { key: 'ts', label: 'When' },
        { key: 'memberId', label: 'Member' }, { key: 'outletName', label: 'Outlet' },
        { key: 'property', label: 'Property' },
        { key: 'gross', label: 'Gross' }, { key: 'discountPct', label: 'Disc %' },
        { key: 'discount', label: 'Discount · NPR' }, { key: 'vat', label: 'VAT' },
        { key: 'total', label: 'Total' }, { key: 'staff', label: 'Staff' },
      ]);
      return downloadCSV(`bills_${rngTag}.csv`, csv);
    }
    if (kind === 'topspenders') {
      const csv = toCSV(topSpenders, [
        { key: 'id', label: 'Member ID' }, { key: 'name', label: 'Name' },
        { key: 'type', label: 'Tier' },
        { key: 'rooms', label: 'Rooms', get: m => (m.spend && m.spend.rooms) || 0 },
        { key: 'fnb', label: 'F&B', get: m => (m.spend && m.spend.fnb) || 0 },
        { key: 'wellness', label: 'Wellness', get: m => (m.spend && m.spend.wellness) || 0 },
        { key: '_ytd', label: 'Total YTD' },
        { key: 'discount', label: 'Discount used', get: m => (m.spend && m.spend.discount) || 0 },
      ]);
      return downloadCSV(`topspenders_${rngTag}.csv`, csv);
    }
    if (kind === 'churn') {
      const csv = toCSV(churnRisk, [
        { key: 'id', label: 'Member ID' }, { key: 'name', label: 'Name' },
        { key: 'phone', label: 'Phone' }, { key: 'email', label: 'Email' },
        { key: 'expiryDate', label: 'Expires' },
        { key: 'last', label: 'Last visit', get: m => m.redemptions && m.redemptions[0] ? m.redemptions[0].ts : '' },
      ]);
      return downloadCSV(`churn-risk_${rngTag}.csv`, csv);
    }
    if (kind === 'vat') {
      const rows = Object.entries(revenueByOutlet).map(([name, v]) => ({ outlet: name, ...v }));
      const csv = toCSV(rows, [
        { key: 'outlet', label: 'Outlet' }, { key: 'property', label: 'Property' },
        { key: 'count', label: 'Bills' }, { key: 'gross', label: 'Gross · NPR' },
        { key: 'discount', label: 'Member discount' }, { key: 'net', label: 'Net (ex-VAT)' },
        { key: 'vat', label: 'VAT collected' },
      ]);
      return downloadCSV(`vat-summary_${rngTag}.csv`, csv);
    }
    if (kind === 'audit') {
      const auditFiltered = audit.filter(a => inRange(a.ts, range));
      const csv = toCSV(auditFiltered, [
        { key: 'ts', label: 'When' }, { key: 'who', label: 'Who' },
        { key: 'role', label: 'Role' }, { key: 'property', label: 'Property' },
        { key: 'action', label: 'Action' }, { key: 'memberId', label: 'Member' },
      ]);
      return downloadCSV(`audit_${rngTag}.csv`, csv);
    }
    toast.show('Unknown report', { bad: true });
  }

  const presetLabel = ({
    today: 'Today', yesterday: 'Yesterday', last7: 'Last 7 days', last30: 'Last 30 days',
    thismonth: 'This month', lastmonth: 'Last month', thisyear: 'This year', custom: 'Custom range',
  })[preset];

  return (
    <div>
      <PageHeader title="Reports" eyebrow="Analytics" sub={`Showing data for ${presetLabel} · ${range.from.toLocaleDateString('en-GB', { timeZone: 'Asia/Kathmandu' })} → ${range.to.toLocaleDateString('en-GB', { timeZone: 'Asia/Kathmandu' })}`} />

      {/* Date + filter bar */}
      <Card flat style={{ marginBottom: 14 }}>
        <div className="pt-row" style={{ gap: 8, flexWrap: 'wrap' }}>
          {['today', 'yesterday', 'last7', 'last30', 'thismonth', 'lastmonth', 'thisyear', 'custom'].map(k => (
            <Button key={k} size="sm" variant={preset === k ? 'gold' : 'ghost'} onClick={() => setPreset(k)}>
              {({today:'Today',yesterday:'Yesterday',last7:'Last 7d',last30:'Last 30d',thismonth:'This month',lastmonth:'Last month',thisyear:'This year',custom:'Custom'})[k]}
            </Button>
          ))}
        </div>
        {preset === 'custom' && (
          <div className="pt-row" style={{ gap: 10, marginTop: 12 }}>
            <Input label="From" type="date" value={customFrom} onChange={setCustomFrom} />
            <Input label="To" type="date" value={customTo} onChange={setCustomTo} />
          </div>
        )}
        <div className="pt-row" style={{ gap: 10, marginTop: 12, flexWrap: 'wrap' }}>
          <Select label="Property" value={propertyF} onChange={setPropertyF} options={[{value:'all',label:'All properties'}, 'Biratchowk', 'Damak']} />
          <Select label="Tier" value={tierF} onChange={setTierF} options={[{value:'all',label:'All tiers'}, {value:'wellness',label:'Wellness'}, {value:'gold',label:'Gold'}, {value:'silver',label:'Silver'}]} />
          <div style={{ flex: 1, minWidth: 240 }}>
            <Input
              label="Search by member · name · ID · card # · phone"
              value={memberSearch}
              onChange={setMemberSearch}
              placeholder="leave blank for all members"
              hint={memberSearch ? `${memFiltered.length} member(s) match — all widgets filter to these.` : ''}
            />
          </div>
          {memberSearch && (
            <Button size="sm" variant="ghost" onClick={() => setMemberSearch('')} style={{ marginTop: 18 }}>Clear member filter</Button>
          )}
        </div>
      </Card>

      {/* Top-line cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 14 }}>
        <ReportTile label="New enrolments" value={enrolmentsInRange.length} sub="in range" icon="✚" />
        <ReportTile label="Bills posted" value={billsInRange.length} sub={`NPR ${grossTotal.toLocaleString()} gross`} icon="🧾" />
        <ReportTile label="Member discount" value={`NPR ${discountTotal.toLocaleString()}`} sub="given to members" icon="%" />
        <ReportTile label="VAT collected" value={`NPR ${vatTotal.toLocaleString()}`} sub="for tax filing" icon="◇" />
      </div>

      {/* Anti-fraud flags */}
      {fraudFlags.length > 0 && (
        <Card flat style={{ marginBottom: 14, borderColor: 'rgba(239,68,68,0.3)' }}>
          <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 8 }}>
            <h3 className="pt-h3" style={{ color: '#fca5a5' }}>⚠ Anti-fraud flags · {fraudFlags.length}</h3>
            <span className="pt-faint" style={{ fontSize: 12 }}>cross-property + over-cap discount in range</span>
          </div>
          <div className="pt-col" style={{ gap: 6, maxHeight: 200, overflowY: 'auto' }}>
            {fraudFlags.slice(0, 30).map((f, i) => (
              <div key={i} style={{ padding: '6px 10px', background: 'rgba(239,68,68,0.06)', borderRadius: 6, fontSize: 12 }}>
                <Badge>{f.type}</Badge> <b>{f.member || f.memberId}</b> — <span className="pt-mute">{f.detail}</span>
              </div>
            ))}
          </div>
        </Card>
      )}

      {/* Per-outlet revenue + VAT */}
      <Card flat style={{ marginBottom: 14 }}>
        <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 10 }}>
          <h3 className="pt-h3">Revenue by outlet</h3>
          <Button size="sm" onClick={() => exportCSV('vat')}>⤓ VAT summary CSV</Button>
        </div>
        {Object.keys(revenueByOutlet).length === 0 ? (
          <div className="pt-faint" style={{ padding: 14, fontSize: 13 }}>No bills posted in this range.</div>
        ) : (
          <table className="pt-table" style={{ fontSize: 13 }}>
            <thead><tr><th>Outlet</th><th>Property</th><th>Bills</th><th style={{ textAlign: 'right' }}>Gross</th><th style={{ textAlign: 'right' }}>Discount</th><th style={{ textAlign: 'right' }}>Net</th><th style={{ textAlign: 'right' }}>VAT</th></tr></thead>
            <tbody>
              {Object.entries(revenueByOutlet).map(([name, v]) => (
                <tr key={name}>
                  <td>{name}</td>
                  <td className="pt-mute">{v.property}</td>
                  <td className="pt-num">{v.count}</td>
                  <td className="pt-num" style={{ textAlign: 'right' }}>{v.gross.toLocaleString()}</td>
                  <td className="pt-num" style={{ textAlign: 'right' }}>{v.discount.toLocaleString()}</td>
                  <td className="pt-num" style={{ textAlign: 'right' }}>{v.net.toLocaleString()}</td>
                  <td className="pt-num" style={{ textAlign: 'right', color: T.gold }}>{v.vat.toLocaleString()}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </Card>

      {/* CSV export grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
        <ExportCard icon="✚" label="Enrolments in range" count={enrolmentsInRange.length} onExport={() => exportCSV('enrolments')} />
        <ExportCard icon="✓" label="Redemptions in range" count={redemptionsInRange.length} onExport={() => exportCSV('redemptions')} />
        <ExportCard icon="🧾" label="Bills in range" count={billsInRange.length} onExport={() => exportCSV('bills')} />
        <ExportCard icon="★" label="Top spenders (lifetime)" count={topSpenders.length} onExport={() => exportCSV('topspenders')} />
        <ExportCard icon="⏱" label="Churn risk · no visit 60d+" count={churnRisk.length} onExport={() => exportCSV('churn')} />
        <ExportCard icon="⏱" label="Audit log in range" count={audit.filter(a => inRange(a.ts, range)).length} onExport={() => exportCSV('audit')} />
      </div>
    </div>
  );
}

function ReportTile({ label, value, sub, icon }) {
  return (
    <Card flat>
      <div className="pt-row" style={{ gap: 10 }}>
        <div style={{ width: 38, height: 38, borderRadius: 10, background: T.surface3, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18 }}>{icon}</div>
        <div className="pt-col" style={{ lineHeight: 1.2 }}>
          <div className="pt-faint" style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{label}</div>
          <div className="pt-display pt-num" style={{ fontSize: 20 }}>{value}</div>
          {sub && <div className="pt-faint" style={{ fontSize: 11 }}>{sub}</div>}
        </div>
      </div>
    </Card>
  );
}
function ExportCard({ icon, label, count, onExport }) {
  return (
    <Card flat>
      <div className="pt-row" style={{ gap: 12 }}>
        <div style={{ width: 40, height: 40, borderRadius: 10, background: T.surface3, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 20 }}>{icon}</div>
        <div className="pt-col" style={{ flex: 1, lineHeight: 1.3 }}>
          <div style={{ fontWeight: 600, fontSize: 13 }}>{label}</div>
          <div className="pt-faint pt-num" style={{ fontSize: 11 }}>{count} row{count === 1 ? '' : 's'}</div>
        </div>
        <Button size="sm" onClick={onExport} disabled={count === 0}>⤓ CSV</Button>
      </div>
    </Card>
  );
}

function countBirthdays(members, days) {
  const today = new Date();
  return members.filter(m => {
    if (!m.dob) return false;
    const [y, mo, d] = m.dob.split('-').map(Number);
    const next = new Date(today.getFullYear(), mo - 1, d);
    if (next < today) next.setFullYear(today.getFullYear() + 1);
    return Math.round((next - today) / 86400000) <= days;
  }).length;
}
function countAnniversaries(members, days) {
  const today = new Date();
  return members.filter(m => {
    if (!m.anniversary || m.type !== 'wellness') return false;
    const [mo, d] = m.anniversary.split('-').map(Number);
    const next = new Date(today.getFullYear(), mo - 1, d);
    if (next < today) next.setFullYear(today.getFullYear() + 1);
    return Math.round((next - today) / 86400000) <= days;
  }).length;
}

// ═══════════════════════════════════════════════════════════════
// AUDIT LOG
// ═══════════════════════════════════════════════════════════════

function AuditScreen() {
  const audit = useStore(s => s.audit);
  const members = useStore(s => s.members);
  const memberById = React.useMemo(() => Object.fromEntries(members.map(m => [m.id, m])), [members]);
  const toast = useToast();
  const confirmDlg = useConfirm();
  const [filter, setFilter] = React.useState('');
  const [editing, setEditing] = React.useState(null);  // entry being edited

  const canEdit = Store.can('audit-edit');

  const filtered = audit.filter(a => {
    if (!filter) return true;
    const m = memberById[a.memberId];
    return [a.who, a.role, a.property, a.action, a.memberId, m && m.name].filter(Boolean).join(' ').toLowerCase().includes(filter.toLowerCase());
  });

  async function doDelete(a) {
    const ok = await confirmDlg(`"${a.action}"`, { title: 'Delete audit entry?', danger: true, confirmLabel: 'Delete' });
    if (!ok) return;
    const res = Store.deleteAudit(a.id);
    if (res.ok) toast.show('Audit entry deleted');
    else toast.show(res.error, { bad: true });
  }

  return (
    <div>
      <PageHeader title="Audit log" eyebrow="Activity"
        sub={canEdit
          ? `${audit.length} actions logged · Super Admin can edit or delete entries (the change itself is logged).`
          : `${audit.length} actions logged · read-only for your role.`} />
      <Card flat style={{ marginBottom: 14 }}>
        <input className="pt-input" placeholder="Filter by staff · member · action…" value={filter} onChange={e => setFilter(e.target.value)} />
      </Card>
      <Card flat style={{ padding: 0, overflow: 'hidden' }}>
        <div className="pt-table-scroll">
          <table className="pt-table">
            <thead><tr>
              <th>When</th><th>Staff</th><th>Role</th><th>Property</th><th>Action</th><th>Member</th>
              {canEdit && <th style={{ textAlign: 'right' }}>Actions</th>}
            </tr></thead>
            <tbody>
              {filtered.map(a => {
                const m = memberById[a.memberId];
                const isMeta = /^AUDIT (EDIT|DELETE)/i.test(a.action || '');
                return (
                  <tr key={a.id} style={isMeta ? { background: 'rgba(234,179,8,0.05)' } : undefined}>
                    <td className="pt-mute pt-num" style={{ whiteSpace: 'nowrap' }}>{fmtDateTime(a.ts)}</td>
                    <td style={{ fontWeight: 600 }}>{a.who}</td>
                    <td className="pt-mute">{a.role}</td>
                    <td className="pt-mute">{a.property}</td>
                    <td>
                      {isMeta && <Badge variant="gold" style={{ marginRight: 6 }}>meta</Badge>}
                      {a.action}
                    </td>
                    <td>
                      {m ? (
                        <span className="pt-row-link" onClick={() => navigate('members/' + a.memberId)}>
                          <span className="pt-num" style={{ color: m.type === 'wellness' ? T.gold : T.silver, fontWeight: 600 }}>{m.id}</span>
                          <span className="pt-mute"> · {m.name}</span>
                        </span>
                      ) : <span className="pt-faint">—</span>}
                    </td>
                    {canEdit && (
                      <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                        <Button size="sm" onClick={() => setEditing(a)}>✎ Edit</Button>
                        <Button size="sm" variant="danger" style={{ marginLeft: 4 }} onClick={() => doDelete(a)}>✕</Button>
                      </td>
                    )}
                  </tr>
                );
              })}
              {filtered.length === 0 && <tr><td colSpan={canEdit ? 7 : 6} className="pt-faint" style={{ textAlign: 'center', padding: 30 }}>Nothing matches.</td></tr>}
            </tbody>
          </table>
        </div>
      </Card>
      <AuditEditModal entry={editing} onClose={() => setEditing(null)}
        onSaved={() => toast.show('Audit entry updated · change recorded as a meta-entry')} />
    </div>
  );
}

function AuditEditModal({ entry, onClose, onSaved }) {
  const [text, setText] = React.useState('');
  React.useEffect(() => { setText(entry ? entry.action : ''); }, [entry]);
  if (!entry) return null;
  return (
    <Modal open title="Edit audit entry" onClose={onClose} width={520} footer={
      <>
        <Button variant="ghost" onClick={onClose}>Cancel</Button>
        <Button variant="gold" disabled={!text.trim() || text === entry.action} onClick={() => {
          const res = Store.editAudit(entry.id, text);
          if (res.ok) { onSaved(); onClose(); }
          else window._appNotify && window._appNotify(res.error, { icon: 'warn', title: 'Error' });
        }}>Save change</Button>
      </>
    }>
      <div className="pt-mute" style={{ fontSize: 13, marginBottom: 10 }}>
        Editing this entry records a separate <b>AUDIT EDIT</b> meta-entry capturing the original text + who changed it.
      </div>
      <div className="pt-faint" style={{ fontSize: 12, marginBottom: 6 }}>
        {fmtDateTime(entry.ts)} · {entry.who} ({entry.role}) · {entry.property}
      </div>
      <textarea value={text} onChange={e => setText(e.target.value)} rows={4}
        style={{
          width: '100%', padding: 10, background: 'rgba(255,255,255,0.04)',
          color: T.text, border: '1px solid ' + T.borderSoft, borderRadius: 8, fontSize: 13,
        }} />
    </Modal>
  );
}

// ═══════════════════════════════════════════════════════════════
// SETTINGS (super-admin only)
// ═══════════════════════════════════════════════════════════════
function SettingsScreen() {
  const settings = useStore(s => s.settings || {});
  const toast = useToast();
  const [silverPct, setSilverPct] = React.useState(((settings.tierDiscountPct || {}).silver) ?? 10);
  const [goldPct, setGoldPct] = React.useState(((settings.tierDiscountPct || {}).gold) ?? 15);
  const [wellnessPct, setWellnessPct] = React.useState(((settings.tierDiscountPct || {}).wellness) ?? 20);
  const [vatPct, setVatPct] = React.useState(settings.vatPct ?? 13);
  const [earnPerNpr, setEarnPerNpr] = React.useState(((settings.loyalty || {}).earnPerNpr) ?? 1);
  const [redeemPerPoint, setRedeemPerPoint] = React.useState(((settings.loyalty || {}).redeemPerPoint) ?? 0.01);
  const [minRedeemPts, setMinRedeemPts] = React.useState(((settings.loyalty || {}).minRedeemPts) ?? 100);
  const [dateSystem, setDateSystem] = React.useState(settings.dateSystem || 'AD');

  if (!Store.can('manage-roles') && !Store.can('manage')) {
    return <Card flat><div className="pt-mute">You don't have permission to access settings.</div></Card>;
  }

  function save() {
    const s = Number(silverPct), g = Number(goldPct), w = Number(wellnessPct);
    if ([s, g, w].some(x => x < 0 || x > 100)) return toast.show('Discount % must be 0-100', { bad: true });
    Store.updateSettings({
      tierDiscountPct: { silver: s, gold: g, wellness: w },
      vatPct: Number(vatPct),
      loyalty: { earnPerNpr: Number(earnPerNpr), redeemPerPoint: Number(redeemPerPoint), minRedeemPts: Number(minRedeemPts) },
      dateSystem,
    });
    toast.show('Settings saved · changes take effect immediately');
  }

  return (
    <div>
      <PageHeader title="Settings" eyebrow="Configuration" sub="Tier discounts · loyalty points · VAT · date system. Changes are audit-logged.">
        <Button variant="gold" onClick={save}>Save settings</Button>
      </PageHeader>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <Card flat>
          <h3 className="pt-h3" style={{ marginBottom: 12 }}>Tier discount %</h3>
          <div className="pt-mute" style={{ fontSize: 13, marginBottom: 12 }}>
            Default member discount applied on F&B and rooms. Staff can apply this at point of sale; super admins with the
            <code> override-discount </code> permission can exceed the cap on a per-bill basis.
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
            <Input label="Silver tier %" value={silverPct} onChange={setSilverPct} hint="default 10%" />
            <Input label="Gold tier %" value={goldPct} onChange={setGoldPct} hint="default 15%" />
            <Input label="Wellness tier %" value={wellnessPct} onChange={setWellnessPct} hint="default 20%" />
          </div>
        </Card>

        <Card flat>
          <h3 className="pt-h3" style={{ marginBottom: 12 }}>Loyalty points</h3>
          <div className="pt-mute" style={{ fontSize: 13, marginBottom: 12 }}>
            Members earn points on every bill. They can redeem points against future bills.
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
            <Input label="Earn per NPR" value={earnPerNpr} onChange={setEarnPerNpr} hint="1.0 = 1 pt / NPR" />
            <Input label="NPR per point" value={redeemPerPoint} onChange={setRedeemPerPoint} hint="0.01 = 100 pts / NPR" />
            <Input label="Min redeem pts" value={minRedeemPts} onChange={setMinRedeemPts} hint="floor per redemption" />
          </div>
        </Card>

        <Card flat>
          <h3 className="pt-h3" style={{ marginBottom: 12 }}>Tax</h3>
          <Input label="Default VAT %" value={vatPct} onChange={setVatPct} hint="applies to new outlets · existing outlets keep their own" />
        </Card>

        <Card flat>
          <h3 className="pt-h3" style={{ marginBottom: 12 }}>Date display</h3>
          <Select label="Calendar system" value={dateSystem} onChange={setDateSystem}
            options={[
              { value: 'AD', label: 'AD (Gregorian) · default' },
              { value: 'BS', label: 'BS (Bikram Sambat) · alongside AD' },
            ]} />
          <div className="pt-faint" style={{ fontSize: 11, marginTop: 8 }}>
            BS dates are shown next to AD dates throughout the app. Internal storage remains AD-ISO for compatibility.
          </div>
        </Card>
      </div>

      <OutletsManagement />

      <Card flat style={{ marginTop: 14 }}>
        <h3 className="pt-h3" style={{ marginBottom: 10 }}>What's coming (deferred)</h3>
        <ul className="pt-mute" style={{ fontSize: 12, lineHeight: 1.8, paddingLeft: 18 }}>
          <li>2FA for super admin (TOTP via authenticator apps)</li>
          <li>R2 image storage for photos + payment proofs (currently base64 in D1)</li>
          <li>SMS notifications (needs Twilio/Nepali gateway signup)</li>
          <li>Email reports (needs SendGrid signup)</li>
          <li>Daily D1 → R2 backup cron</li>
          <li>Full Nepali language UI</li>
        </ul>
      </Card>
    </div>
  );
}

// ─── Outlets management (Settings) ─────────────────────────────
function OutletsManagement() {
  const outlets = useStore(s => s.outlets || []);
  const toast = useToast();
  const confirmDlg = useConfirm();
  const [adding, setAdding] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const grouped = { Biratchowk: [], Damak: [] };
  outlets.forEach(o => { (grouped[o.property] = grouped[o.property] || []).push(o); });

  return (
    <Card flat style={{ marginTop: 14 }}>
      <div className="pt-row" style={{ justifyContent: 'space-between', marginBottom: 12, alignItems: 'center' }}>
        <h3 className="pt-h3">Outlets · F&B + rooms + wellness</h3>
        <Button variant="gold" size="sm" onClick={() => setAdding(true)}>+ Add outlet</Button>
      </div>
      <div className="pt-mute" style={{ fontSize: 13, marginBottom: 12 }}>
        F&B discount and bill flow use this list. Add a property dropdown so each outlet is mapped to Biratchowk or Damak.
      </div>
      {Object.entries(grouped).map(([prop, list]) => (
        <div key={prop} style={{ marginBottom: 16 }}>
          <div className="pt-eyebrow" style={{ marginBottom: 6 }}>◆ {prop} · {list.length} outlets</div>
          {list.length === 0 ? (
            <div className="pt-faint" style={{ fontSize: 12, padding: 8 }}>No outlets at this property yet.</div>
          ) : (
            <div className="pt-table-scroll">
              <table className="pt-table">
                <thead><tr><th>Name</th><th>Kind</th><th>Tax %</th><th>Service %</th><th>Active</th><th></th></tr></thead>
                <tbody>
                  {list.map(o => (
                    <tr key={o.id}>
                      <td style={{ fontWeight: 600 }}>{o.name}</td>
                      <td className="pt-mute">{o.kind}</td>
                      <td className="pt-num">{o.taxPct}%</td>
                      <td className="pt-num">{o.serviceChargePct}%</td>
                      <td>{o.active === false ? <Badge variant="bad">disabled</Badge> : <Badge variant="good">active</Badge>}</td>
                      <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                        <Button size="sm" onClick={() => setEditing(o)}>Edit</Button>
                        <Button size="sm" variant="danger" style={{ marginLeft: 4 }}
                          onClick={async () => {
                            const ok = await confirmDlg(`Existing bills will keep "${o.name}" in their records.`, { title: `Remove outlet "${o.name}"?`, danger: true, confirmLabel: 'Remove' });
                            if (ok) { Store.deleteOutlet(o.id); toast.show('Outlet removed'); }
                          }}>✕</Button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      ))}
      <OutletFormModal open={adding || !!editing} outlet={editing}
        onClose={() => { setAdding(false); setEditing(null); }}
        onSaved={() => toast.show('Outlet saved')} />
    </Card>
  );
}

function OutletFormModal({ open, outlet, onClose, onSaved }) {
  const isEdit = !!outlet;
  const [name, setName] = React.useState('');
  const [property, setProperty] = React.useState('Biratchowk');
  const [kind, setKind] = React.useState('fnb');
  const [taxPct, setTaxPct] = React.useState(13);
  const [servicePct, setServicePct] = React.useState(10);
  React.useEffect(() => {
    if (outlet) {
      setName(outlet.name || ''); setProperty(outlet.property || 'Biratchowk');
      setKind(outlet.kind || 'fnb'); setTaxPct(outlet.taxPct ?? 13); setServicePct(outlet.serviceChargePct ?? 10);
    } else if (open) {
      setName(''); setProperty('Biratchowk'); setKind('fnb'); setTaxPct(13); setServicePct(10);
    }
  }, [outlet, open]);
  if (!open) return null;
  return (
    <Modal open title={isEdit ? `Edit outlet · ${outlet.name}` : 'Add outlet'} onClose={onClose} width={520} footer={
      <>
        <Button variant="ghost" onClick={onClose}>Cancel</Button>
        <Button variant="gold" disabled={!name.trim() || !property}
          onClick={() => {
            const data = { name: name.trim(), property, kind, taxPct: Number(taxPct), serviceChargePct: Number(servicePct) };
            if (isEdit) Store.updateOutlet(outlet.id, data);
            else Store.addOutlet(data);
            onSaved(); onClose();
          }}>{isEdit ? 'Save changes' : '+ Add outlet'}</Button>
      </>
    }>
      <div className="pt-col" style={{ gap: 12 }}>
        <Input label="Outlet name *" value={name} onChange={setName} placeholder="e.g. Chiya Cafe" />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <Select label="Property *" value={property} onChange={setProperty} options={['Biratchowk', 'Damak']} />
          <Select label="Kind" value={kind} onChange={setKind} options={[
            { value: 'fnb', label: 'F&B (food + beverage)' },
            { value: 'rooms', label: 'Rooms' },
            { value: 'wellness', label: 'Wellness / Spa' },
          ]} />
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <Input label="Tax / VAT %" value={taxPct} onChange={setTaxPct} hint="usually 13" />
          <Input label="Service charge %" value={servicePct} onChange={setServicePct} hint="usually 10" />
        </div>
      </div>
    </Modal>
  );
}

Object.assign(window, { PageHeader, Stat, BarChart, DonutChart,
  DashboardScreen, MembersScreen, ReportsScreen, AuditScreen, SettingsScreen,
  OutletsManagement, OutletFormModal,
  dateRange, inRange, ReportTile, ExportCard });
