// tab-requests.jsx — Pending shift-change AND time-off requests review.
// Leads see only their own team's pending; admins see every team's. Reads
// come direct from Firestore (rules already gate by team-of-doc); the
// approve/deny actions go through reviewShiftChangeRequest /
// reviewTimeOffRequest callables.

const REQ_DAY_LABELS = {
  monday: 'Mon', tuesday: 'Tue', wednesday: 'Wed', thursday: 'Thu',
  friday: 'Fri', saturday: 'Sat', sunday: 'Sun',
};

function reqTsLabel(ts) {
  if (!ts) return '—';
  const d = ts.toDate ? ts.toDate() : (ts.seconds ? new Date(ts.seconds * 1000) : new Date(ts));
  if (isNaN(d.getTime())) return '—';
  return d.toLocaleDateString(undefined, { day: 'numeric', month: 'short' }) + ' ' +
    d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
}

function reqDateLabel(s) {
  if (!s) return '—';
  const d = new Date(s);
  if (isNaN(d.getTime())) return s;
  return d.toLocaleDateString(undefined, { day: 'numeric', month: 'short', year: 'numeric' });
}

function reqDateRange(start, end) {
  if (!start) return '—';
  if (!end || start === end) return reqDateLabel(start);
  return `${reqDateLabel(start)} → ${reqDateLabel(end)}`;
}

function reqDayCount(start, end) {
  if (!start || !end) return 0;
  const s = new Date(start), e = new Date(end);
  if (isNaN(s.getTime()) || isNaN(e.getTime())) return 0;
  return Math.round((e - s) / 86400000) + 1;
}

const COLLECTION_BY_KIND = {
  shift: 'shiftChangeRequests',
  timeoff: 'timeOffRequests',
};
const REVIEW_CALLABLE_BY_KIND = {
  shift: 'reviewShiftChangeRequest',
  timeoff: 'reviewTimeOffRequest',
};

function TabRequests({ viewer }) {
  // Hooks pulled inside the component — Babel-standalone shares scope
  // across all text/babel scripts so module-level const aliases collide.
  const isAdmin = viewer && viewer.role === 'admin';
  const ownTeam = (window.YD && window.YD.TEAM && window.YD.TEAM.teamName) || (viewer && viewer.team) || '';
  const [kind, setKind] = React.useState('shift'); // 'shift' | 'timeoff'
  const [scope, setScope] = React.useState(isAdmin ? 'all' : 'team');
  const [items, setItems] = React.useState([]);
  const [shiftCount, setShiftCount] = React.useState(0);
  const [timeoffCount, setTimeoffCount] = React.useState(0);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);
  const [busyId, setBusyId] = React.useState(null);
  const [toast, setToast] = React.useState(null);

  const load = React.useCallback(() => {
    setLoading(true); setErr(null);
    const collection = COLLECTION_BY_KIND[kind];
    let q = window.YDApp.firestore
      .collection(collection)
      .where('status', '==', 'pending');
    if (!isAdmin || scope === 'team') {
      q = q.where('team', '==', ownTeam);
    }
    // Force server fetch — without this the SDK returns a cached
    // snapshot that may not include the just-completed status update.
    q.get({ source: 'server' })
      .then((snap) => {
        const rows = [];
        snap.forEach((d) => rows.push(Object.assign({ id: d.id }, d.data())));
        rows.sort((a, b) => {
          const ta = a.createdAt && a.createdAt.toMillis ? a.createdAt.toMillis() : 0;
          const tb = b.createdAt && b.createdAt.toMillis ? b.createdAt.toMillis() : 0;
          return tb - ta;
        });
        setItems(rows); setLoading(false);
      })
      .catch((e) => { setErr(e.message || String(e)); setLoading(false); });
  }, [isAdmin, scope, ownTeam, kind]);

  // Pending counts for both kinds — drives the toggle badges. Same scope
  // rules as the main fetch so the count reflects what they'll see.
  const loadCounts = React.useCallback(() => {
    const fetchCount = (col, setter) => {
      let q = window.YDApp.firestore.collection(col).where('status', '==', 'pending');
      if (!isAdmin || scope === 'team') q = q.where('team', '==', ownTeam);
      q.get({ source: 'server' }).then((snap) => setter(snap.size)).catch(() => setter(0));
    };
    fetchCount('shiftChangeRequests', setShiftCount);
    fetchCount('timeOffRequests', setTimeoffCount);
  }, [isAdmin, scope, ownTeam]);

  React.useEffect(() => { load(); }, [load]);
  React.useEffect(() => { loadCounts(); }, [loadCounts]);

  const decide = async (item, approved, extras) => {
    setBusyId(item.id); setErr(null);
    try {
      const callable = REVIEW_CALLABLE_BY_KIND[kind];
      await window.YDApp.call(callable, Object.assign({ id: item.id, approved }, extras || {}));
      // Optimistically drop the row so the UI reflects the decision
      // immediately even if the next .get() comes from cache.
      setItems((prev) => prev.filter((x) => x.id !== item.id));
      // Decrement the active-kind badge so it matches.
      if (kind === 'shift') setShiftCount((c) => Math.max(0, c - 1));
      else setTimeoffCount((c) => Math.max(0, c - 1));
      setToast(approved
        ? (kind === 'shift' ? 'Approved · schedule updated' : 'Leave approved')
        : 'Denied');
      setTimeout(() => setToast(null), 2400);
      load();
      loadCounts();
    } catch (e) {
      setErr(e.message || String(e));
    } finally {
      setBusyId(null);
    }
  };

  const total = items.length;
  const teamCount = items.filter((r) => r.team === ownTeam).length;

  const titleByKind = kind === 'shift' ? 'Pending shift changes' : 'Pending leave requests';

  return (
    <div className="page">
      <PageHeader
        eyebrow="Requests"
        title={`${titleByKind} · ${total}`}
        subtitle={isAdmin
          ? (scope === 'all' ? 'Company-wide view · approve any team' : `Showing ${ownTeam} only`)
          : `Your team · ${ownTeam}`}
        actions={
          <div className="flex g8 ac">
            {isAdmin && (
              <div className="segbar">
                <button className={scope === 'team' ? 'active' : ''} onClick={() => setScope('team')}>
                  My team
                </button>
                <button className={scope === 'all' ? 'active' : ''} onClick={() => setScope('all')}>
                  All teams
                </button>
              </div>
            )}
            <button className="btn" onClick={() => { load(); loadCounts(); }} disabled={loading}>
              {loading ? 'Refreshing…' : 'Refresh'}
            </button>
          </div>
        }/>

      <div className="segbar" style={{ marginBottom: 16 }}>
        <button className={kind === 'shift' ? 'active' : ''} onClick={() => setKind('shift')}>
          Shift changes <span style={{ marginLeft: 6, color: '#9ca3af' }}>{shiftCount}</span>
        </button>
        <button className={kind === 'timeoff' ? 'active' : ''} onClick={() => setKind('timeoff')}>
          Time off <span style={{ marginLeft: 6, color: '#9ca3af' }}>{timeoffCount}</span>
        </button>
      </div>

      {err && <div className="card"><div className="card-bd" style={{ color: '#b91c1c' }}>{err}</div></div>}

      <div className="card">
        <div className="card-bd" style={{ padding: 0 }}>
          {loading && total === 0 ? (
            <div style={{ padding: 24, color: '#9ca3af', fontSize: 13, textAlign: 'center' }}>Loading…</div>
          ) : total === 0 ? (
            <div style={{ padding: 24, color: '#9ca3af', fontSize: 13, textAlign: 'center' }}>
              No pending {kind === 'shift' ? 'shift change' : 'time off'} requests.
            </div>
          ) : kind === 'shift' ? (
            <ShiftRequestsTable items={items} ownTeam={ownTeam} busyId={busyId} decide={decide}/>
          ) : (
            <TimeOffRequestsTable items={items} busyId={busyId} decide={decide}/>
          )}
        </div>
      </div>

      {toast && <div className="toast">{toast}</div>}
    </div>
  );
}

function ShiftRequestsTable({ items, busyId, decide }) {
  return (
    <table className="pl-table">
      <thead>
        <tr>
          <th>Submitted</th>
          <th>Annotator</th>
          <th>Team</th>
          <th>Day changes</th>
          <th>Reason</th>
          <th style={{ width: 200, textAlign: 'right' }}>Decision</th>
        </tr>
      </thead>
      <tbody>
        {items.map((r) => (
          <tr key={r.id}>
            <td className="mono" style={{ fontSize: 11, whiteSpace: 'nowrap' }}>{reqTsLabel(r.createdAt)}</td>
            <td>
              <div className="flex ac g8">
                <Avatar name={r.name || r.email} size={24}/>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{r.name || r.email}</div>
                  <div className="meta">{r.email}</div>
                </div>
              </div>
            </td>
            <td>{r.team || '—'}</td>
            <td>
              <div className="col g4" style={{ fontSize: 12 }}>
                {Object.entries(r.dayChanges || {}).map(([day, c]) => {
                  const from = (c && typeof c === 'object' && c.from) || (typeof c === 'string' ? c : '');
                  const to = (c && typeof c === 'object' && c.to) || '';
                  return (
                    <div key={day}>
                      <b style={{ marginRight: 6 }}>{REQ_DAY_LABELS[day] || day}:</b>
                      <span className="mono" style={{ color: '#9ca3af' }}>{from || 'off'}</span>
                      <span style={{ margin: '0 6px' }}>→</span>
                      <span className="mono" style={{ color: '#3730a3', fontWeight: 700 }}>{to || 'off'}</span>
                    </div>
                  );
                })}
              </div>
            </td>
            <td style={{ fontSize: 12, color: '#374151' }}>{r.reason || <span className="meta">—</span>}</td>
            <td style={{ textAlign: 'right' }}>
              <div className="flex g6" style={{ justifyContent: 'flex-end' }}>
                <button className="btn btn-sm" disabled={busyId === r.id} onClick={() => decide(r, false)}>Deny</button>
                <button className="btn btn-sm btn-dark" disabled={busyId === r.id} onClick={() => decide(r, true)}>
                  {busyId === r.id ? '…' : 'Approve'}
                </button>
              </div>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

function TimeOffRequestsTable({ items, busyId, decide }) {
  return (
    <table className="pl-table">
      <thead>
        <tr>
          <th>Submitted</th>
          <th>Annotator</th>
          <th>Team</th>
          <th>Dates</th>
          <th>Reason</th>
          <th>Capacity</th>
          <th style={{ width: 200, textAlign: 'right' }}>Decision</th>
        </tr>
      </thead>
      <tbody>
        {items.map((r) => {
          const days = reqDayCount(r.startDate, r.endDate);
          return (
            <tr key={r.id}>
              <td className="mono" style={{ fontSize: 11, whiteSpace: 'nowrap' }}>{reqTsLabel(r.createdAt)}</td>
              <td>
                <div className="flex ac g8">
                  <Avatar name={r.name || r.email} size={24}/>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>{r.name || r.email}</div>
                    <div className="meta">{r.email}</div>
                  </div>
                </div>
              </td>
              <td>{r.team || '—'}</td>
              <td>
                <div style={{ fontSize: 12 }}>{reqDateRange(r.startDate, r.endDate)}</div>
                <div className="meta">{days} day{days === 1 ? '' : 's'}</div>
              </td>
              <td>
                <div style={{ fontSize: 12, fontWeight: 600 }}>{r.reason || '—'}</div>
                {r.detail && <div className="meta" style={{ marginTop: 2 }}>{r.detail}</div>}
              </td>
              <td style={{ fontSize: 12 }}>
                {r.capacity === 'reduced'
                  ? <>Reduced · {r.reducedHours ? `${r.reducedHours}h/day` : '—'}</>
                  : r.capacity === 'full'
                    ? 'Full leave'
                    : (r.capacity || '—')}
              </td>
              <td style={{ textAlign: 'right' }}>
                <div className="flex g6" style={{ justifyContent: 'flex-end' }}>
                  <button className="btn btn-sm" disabled={busyId === r.id} onClick={() => decide(r, false)}>Deny</button>
                  <button
                    className="btn btn-sm btn-dark"
                    disabled={busyId === r.id}
                    onClick={() => decide(r, true, r.capacity === 'reduced' ? { approvedReducedHours: r.reducedHours } : undefined)}>
                    {busyId === r.id ? '…' : 'Approve'}
                  </button>
                </div>
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

Object.assign(window, { TabRequests });
