// Scheduler page — cron jobs (weekly report) + reminders + scheduled messages.

const CRONS = [
  { id: 'cron_weekly_report', name: 'Weekly shift report', schedule: '0 20 * * 0', next: 'Sun 20:00', desc: 'Send weekly report to #bot-log', last: 'Y-7 20:00 · ok', enabled: true, owner: 'system' },
  { id: 'cron_sheets_sync', name: 'Sheets sync', schedule: '*/5 * * * *', next: 'in 3m', desc: 'Mirror shift log to Google Sheets', last: '2m ago · 187 rows', enabled: true, owner: 'system' },
  { id: 'cron_idle_clockout', name: 'Auto clock-out idle', schedule: '0 0 * * *', next: 'Tonight 00:00', desc: 'Close shifts open >12h', last: 'Y-1 00:00 · 3 closed', enabled: true, owner: 'system' },
  { id: 'cron_health', name: 'Self health-check', schedule: '*/10 * * * *', next: 'in 7m', desc: 'Ping gateway, alert if > 200ms', last: '3m ago · ok', enabled: true, owner: 'system' },
  { id: 'cron_backup', name: 'Daily backup', schedule: '0 3 * * *', next: 'Tomorrow 03:00', desc: 'Snapshot Sheets + settings', last: 'Today 03:00 · 4.2 MB', enabled: true, owner: 'system' },
  { id: 'cron_reset_warns', name: 'Warn memory reset', schedule: '0 4 * * 1', next: 'Mon 04:00', desc: 'Clear in-memory warns weekly', last: 'Mon 04:00 · ok', enabled: false, owner: 'system' },
];

const REMINDERS = [
  { id: 'rem_1', user: 'ake', when: 'in 2h 14m', text: 'patrol report ส่งให้ admin', set: '12:30', guild: 'Pacific Logistics' },
  { id: 'rem_2', user: 'nine', when: 'tomorrow 09:00', text: 'meeting ที่ HQ', set: 'Y-1 18:20', guild: 'Bangkok Underground' },
  { id: 'rem_3', user: 'noi', when: 'in 38m', text: 'หมดเวลาพัก กลับเข้างาน', set: '13:50', guild: 'Bangkok Underground' },
  { id: 'rem_4', user: 'pim', when: 'Fri 17:00', text: 'ส่ง weekly hours', set: 'Y-2 09:14', guild: 'Pacific Logistics' },
  { id: 'rem_5', user: 'tar', when: 'in 1h 02m', text: 'check ammo locker', set: '11:00', guild: 'Highway Patrol HQ' },
];

const SCHEDULED_POSTS = [
  { id: 'msg_1', when: 'Fri 18:00', channel: '#announcements', guild: 'Pacific Logistics', text: 'Reminder: weekly hours due by Sunday EOD.' },
  { id: 'msg_2', when: 'Sun 20:30', channel: '#bot-log', guild: 'Pacific Logistics', text: 'Weekly stats summary auto-posts after weekly report.' },
];

function PageScheduler() {
  const [enabled, setEnabled] = React.useState(() => Object.fromEntries(CRONS.map((c) => [c.id, c.enabled])));
  const activeCount = Object.values(enabled).filter(Boolean).length;
  const conn = useConn();
  const live = conn.status === 'connected';
  const cronAction = { cron_weekly_report: 'weeklyreport', cron_sheets_sync: 'sheetstyle' };

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">Scheduler</h1>
          <div className="page-sub">{activeCount} active jobs · {REMINDERS.length} reminders queued · {SCHEDULED_POSTS.length} scheduled posts</div>
        </div>
      </div>

      <div className="grid grid-3">
        <StatCard label="Active jobs" value={activeCount} delta={`${CRONS.length - activeCount} disabled`} spark={[3,3,4,4,5,5,5]}/>
        <StatCard label="Runs · 24h" value="312" delta="0 failed" deltaDir="up" spark={[12,28,42,38,52,48,60,72]}/>
        <StatCard label="Avg duration" value="184ms" delta="p99 824ms" spark={[180,170,200,160,210,180,184]} sparkColor="var(--violet)"/>
      </div>

      <Card title="Cron jobs" sub="schedule expressed as standard cron syntax" padding={0}>
        <table className="tbl">
          <thead>
            <tr>
              <th>Name</th>
              <th>Schedule</th>
              <th>Next run</th>
              <th>Last result</th>
              <th style={{ width: 80 }}></th>
            </tr>
          </thead>
          <tbody>
            {CRONS.map((c) => (
              <tr key={c.id}>
                <td>
                  <div>
                    <div>{c.name}</div>
                    <div className="muted" style={{ fontSize: 11.5 }}>{c.desc}</div>
                  </div>
                </td>
                <td className="mono" style={{ fontSize: 12 }}>{c.schedule}</td>
                <td className="mono muted">{c.next}</td>
                <td className="mono muted" style={{ fontSize: 11.5 }}>{c.last}</td>
                <td className="row" style={{ gap: 4 }}>
                  {cronAction[c.id] && (
                    <button className="btn" style={{ padding: '3px 8px', fontSize: 11 }} disabled={!live} onClick={() => REALDATA.doAction(cronAction[c.id]).then(()=>toast('ส่งแล้ว','success')).catch(e=>toast(e.message,'error'))}>Run now</button>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>

      <div className="grid grid-12-5">
        <Card title="Reminders" sub="user-set via /remind · cleared on bot restart" padding={0}>
          <table className="tbl">
            <thead><tr><th>User</th><th>Reminder</th><th>Fires</th><th>Guild</th></tr></thead>
            <tbody>
              {REMINDERS.map((r) => (
                <tr key={r.id}>
                  <td>
                    <div className="row">
                      <div style={{ width: 22, height: 22, borderRadius: 999, background: `hsl(${r.user.charCodeAt(0) * 9} 70% 60%)` }}/>
                      <span style={{ fontSize: 12.5 }}>{r.user}</span>
                    </div>
                  </td>
                  <td className="ellipsis" style={{ maxWidth: 220 }}>{r.text}</td>
                  <td className="mono" style={{ color: 'var(--accent)' }}>{r.when}</td>
                  <td className="muted" style={{ fontSize: 12 }}>{r.guild}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>

        <Card title="Scheduled posts" padding={0}>
          <table className="tbl">
            <thead><tr><th>When</th><th>Where</th></tr></thead>
            <tbody>
              {SCHEDULED_POSTS.map((p) => (
                <tr key={p.id}>
                  <td className="mono muted">{p.when}</td>
                  <td>
                    <div className="mono" style={{ fontSize: 12 }}>{p.channel}</div>
                    <div className="muted ellipsis" style={{ fontSize: 11.5, maxWidth: 240 }}>{p.text}</div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Requests page — pending approvals from `/request` and `/need`

const REQUESTS = [
  { id: 'r_192', house: 'บ้าน Yamamoto', requester: 'ake', kind: 'item', text: 'ขออาวุธยุทโธปกรณ์เพิ่ม · 4 ชุด', priority: 'high', status: 'pending', created: '12m ago' },
  { id: 'r_191', house: 'บ้าน Tanaka', requester: 'noi', kind: 'help', text: 'ต้องการกำลังเสริมที่ Patrol 3', priority: 'urgent', status: 'pending', created: '38m ago' },
  { id: 'r_190', house: 'บ้าน Yamamoto', requester: 'pim', kind: 'item', text: 'ยา First-Aid 10 ชุด', priority: 'normal', status: 'pending', created: '1h ago' },
  { id: 'r_189', house: 'บ้าน Tanaka', requester: 'tar', kind: 'help', text: 'รถพยาบาลให้ Patrol 1', priority: 'high', status: 'approved', created: '2h ago', resolver: 'ake' },
  { id: 'r_188', house: 'บ้าน Yamamoto', requester: 'bell', kind: 'item', text: 'กุญแจสำรอง office', priority: 'low', status: 'denied', created: '3h ago', resolver: 'ake' },
  { id: 'r_187', house: 'บ้าน Tanaka', requester: 'kong', kind: 'help', text: 'ขอ backup ที่ checkpoint A', priority: 'urgent', status: 'approved', created: '5h ago', resolver: 'nine' },
];

// "Xm ago" / "Xh ago" from an epoch-ms timestamp.
function relTime(ms) {
  const n = Number(ms);
  if (!n) return '—';
  const s = Math.max(0, Math.floor((Date.now() - n) / 1000));
  if (s < 60) return s + 's ago';
  if (s < 3600) return Math.floor(s / 60) + 'm ago';
  if (s < 86400) return Math.floor(s / 3600) + 'h ago';
  return Math.floor(s / 86400) + 'd ago';
}

function PageRequests() {
  const [tab, setTab] = React.useState('pending');
  const conn = useConn();
  useRealData(); // re-render on real-data refresh
  const live = conn.status === 'connected';

  // Normalize a status from either real or mock data to 'pending'|'approved'|'denied'.
  const normStatus = (s) => String(s || '').toLowerCase();
  // Map house key → Thai label (REQUEST_CONFIG.HOUSES may not exist on frontend).
  const houseLabel = (h) => (h === 'twin' ? 'บ้านแฝด' : h === 'new' ? 'บ้านใหม่' : (h || '—'));

  // Use real requests when connected (even if empty → show empty state, don't crash).
  const realRequests = (REALDATA.requests || []).map((r) => ({
    id: r.id,
    house: houseLabel(r.house),
    requester: (r.requester && (r.requester.displayName || r.requester.username)) || '—',
    requesterAvatar: r.requester && r.requester.avatarURL,
    kind: r.quantity ? ('×' + r.quantity) : 'request',
    text: r.details || '',
    priority: 'normal',
    status: normStatus(r.status),
    created: relTime(r.createdAt),
    resolver: (r.decider && (r.decider.username || r.decider.displayName || r.decider.id)) || '—',
  }));
  // Mock array: normalize status so both sources filter identically.
  const mockRequests = REQUESTS.map((r) => ({ ...r, status: normStatus(r.status) }));
  const source = live ? realRequests : mockRequests;

  const list = source.filter((r) => tab === 'all' || r.status === tab);
  const pending = source.filter((r) => r.status === 'pending').length;
  const approved = source.filter((r) => r.status === 'approved').length;
  const denied = source.filter((r) => r.status === 'denied').length;
  const total = source.length;

  const prioColor = { urgent: 'var(--danger)', high: 'var(--warn)', normal: 'var(--info)', low: 'var(--text-muted)' };
  const statusChip = {
    pending: <span className="chip warn">pending</span>,
    approved: <span className="chip solid">approved</span>,
    denied: <span className="chip danger">denied</span>,
  };

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">Requests</h1>
          <div className="page-sub">Approval queue from /request and /need · across all houses</div>
        </div>
        <div className="row">
          <button className="btn" onClick={() => {
            const esc = (v) => '"' + String(v == null ? '' : v).replace(/"/g, '""') + '"';
            const header = ['id', 'house', 'requester', 'details', 'quantity', 'status', 'createdAt'];
            const rows = list.map((r) => [r.id, r.house, r.requester, r.text, r.kind, r.status, r.created]);
            const csv = [header, ...rows].map((cols) => cols.map(esc).join(',')).join('\n');
            const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url; a.download = 'requests.csv';
            document.body.appendChild(a); a.click();
            document.body.removeChild(a); URL.revokeObjectURL(url);
          }}>Export</button>
          <button className="btn primary" disabled={!live} onClick={async () => {
            const pending = (REALDATA.requests||[]).filter(x => x.status==='pending');
            if (!pending.length) return toast('ไม่มีคำขอที่รออนุมัติ', 'warning');
            if (!(await toastConfirm('อนุมัติ ' + pending.length + ' คำขอทั้งหมด?'))) return;
            for (const x of pending) { try { await REALDATA.requestAction(x.id, 'approve'); } catch(e){} }
            REALDATA.refreshAll();
          }}>Bulk approve…</button>
        </div>
      </div>

      <div className="grid grid-4">
        <StatCard label="Pending" value={pending} delta={live ? '' : '3 urgent'} deltaDir="up" sparkColor="var(--warn)" spark={[2,3,3,4,4,3,3]}/>
        <StatCard label="Approved · 7d" value={live ? approved : approved + 14} delta={live ? '' : 'avg 18m to resolve'} deltaDir="up" spark={[1,2,3,2,4,3,3]}/>
        <StatCard label="Denied · 7d" value={live ? denied : denied + 4} sparkColor="var(--danger)" spark={[1,0,1,0,1,1,0]}/>
        <StatCard label="Total" value={source.length} delta={live ? 'live' : '2 idle'} spark={[3,4,4,4,4,4,4]} sparkColor="var(--violet)"/>
      </div>

      <div className="tabs">
        <button className="tab" aria-current={tab === 'all'} onClick={() => setTab('all')}>All ({total})</button>
        <button className="tab" aria-current={tab === 'pending'} onClick={() => setTab('pending')}>Pending ({pending})</button>
        <button className="tab" aria-current={tab === 'approved'} onClick={() => setTab('approved')}>Approved ({approved})</button>
        <button className="tab" aria-current={tab === 'denied'} onClick={() => setTab('denied')}>Denied ({denied})</button>
      </div>

      <Card padding={0}>
        <table className="tbl">
          <thead>
            <tr>
              <th></th>
              <th>Request</th>
              <th>House</th>
              <th>By</th>
              <th>Created</th>
              <th>Status</th>
              <th style={{ width: 140 }}></th>
            </tr>
          </thead>
          <tbody>
            {list.map((r) => (
              <tr key={r.id}>
                <td><span style={{ width: 8, height: 8, borderRadius: 999, background: prioColor[r.priority], display: 'inline-block' }} title={r.priority}/></td>
                <td>
                  <div>{r.text}</div>
                  <div className="muted mono" style={{ fontSize: 11 }}>{r.id} · {r.kind}</div>
                </td>
                <td>{r.house}</td>
                <td>{r.requester}</td>
                <td className="muted">{r.created}</td>
                <td>{statusChip[r.status]}</td>
                <td>
                  {r.status === 'pending' ? (
                    <div className="row" style={{ gap: 4 }}>
                      <button className="btn primary" style={{ padding: '3px 8px', fontSize: 11 }} disabled={!live} onClick={() => REALDATA.requestAction(r.id, 'approve').then(()=>toast('อนุมัติแล้ว','success')).catch(e=>toast(e.message,'error'))}>Approve</button>
                      <button className="btn danger" style={{ padding: '3px 8px', fontSize: 11 }} disabled={!live} onClick={() => REALDATA.requestAction(r.id, 'deny').then(()=>toast('ปฏิเสธแล้ว','info')).catch(e=>toast(e.message,'error'))}>Deny</button>
                    </div>
                  ) : (
                    <span className="muted" style={{ fontSize: 11.5 }}>by {r.resolver}</span>
                  )}
                </td>
              </tr>
            ))}
            {list.length === 0 && (
              <tr><td colSpan={7} style={{ padding: 24, textAlign: 'center', color: 'var(--text-muted)' }}>
                ไม่มีคำขอ
              </td></tr>
            )}
          </tbody>
        </table>
      </Card>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Help dialog — ? to open

function HelpDialog({ open, onClose }) {
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;
  const shortcuts = [
    { keys: ['⌘', 'K'], desc: 'Open command palette' },
    { keys: ['/'], desc: 'Quick search' },
    { keys: ['?'], desc: 'This help' },
    { keys: ['Esc'], desc: 'Close any overlay' },
    { keys: ['G', 'O'], desc: 'Go to Overview' },
    { keys: ['G', 'S'], desc: 'Go to Servers' },
    { keys: ['G', 'C'], desc: 'Go to Commands' },
    { keys: ['G', 'H'], desc: 'Go to Shifts' },
    { keys: ['G', 'L'], desc: 'Go to Logs' },
    { keys: ['G', 'E'], desc: 'Go to Errors' },
    { keys: ['R'], desc: 'Refresh data' },
    { keys: ['T'], desc: 'Toggle theme' },
  ];
  return (
    <div className="palette-scrim" onClick={onClose}>
      <div className="palette" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 540 }}>
        <div className="palette-input">
          <span style={{ fontWeight: 600 }}>Keyboard shortcuts</span>
          <span style={{ flex: 1 }}/>
          <kbd>ESC</kbd>
        </div>
        <div style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          {shortcuts.map((s, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '6px 10px', borderRadius: 6 }}>
              <div className="row" style={{ gap: 3 }}>
                {s.keys.map((k) => <kbd key={k} style={{ fontFamily: 'var(--font-mono)', fontSize: 11, padding: '2px 6px', borderRadius: 4, background: 'var(--surface-2)', border: '1px solid var(--border)', color: 'var(--text)' }}>{k}</kbd>)}
              </div>
              <span style={{ flex: 1, fontSize: 12.5, color: 'var(--text-muted)' }}>{s.desc}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Onboarding banner — shown on Overview when not connected

function OnboardBanner({ onConnect }) {
  const conn = useConn();
  const [dismissed, setDismissed] = React.useState(false);
  if (conn.status === 'connected' || dismissed) return null;
  return (
    <div className="onboard-banner" style={{
      background: 'linear-gradient(135deg, color-mix(in oklab, var(--accent) 14%, var(--surface)), var(--surface))',
      border: '1px solid color-mix(in oklab, var(--accent) 30%, var(--border))',
      borderRadius: 10,
      padding: 16,
      display: 'flex',
      alignItems: 'center',
      gap: 14,
      flexWrap: 'wrap',
    }}>
      <div style={{ width: 38, height: 38, borderRadius: 10, background: 'var(--accent)', display: 'grid', placeItems: 'center', color: '#0a0b0d', flexShrink: 0 }}>
        <I.plug width="18" height="18"/>
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 2 }}>
          Connect your bot to see live data
        </div>
        <div style={{ fontSize: 12.5, color: 'var(--text-muted)' }}>
          Right now this dashboard is showing sample data. Add the adapter snippet to your bot and point this here in <strong>Settings → Connection</strong>.
        </div>
      </div>
      <button className="btn primary" onClick={onConnect}>Set up connection</button>
      <button className="btn" onClick={() => setDismissed(true)}>Hide</button>
    </div>
  );
}

Object.assign(window, { PageScheduler, PageRequests, HelpDialog, OnboardBanner, REQUESTS, CRONS });
