// admin-trash.jsx — Trash tab. Lists recently deleted students + teachers
// from public.deleted_account_archive, lets the admin restore (recreates
// auth user + profile/instructor/student_info row) or permanently purge.
//
// Data: window.ADMIN_DATA.{listDeletedAccounts,getArchivedSnapshot,
//                          restoreDeletedAccount,purgeDeletedAccount}
// installed by data-trash.js. Server work for restore goes through
// /api/admin-restore-account (creates the new auth.users via GoTrue admin).
//
// Public on window: AdminTrash.

const AdminTrash = () => {
  const [rows, setRows]       = React.useState(null);   // null = loading
  const [err,  setErr]        = React.useState('');
  const [busy, setBusy]       = React.useState({});
  const [filter, setFilter]   = React.useState('all');  // all | student | instructor
  const [search, setSearch]   = React.useState('');
  const [snapshotId, setSnapshotId] = React.useState(null);
  const [snapshotData, setSnapshotData] = React.useState(null);
  const [purgeTarget, setPurgeTarget] = React.useState(null);
  const [confirmRestoreTarget, setConfirmRestoreTarget] = React.useState(null);
  const [flash, setFlash] = React.useState('');

  const load = React.useCallback(async () => {
    setErr('');
    try {
      const data = await window.ADMIN_DATA.listDeletedAccounts();
      setRows(data);
    } catch (e) {
      setErr(e.message || 'Could not load trash.');
      setRows([]);
    }
  }, []);

  React.useEffect(() => { load(); }, [load]);

  const setRowBusy = (id, v) => setBusy(b => ({ ...b, [id]: v }));

  const onRestore = async (row) => {
    setRowBusy(row.id, 'restore');
    setErr('');
    try {
      const out = await window.ADMIN_DATA.restoreDeletedAccount(row.id);
      setFlash(`Restored ${row.displayName} (${row.accountKind}). New user id: ${out.userId}. Send a magic link from Students/Instructors to give them access again.`);
      await load();
    } catch (e) {
      setErr(e.message || 'Restore failed.');
    } finally {
      setRowBusy(row.id, null);
      setConfirmRestoreTarget(null);
    }
  };

  const onPurge = async (row) => {
    setRowBusy(row.id, 'purge');
    setErr('');
    try {
      await window.ADMIN_DATA.purgeDeletedAccount(row.id);
      setFlash(`Permanently removed ${row.displayName} from Trash.`);
      await load();
    } catch (e) {
      setErr(e.message || 'Purge failed.');
    } finally {
      setRowBusy(row.id, null);
      setPurgeTarget(null);
    }
  };

  const onShowSnapshot = async (row) => {
    setSnapshotId(row.id);
    setSnapshotData(null);
    try {
      const snap = await window.ADMIN_DATA.getArchivedSnapshot(row.id);
      setSnapshotData(snap);
    } catch (e) {
      setSnapshotData({ error: e.message || 'Could not load snapshot.' });
    }
  };

  const filtered = (rows || []).filter(r => {
    if (filter !== 'all' && r.accountKind !== filter) return false;
    if (search.trim()) {
      const q = search.trim().toLowerCase();
      const blob = [r.displayName, r.originalEmail, r.archivedByEmail].filter(Boolean).join(' ').toLowerCase();
      if (!blob.includes(q)) return false;
    }
    return true;
  });

  const fmtWhen = (iso) => {
    if (!iso) return '';
    try {
      const d = new Date(iso);
      const diffMs = Date.now() - d.getTime();
      const mins = Math.floor(diffMs / 60000);
      if (mins < 1)   return 'just now';
      if (mins < 60)  return `${mins} min ago`;
      const hrs = Math.floor(mins / 60);
      if (hrs < 24)   return `${hrs} h ago`;
      const days = Math.floor(hrs / 24);
      if (days < 14)  return `${days} d ago`;
      return d.toLocaleString();
    } catch { return iso; }
  };

  return (
    <div style={{ padding:'18px 22px 60px', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
      {flash && (
        <div role="status" style={{
          background:'oklch(96% 0.05 145)', color:'oklch(34% 0.15 145)',
          border:'1px solid oklch(82% 0.08 145)', padding:'10px 14px',
          borderRadius:10, fontSize:13, marginBottom:14, display:'flex',
          alignItems:'center', justifyContent:'space-between', gap:12,
        }}>
          <span>{flash}</span>
          <button onClick={() => setFlash('')} style={{ background:'transparent', border:'none', color:'inherit', fontSize:16, cursor:'pointer' }} aria-label="Dismiss">×</button>
        </div>
      )}

      <div style={{
        display:'flex', alignItems:'center', justifyContent:'space-between',
        gap:12, flexWrap:'wrap', marginBottom:14,
      }}>
        <div>
          <div style={{ fontSize:18, fontWeight:700, color:'oklch(18% 0.03 265)' }}>Recently deleted</div>
          <div style={{ fontSize:12, color:'oklch(50% 0.03 265)', marginTop:2 }}>
            Restore brings the account back with the same email. Purge permanently removes the archived snapshot (cannot be undone).
          </div>
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
          {['all','student','instructor'].map(f => (
            <button key={f} onClick={() => setFilter(f)} style={{
              padding:'7px 12px', borderRadius:8, fontSize:12, fontWeight:600,
              fontFamily:"'Plus Jakarta Sans', sans-serif",
              border: filter === f ? '1px solid oklch(40% 0.18 265)' : '1px solid oklch(88% 0.02 265)',
              background: filter === f ? 'oklch(96% 0.04 265)' : '#fff',
              color: filter === f ? 'oklch(28% 0.12 265)' : 'oklch(40% 0.04 265)',
              cursor:'pointer', textTransform:'capitalize',
            }}>{f === 'all' ? 'All' : (f + 's')}</button>
          ))}
          <input
            value={search}
            onChange={e => setSearch(e.target.value)}
            placeholder="Search name or email"
            aria-label="Search trash"
            style={{
              padding:'7px 11px', borderRadius:8, fontSize:12,
              border:'1px solid oklch(88% 0.02 265)',
              fontFamily:"'Plus Jakarta Sans', sans-serif",
              minWidth:180,
            }}
          />
          <button onClick={load} title="Refresh" aria-label="Refresh" style={{
            padding:'7px 11px', borderRadius:8, fontSize:12, fontWeight:600,
            background:'#fff', border:'1px solid oklch(88% 0.02 265)',
            cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif",
          }}>Refresh</button>
        </div>
      </div>

      {err && (
        <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'10px 14px', borderRadius:10, fontSize:13, marginBottom:14 }}>
          {err}
        </div>
      )}

      {rows === null && (
        <div style={{ padding:'40px 0', textAlign:'center', color:'oklch(58% 0.03 265)', fontSize:13 }}>Loading trash…</div>
      )}

      {rows !== null && filtered.length === 0 && (
        <div style={{
          padding:'36px 20px', textAlign:'center', background:'#fff',
          border:'1px dashed oklch(88% 0.02 265)', borderRadius:12,
          color:'oklch(50% 0.03 265)', fontSize:13,
        }}>
          Nothing in trash. Deleted students and teachers show up here.
        </div>
      )}

      {rows !== null && filtered.length > 0 && (
        <div style={{ background:'#fff', borderRadius:12, border:'1px solid oklch(92% 0.01 265)', overflow:'hidden' }}>
          <div style={{ display:'grid', gridTemplateColumns:'minmax(0,1fr) 92px 130px 130px auto', padding:'10px 16px', background:'oklch(98% 0.005 265)', borderBottom:'1px solid oklch(92% 0.01 265)', fontSize:11, fontWeight:700, color:'oklch(46% 0.04 265)', textTransform:'uppercase', letterSpacing:'0.04em', gap:12 }}>
            <div>Name · Email</div>
            <div>Kind</div>
            <div>Deleted</div>
            <div>By</div>
            <div style={{ textAlign:'right' }}>Actions</div>
          </div>

          {filtered.map(row => {
            const isBusy = !!busy[row.id];
            const restored = !!row.restoredAt;
            return (
              <div key={row.id} style={{
                display:'grid', gridTemplateColumns:'minmax(0,1fr) 92px 130px 130px auto',
                padding:'12px 16px', borderBottom:'1px solid oklch(96% 0.005 265)',
                fontSize:13, alignItems:'center', gap:12,
                background: restored ? 'oklch(98% 0.02 145)' : '#fff',
              }}>
                <div style={{ minWidth:0 }}>
                  <div style={{ fontWeight:600, color:'oklch(18% 0.03 265)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{row.displayName}</div>
                  <div style={{ color:'oklch(56% 0.03 265)', fontSize:12, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }} title={row.originalEmail || ''}>{row.originalEmail || <em>(no email)</em>}</div>
                </div>
                <div>
                  <span style={{ display:'inline-block', padding:'3px 9px', borderRadius:99, fontSize:11, fontWeight:600,
                    background: row.accountKind === 'instructor' ? 'oklch(95% 0.05 265)' : 'oklch(96% 0.05 80)',
                    color:     row.accountKind === 'instructor' ? 'oklch(34% 0.13 265)' : 'oklch(38% 0.14 80)',
                  }}>{row.accountKind}</span>
                </div>
                <div style={{ color:'oklch(40% 0.04 265)', fontSize:12 }} title={row.archivedAt}>{fmtWhen(row.archivedAt)}</div>
                <div style={{ color:'oklch(46% 0.04 265)', fontSize:12, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }} title={row.archivedByEmail || ''}>{row.archivedByEmail || '—'}</div>
                <div style={{ display:'flex', gap:7, justifyContent:'flex-end', flexWrap:'wrap' }}>
                  <button onClick={() => onShowSnapshot(row)} disabled={isBusy} style={btnGhost(isBusy)}>View</button>
                  {restored ? (
                    <span style={{ fontSize:11, fontWeight:600, color:'oklch(40% 0.15 145)', alignSelf:'center', padding:'0 6px' }}>Restored {fmtWhen(row.restoredAt)}</span>
                  ) : (
                    <button onClick={() => setConfirmRestoreTarget(row)} disabled={isBusy} style={btnPrimary(isBusy)}>{busy[row.id] === 'restore' ? 'Restoring…' : 'Restore'}</button>
                  )}
                  <button onClick={() => setPurgeTarget(row)} disabled={isBusy} style={btnDanger(isBusy)}>{busy[row.id] === 'purge' ? 'Purging…' : 'Delete forever'}</button>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* Snapshot drawer */}
      {snapshotId && (
        <div style={overlayStyle} onClick={() => { setSnapshotId(null); setSnapshotData(null); }}>
          <div style={{ ...sheetStyle, maxWidth:640 }} onClick={e => e.stopPropagation()}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
              <div style={{ fontWeight:700, fontSize:15, color:'oklch(18% 0.03 265)' }}>Archive snapshot</div>
              <button onClick={() => { setSnapshotId(null); setSnapshotData(null); }} style={{ background:'transparent', border:'none', fontSize:20, cursor:'pointer', color:'oklch(50% 0.03 265)' }} aria-label="Close">×</button>
            </div>
            <div style={{ fontSize:12, color:'oklch(50% 0.03 265)', marginBottom:10 }}>
              Raw data captured at delete time. This is what Restore re-creates.
            </div>
            {snapshotData === null && <div style={{ fontSize:13, color:'oklch(50% 0.03 265)' }}>Loading snapshot…</div>}
            {snapshotData && snapshotData.error && (
              <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'10px 14px', borderRadius:8, fontSize:12 }}>{snapshotData.error}</div>
            )}
            {snapshotData && !snapshotData.error && (
              <pre style={{
                background:'oklch(98% 0.005 265)', border:'1px solid oklch(92% 0.01 265)',
                borderRadius:8, padding:'12px 14px', fontSize:11, lineHeight:1.55,
                maxHeight:'60vh', overflow:'auto', margin:0,
                color:'oklch(20% 0.03 265)', fontFamily:'ui-monospace, SFMono-Regular, Menlo, monospace',
                whiteSpace:'pre-wrap', wordBreak:'break-word',
              }}>{JSON.stringify(snapshotData, null, 2)}</pre>
            )}
          </div>
        </div>
      )}

      {/* Confirm restore */}
      {confirmRestoreTarget && (
        <div style={overlayStyle} onClick={() => setConfirmRestoreTarget(null)}>
          <div style={sheetStyle} onClick={e => e.stopPropagation()}>
            <div style={{ fontWeight:700, fontSize:15, color:'oklch(18% 0.03 265)', marginBottom:8 }}>Restore {confirmRestoreTarget.displayName}?</div>
            <div style={{ fontSize:13, color:'oklch(54% 0.03 265)', lineHeight:1.55, marginBottom:14 }}>
              This recreates the auth user with email <strong>{confirmRestoreTarget.originalEmail}</strong> and re-hydrates the profile + {confirmRestoreTarget.accountKind === 'instructor' ? 'instructor row, subject, availability' : 'student info'}. Bookings, assignments and history are <strong>not</strong> restored — they cascade-deleted with the auth user and live only in the read-only snapshot. After restore, send a magic-link sign-in from the {confirmRestoreTarget.accountKind === 'instructor' ? 'Instructors' : 'Students'} tab.
            </div>
            <div style={{ display:'flex', gap:10 }}>
              <button onClick={() => onRestore(confirmRestoreTarget)} disabled={!!busy[confirmRestoreTarget.id]} style={{ ...btnPrimary(!!busy[confirmRestoreTarget.id]), flex:1, padding:'11px 0', fontSize:13 }}>
                {busy[confirmRestoreTarget.id] === 'restore' ? 'Restoring…' : 'Yes, restore'}
              </button>
              <button onClick={() => setConfirmRestoreTarget(null)} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:9, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
            </div>
          </div>
        </div>
      )}

      {/* Confirm purge — typed-name confirmation, same shape as ASConfirmDelete */}
      {purgeTarget && (
        <PurgeConfirmModal
          row={purgeTarget}
          busy={!!busy[purgeTarget.id]}
          onCancel={() => setPurgeTarget(null)}
          onConfirm={() => onPurge(purgeTarget)}
        />
      )}
    </div>
  );
};

// Purge confirm — second-line of defense. The archive row is the LAST trace
// of this user; permanently dropping it should require typing the name.
const PurgeConfirmModal = ({ row, busy, onCancel, onConfirm }) => {
  const [typed, setTyped] = React.useState('');
  const expected = String(row.displayName || '').trim();
  const matches  = typed.trim().toLowerCase() === expected.toLowerCase() && expected.length > 0;
  return (
    <div style={overlayStyle} onClick={onCancel}>
      <div style={sheetStyle} onClick={e => e.stopPropagation()}>
        <div style={{ fontWeight:700, fontSize:15, color:'oklch(40% 0.15 25)', marginBottom:8 }}>Permanently delete {row.displayName}?</div>
        <div style={{ fontSize:13, color:'oklch(54% 0.03 265)', lineHeight:1.55, marginBottom:12 }}>
          The archive row is the last copy of this {row.accountKind}. After this it’s gone for good — Restore won’t work anymore. Use this for accounts you’re sure don’t need to come back.
        </div>
        <div style={{ fontSize:12, color:'oklch(40% 0.04 265)', marginBottom:6, fontWeight:600 }}>
          Type <span style={{ background:'oklch(96% 0.01 265)', padding:'1px 6px', borderRadius:4, fontWeight:700, color:'oklch(18% 0.03 265)' }}>{expected}</span> to confirm
        </div>
        <input
          type="text"
          value={typed}
          onChange={e => setTyped(e.target.value)}
          autoFocus
          placeholder={`Type ${expected} here`}
          aria-label="Type name to permanently delete"
          data-testid="confirm-purge-typed-name"
          style={{ width:'100%', boxSizing:'border-box', padding:'10px 12px', borderRadius:8, fontSize:13, marginBottom:14,
            border: matches ? '1.5px solid oklch(60% 0.16 25)' : '1.5px solid oklch(88% 0.02 265)',
            outline:'none', fontFamily:"'Plus Jakarta Sans', sans-serif" }}
        />
        <div style={{ display:'flex', gap:10 }}>
          <button
            onClick={() => { if (matches && !busy) onConfirm(); }}
            disabled={!matches || busy}
            style={{ flex:1,
              background: matches ? 'oklch(40% 0.18 25)' : 'oklch(88% 0.04 25)',
              color:'#fff', border:'none', borderRadius:9, padding:'11px 0',
              fontWeight:700, fontSize:13,
              cursor: matches ? (busy?'wait':'pointer') : 'not-allowed',
              fontFamily:"'Plus Jakarta Sans', sans-serif",
              opacity: busy ? 0.7 : 1,
            }}
          >{busy ? 'Purging…' : 'Delete forever'}</button>
          <button onClick={onCancel} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:9, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
        </div>
      </div>
    </div>
  );
};

const overlayStyle = {
  position:'fixed', inset:0, background:'rgba(10,12,24,0.4)',
  display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000,
};
const sheetStyle = {
  background:'#fff', borderRadius:14, padding:'24px', width:420,
  maxWidth:'calc(100vw - 32px)', boxShadow:'0 20px 60px rgba(0,0,0,0.18)',
  fontFamily:"'Plus Jakarta Sans', sans-serif",
};
const btnBase = {
  padding:'7px 12px', borderRadius:8, fontSize:11, fontWeight:600,
  border:'none', cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif",
};
const btnGhost = (disabled) => ({ ...btnBase, background:'#fff', border:'1px solid oklch(88% 0.02 265)', color:'oklch(40% 0.04 265)', cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.6 : 1 });
const btnPrimary = (disabled) => ({ ...btnBase, background: disabled ? 'oklch(75% 0.04 265)' : 'oklch(22% 0.06 265)', color:'#fff', cursor: disabled ? 'not-allowed' : 'pointer' });
const btnDanger = (disabled) => ({ ...btnBase, background:'#fff', border:'1px solid oklch(80% 0.08 25)', color:'oklch(40% 0.18 25)', cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.6 : 1 });

Object.assign(window, { AdminTrash });
