/* ============================================================
   page-oncall.jsx — On-call rotations per team (#26)
   ============================================================ */
const { useState, useEffect } = React;

function OnCallPage() {
  const [data, setData]       = useState({ current: [], upcoming: [], teams: [] });
  const [loading, setLoading] = useState(true);
  const [employees, setEmployees] = useState([]);
  const [teams, setTeams]     = useState([]);
  const [creating, setCreating] = useState(false);
  const toast = useToast ? useToast() : { push: () => {} };

  // Form state
  const [fTeam, setFTeam]   = useState('');
  const [fUser, setFUser]   = useState('');
  const [fStart, setFStart] = useState(new Date().toISOString().slice(0, 10));
  const [fEnd, setFEnd]     = useState(() => {
    const d = new Date(); d.setDate(d.getDate() + 6);
    return d.toISOString().slice(0, 10);
  });
  const [fRole, setFRole]   = useState('primary');
  const [fNotes, setFNotes] = useState('');
  const [uploading, setUploading] = useState(false);
  const fileRef = React.useRef(null);

  const reload = async () => {
    setLoading(true);
    try {
      const [r1, r2, r3] = await Promise.all([
        fetch('/api/on-call', { credentials: 'same-origin' }).then(r => r.json()),
        fetch('/api/employees', { credentials: 'same-origin' }).then(r => r.ok ? r.json() : []),
        fetch('/api/teams', { credentials: 'same-origin' }).then(r => r.ok ? r.json() : []),
      ]);
      setData(r1 || { current: [], upcoming: [], teams: [] });
      setEmployees(Array.isArray(r2) ? r2 : (r2.users || []));
      setTeams(Array.isArray(r3) ? r3 : []);
    } catch (e) {
      toast.push && toast.push({ msg: (window.appT||(s=>s))('Load failed: ') + e.message, kind: 'err' });
    } finally {
      setLoading(false);
    }
  };
  useEffect(() => { reload(); }, []);

  const downloadTemplate = () => {
    window.open('/api/on-call/template.csv', '_blank');
  };

  const onUploadFile = async (e) => {
    const f = e.target.files && e.target.files[0];
    if (f) await uploadSchedule(f);
    if (fileRef.current) fileRef.current.value = '';
  };

  const uploadSchedule = async (f) => {
    const replace = window.confirm(
      (window.appT||(s=>s))('Replace all future on-call shifts with this file?\n\nOK = replace future shifts · Cancel = append to existing')
    );
    setUploading(true);
    try {
      const fd = new FormData();
      fd.append('file', f);
      const r = await fetch('/api/on-call/upload?replace=' + (replace ? 'true' : 'false'), {
        method: 'POST', credentials: 'same-origin', body: fd,
      });
      const body = await r.json().catch(() => null);
      if (!r.ok) throw new Error(parseDetail(body, r.status));
      const errs = (body && body.errors) || [];
      toast.push({
        msg: (window.appLang && window.appLang() === 'ar'
          ? `تم استيراد ${body.created} مناوبة` + (errs.length ? ` · ${errs.length} مشكلة في الصفوف` : '')
          : `Imported ${body.created} shift${body.created === 1 ? '' : 's'}` + (errs.length ? ` · ${errs.length} row issue(s)` : '')),
        kind: errs.length ? 'warn' : 'ok',
      });
      if (errs.length) errs.slice(0, 6).forEach(m => toast.push({ msg: m, kind: 'warn' }));
      await reload();
    } catch (e) {
      toast.push({ msg: (window.appT||(s=>s))('Upload failed: ') + e.message, kind: 'err' });
    } finally {
      setUploading(false);
    }
  };

  const create = async () => {
    if (!fTeam || !fUser || !fStart || !fEnd) {
      toast.push({ msg: (window.appT||(s=>s))('Fill all required fields'), kind: 'warn' });
      return;
    }
    setCreating(true);
    try {
      const r = await fetch('/api/on-call', {
        method: 'POST',
        credentials: 'same-origin',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          team_name: fTeam, user_id: parseInt(fUser, 10),
          start_date: fStart, end_date: fEnd, role: fRole,
          notes: fNotes || null,
        }),
      });
      if (!r.ok) {
        const body = await r.json().catch(() => null);
        throw new Error(parseDetail(body, r.status));
      }
      toast.push({ msg: (window.appT||(s=>s))('On-call rotation created'), kind: 'ok' });
      setFNotes('');
      await reload();
    } catch (e) {
      toast.push({ msg: (window.appT||(s=>s))('Failed: ') + e.message, kind: 'err' });
    } finally {
      setCreating(false);
    }
  };

  const removeRotation = async (id) => {
    if (!confirm((window.appT||(s=>s))('Delete this on-call rotation?'))) return;
    try {
      const r = await fetch(`/api/on-call/${id}`, { method: 'DELETE', credentials: 'same-origin' });
      if (!r.ok) {
        const body = await r.json().catch(() => null);
        throw new Error(parseDetail(body, r.status));
      }
      toast.push({ msg: (window.appT||(s=>s))('Deleted'), kind: 'ok' });
      await reload();
    } catch (e) {
      toast.push({ msg: (window.appT||(s=>s))('Delete failed: ') + e.message, kind: 'err' });
    }
  };

  const renderRow = (r, allowDelete = true) => (
    <tr key={r.id}>
      <td style={{ padding: '8px 12px', fontSize: 13 }}>
        <strong>{r.team_name}</strong>
      </td>
      <td style={{ padding: '8px 12px', fontSize: 13 }}>{r.display_name}</td>
      <td style={{ padding: '8px 12px', fontSize: 12 }}>
        <Badge kind={r.role === 'primary' ? 'brand' : 'mute'}>{(window.appT||(s=>s))(r.role)}</Badge>
      </td>
      <td style={{ padding: '8px 12px', fontSize: 12, fontFamily: 'var(--font-mono)' }}>
        {r.start_date} → {r.end_date}
      </td>
      <td style={{ padding: '8px 12px', fontSize: 12, color: 'var(--text-2)' }}>
        {r.notes || '—'}
      </td>
      <td style={{ padding: '8px 12px', textAlign: 'right' }}>
        {allowDelete && (
          <button className="btn btn-ghost btn-icon" onClick={() => removeRotation(r.id)} title={(window.appT||(s=>s))("Delete")}>
            <Icon name="trash" size={12}/>
          </button>
        )}
      </td>
    </tr>
  );

  return (
    <div style={{ padding: 'var(--page-pad)', maxWidth: 1100, margin: '0 auto' }}>
      <PageHeader
        title={"📟 " + (window.appT||(s=>s))("On-call rotations")}
        meta={window.appLang && window.appLang() === 'ar'
          ? `${loading ? '…' : data.current.length} نشط · ${loading ? '…' : data.upcoming.length} قادم · تذكيرات الرسائل المباشرة 09:00 (يوم المناوبة) + 18:00 (اليوم السابق) بتوقيت UTC`
          : `${loading ? '…' : data.current.length} active · ${loading ? '…' : data.upcoming.length} upcoming · DM reminders 09:00 (day-of) + 18:00 (day-before) UTC`}
        right={
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <button className="btn btn-ghost" style={{ padding: '5px 11px', fontSize: 12 }}
              onClick={downloadTemplate} title={(window.appT||(s=>s))("Download a sample CSV (primary/backup/escalation + dates)")}>
              <Icon name="download" size={13}/> {(window.appT||(s=>s))("Sample CSV")}
            </button>
            <button className="btn btn-ghost" style={{ padding: '5px 11px', fontSize: 12 }}
              onClick={() => fileRef.current && fileRef.current.click()} disabled={uploading}
              title={(window.appT||(s=>s))("Upload a filled rotation CSV to update the calendar")}>
              <Icon name="plus" size={13}/> {uploading ? (window.appT||(s=>s))('Importing…') : (window.appT||(s=>s))('Upload schedule')}
            </button>
            <input ref={fileRef} type="file" accept=".csv,text/csv" style={{ display: 'none' }} onChange={onUploadFile} />
            <Refresh onClick={reload} loading={loading} />
          </div>
        }
      />

      {/* C5: month calendar grid */}
      <OnCallCalendarCard
        shifts={[...(data.current || []), ...(data.upcoming || [])]}
        employees={employees}
      />

      {/* On-call standings — moved here from the Reports tab so all
          on-call surface area lives together. The component itself is
          still defined in page-reports.jsx (window.OnCallStandingsSection)
          to avoid duplicating ~140 lines of fetch + render logic. */}
      {typeof window.OnCallStandingsSection === 'function' && (
        React.createElement(window.OnCallStandingsSection)
      )}

      {/* Active section */}
      <div className="card" style={{ marginBottom: 14 }}>
        <SectionHeader title={"🔴 " + (window.appT||(s=>s))("Currently on-call")}
          tip={(window.appT||(s=>s))("Primary + secondary on-call right now (per the active rotation). Auto-resolves on every ticket landing.")} sub={window.appLang && window.appLang() === 'ar'
            ? `${data.current.length} مناوبة نشطة`
            : `${data.current.length} active rotation${data.current.length === 1 ? '' : 's'}`} />
        {loading ? (
          <Loading rows={3} label={(window.appT||(s=>s))("Loading rotations…")} />
        ) : data.current.length === 0 ? (
          <Empty icon={<Icon name="alert" size={24}/>} title={(window.appT||(s=>s))("Nobody on-call right now")} subtitle={(window.appT||(s=>s))("Add a rotation below to assign someone.")} />
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--line)' }}>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Team")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Person")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Role")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Coverage")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Notes")}</th>
                  <th />
                </tr>
              </thead>
              <tbody>{data.current.map(r => renderRow(r))}</tbody>
            </table>
          </div>
        )}
      </div>

      {/* Upcoming section */}
      <div className="card" style={{ marginBottom: 14 }}>
        <SectionHeader title={"📅 " + (window.appT||(s=>s))("Upcoming (next 30 days)")}
          tip={(window.appT||(s=>s))("Next 30 days of on-call shifts. Edit any cell to override (admin only).")} sub={window.appLang && window.appLang() === 'ar'
            ? `${data.upcoming.length} مجدولة`
            : `${data.upcoming.length} scheduled`} />
        {loading ? (
          <Loading rows={3} label={(window.appT||(s=>s))("Loading schedule…")} />
        ) : data.upcoming.length === 0 ? (
          <Empty icon={<Icon name="calendar" size={24}/>} title={(window.appT||(s=>s))("No upcoming rotations")} subtitle={(window.appT||(s=>s))("Schedule the next rotation below.")} />
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--line)' }}>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Team")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Person")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Role")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Coverage")}</th>
                  <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{(window.appT||(s=>s))("Notes")}</th>
                  <th />
                </tr>
              </thead>
              <tbody>{data.upcoming.map(r => renderRow(r))}</tbody>
            </table>
          </div>
        )}
      </div>

      {/* Add rotation form */}
      <div className="card">
        <SectionHeader title={"➕ " + (window.appT||(s=>s))("Add rotation")}
          tip={(window.appT||(s=>s))("Single-shift add form. For bulk uploads use 'Import CSV' (#31). 'Export CSV' is available on the same page for round-tripping.")} sub={(window.appT||(s=>s))("Manager+ only")} />
        <div style={{ padding: 14, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 12 }}>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("Team")} *</span>
            <select className="inp" value={fTeam} onChange={e => setFTeam(e.target.value)}>
              <option value="">{(window.appT||(s=>s))("Pick a team…")}</option>
              {teams.map(t => <option key={t.team_name || t.id} value={t.team_name}>{t.team_name}</option>)}
            </select>
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("Person")} *</span>
            <select className="inp" value={fUser} onChange={e => setFUser(e.target.value)}>
              <option value="">{(window.appT||(s=>s))("Pick a person…")}</option>
              {employees.map(e => <option key={e.id} value={e.id}>{e.display_name}</option>)}
            </select>
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("Role")}</span>
            <select className="inp" value={fRole} onChange={e => setFRole(e.target.value)}>
              <option value="primary">{(window.appT||(s=>s))("Primary")}</option>
              <option value="backup">{(window.appT||(s=>s))("Backup")}</option>
              <option value="escalation">{(window.appT||(s=>s))("Escalation")}</option>
            </select>
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("Start date")} *</span>
            <input className="inp" type="date" value={fStart} onChange={e => setFStart(e.target.value)} />
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12 }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("End date")} *</span>
            <input className="inp" type="date" value={fEnd} onChange={e => setFEnd(e.target.value)} />
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, gridColumn: '1 / -1' }}>
            <span style={{ color: 'var(--text-2)' }}>{(window.appT||(s=>s))("Notes")}</span>
            <input className="inp" value={fNotes} onChange={e => setFNotes(e.target.value)} placeholder={(window.appT||(s=>s))("e.g. Customer escalation week — quarterly release")} />
          </label>
        </div>
        <div style={{ padding: '8px 14px 14px', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <button className="btn btn-pri" onClick={create} disabled={creating}>
            {creating ? '…' : <><Icon name="plus" size={13}/> {(window.appT||(s=>s))("Schedule rotation")}</>}
          </button>
        </div>
      </div>
    </div>
  );
}

// C5: month calendar grid with primary + secondary on each day.
function OnCallCalendarCard({ shifts, employees }) {
  const today = new Date();
  const [month, setMonth] = useState({ y: today.getFullYear(), m: today.getMonth() });
  const monthStart = new Date(month.y, month.m, 1);
  const monthEnd   = new Date(month.y, month.m + 1, 0);
  const startWeekday = monthStart.getDay(); // 0=Sun
  const daysInMonth = monthEnd.getDate();
  const empById = Object.fromEntries(employees.map(e => [e.id, e]));
  // Build per-day list of EVERY assigned person — was previously primary+
  // single secondary, which collapsed multi-tier fallback chains
  // (bassel→miro→hany) down to whoever happened to be written last and
  // looked like "only Hany". Now: bucket by primary / backup / escalation
  // and stack them all in the cell so the full chain is visible.
  const byDay = {};
  for (const s of (shifts || [])) {
    const sd = new Date(s.start_date), ed = new Date(s.end_date);
    for (let d = new Date(sd); d <= ed; d.setDate(d.getDate() + 1)) {
      if (d.getMonth() !== month.m || d.getFullYear() !== month.y) continue;
      const key = d.getDate();
      const role = (s.role || (s.is_primary ? 'primary' : 'backup'));
      const slot = (byDay[key] = byDay[key] || { primary: [], backup: [], escalation: [] });
      // Skip placeholder pre-imports — they're real OnCallShift rows but
      // have no real engineer yet (mxid starts with @_oncall-pending-).
      const emp = empById[s.user_id];
      const isPlaceholder = (emp?.matrix_id || '').startsWith('@_oncall-pending-');
      if (isPlaceholder) continue;
      const bucket = slot[role] || slot.backup;
      // Dedupe by user_id so the chain row + a weekly primary row that
      // refer to the same person don't render twice.
      if (!bucket.find(x => x.user_id === s.user_id)) bucket.push(s);
    }
  }
  const cells = [];
  for (let i = 0; i < startWeekday; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);
  while (cells.length % 7 !== 0) cells.push(null);
  const monthName = monthStart.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });
  return (
    <div className="card" style={{ marginBottom: 16 }}>
      <SectionHeader
        title={(window.appT||(s=>s))("On-call calendar")}
        tip={(window.appT||(s=>s))("Visual month view of primary + secondary on-call assignments. Click a shift to jump to its details. Use ← → to change months.")}
        sub={monthName}
        right={
          <div style={{ display: 'flex', gap: 4 }}>
            <button className="btn btn-ghost" style={{ padding: '3px 10px', fontSize: 12 }}
              onClick={() => setMonth(m => m.m === 0 ? { y: m.y - 1, m: 11 } : { y: m.y, m: m.m - 1 })}>←</button>
            <button className="btn btn-ghost" style={{ padding: '3px 10px', fontSize: 12 }}
              onClick={() => setMonth({ y: today.getFullYear(), m: today.getMonth() })}>{(window.appT||(s=>s))("Today")}</button>
            <button className="btn btn-ghost" style={{ padding: '3px 10px', fontSize: 12 }}
              onClick={() => setMonth(m => m.m === 11 ? { y: m.y + 1, m: 0 } : { y: m.y, m: m.m + 1 })}>→</button>
          </div>
        }
      />
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2 }}>
        {['Sun','Mon','Tue','Wed','Thu','Fri','Sat'].map(d => (
          <div key={d} style={{ fontSize: 10, color: 'var(--text-3)', textAlign: 'center', padding: 4 }}>{(window.appT||(s=>s))(d)}</div>
        ))}
        {cells.map((d, i) => {
          if (d === null) return <div key={`e${i}`} />;
          const slot = byDay[d] || {};
          const isToday = d === today.getDate() && month.m === today.getMonth() && month.y === today.getFullYear();
          return (
            <div key={d} style={{
              minHeight: 76, padding: 4,
              border: isToday ? '2px solid var(--brand)' : '1px solid var(--line)',
              borderRadius: 4,
              background: 'var(--bg-elev-2)',
              fontSize: 11,
              display:'flex', flexDirection:'column', gap:1,
            }}>
              <div style={{ fontWeight: isToday ? 700 : 500, color: 'var(--text-2)', marginBottom: 2 }}>{d}</div>
              {(slot.primary || []).map(sh => (
                <div key={`p-${sh.id}`} style={{ fontSize: 10, color:'var(--ok)' }}
                     title={`${(window.appT||(s=>s))("Primary")}: ${(empById[sh.user_id] || {}).display_name || ''}`}>
                  P · {(empById[sh.user_id] || {}).display_name || sh.display_name}
                </div>
              ))}
              {(slot.backup || []).map(sh => (
                <div key={`b-${sh.id}`} style={{ fontSize: 10, color:'var(--warn)' }}
                     title={`${(window.appT||(s=>s))("Backup")}: ${(empById[sh.user_id] || {}).display_name || ''}`}>
                  B · {(empById[sh.user_id] || {}).display_name || sh.display_name}
                </div>
              ))}
              {(slot.escalation || []).map(sh => (
                <div key={`e-${sh.id}`} style={{ fontSize: 10, color:'var(--err)' }}
                     title={`${(window.appT||(s=>s))("Escalation")}: ${(empById[sh.user_id] || {}).display_name || ''}`}>
                  E · {(empById[sh.user_id] || {}).display_name || sh.display_name}
                </div>
              ))}
            </div>
          );
        })}
      </div>
    </div>
  );
}

window.OnCallCalendarCard = OnCallCalendarCard;
window.OnCallPage = OnCallPage;
