/**
 * PhoneCalls.tsx
 *
 * Front-office page: phone-call log. Lets the front-desk / admin record
 * incoming and outgoing calls, and clear pending follow-ups.
 *
 * Backend (see `server/src/controllers/front-office.controller.js`,
 * block "PHONE CALL LOGS"):
 *   GET    /api/front-office/phone-calls
 *   POST   /api/front-office/phone-calls              (staff only)
 *   PUT    /api/front-office/phone-calls/:id          (staff only)
 *   DELETE /api/front-office/phone-calls/:id          (staff only)
 *   PUT    /api/front-office/phone-calls/:id/follow-up (staff only)
 *
 * UI role gating (see App.tsx): this page is registered for
 * school_admin, systems_admin, principal and teacher. The backend will
 * return 403 for student / parent if they ever hit the page.
 */

import React, { useEffect, useMemo, useState } from 'react';
import { createPortal } from 'react-dom';
import {
  Phone, PhoneIncoming, PhoneOutgoing, Plus, X, Search,
  Calendar, Clock, User, CheckCircle2, Filter, FileText,
  ArrowUpRight, AlertCircle, Upload, Check, Sparkles, Trash2, Edit2
} from 'lucide-react';
import { useFrontOfficeStore, PhoneCall, PhoneCallCreate } from '../../../store/frontOffice';
import api from '../../../store/auth';

const CALLER_TYPES: { value: NonNullable<PhoneCallCreate['caller_type']>; label: string }[] = [
  { value: 'parent', label: 'Parent / Guardian' },
  { value: 'student', label: 'Student' },
  { value: 'vendor', label: 'Vendor' },
  { value: 'government', label: 'Government' },
  { value: 'other', label: 'Other' },
];

const todayIso = () => new Date().toISOString().split('T')[0];
const nowDateTimeLocal = () => {
  const d = new Date();
  d.setSeconds(0, 0);
  return d.toISOString().slice(0, 16); // YYYY-MM-DDTHH:MM for <input type="datetime-local">
};

interface FormState {
  caller_name: string;
  caller_phone: string;
  caller_type: NonNullable<PhoneCallCreate['caller_type']>;
  direction: NonNullable<PhoneCallCreate['direction']>;
  call_time: string;
  duration_minutes: number;
  purpose: string;
  response: string;
  follow_up_required: boolean;
  follow_up_date: string;
  notes: string;
}

const emptyForm = (): FormState => ({
  caller_name: '',
  caller_phone: '',
  caller_type: 'parent',
  direction: 'incoming',
  call_time: nowDateTimeLocal(),
  duration_minutes: 0,
  purpose: '',
  response: '',
  follow_up_required: false,
  follow_up_date: '',
  notes: '',
});

export default function PhoneCalls() {
  const {
    phoneCalls, loading, error,
    fetchPhoneCalls, createPhoneCall, markFollowUpDone, deletePhoneCall, updatePhoneCall
  } = useFrontOfficeStore();

  const [search, setSearch] = useState('');
  const [from, setFrom] = useState('');
  const [to, setTo] = useState('');
  const [showAdd, setShowAdd] = useState(false);
  const [showBulkModal, setShowBulkModal] = useState(false);
  const [form, setForm] = useState<FormState>(emptyForm());
  const [submitting, setSubmitting] = useState(false);
  const [successMsg, setSuccessMsg] = useState<string | null>(null);
  const [followUpBusyId, setFollowUpBusyId] = useState<number | null>(null);
  const [editingId, setEditingId] = useState<number | null>(null);

  useEffect(() => {
    fetchPhoneCalls();
  }, [fetchPhoneCalls]);

  // re-fetch when date range changes
  useEffect(() => {
    const params: any = {};
    if (from) params.from = `${from}T00:00:00`;
    if (to) params.to = `${to}T23:59:59`;
    
    // Only call if we have params or if we need to clear them
    fetchPhoneCalls(Object.keys(params).length > 0 ? params : undefined);
  }, [from, to, fetchPhoneCalls]);

  const filtered = useMemo(() => {
    const q = search.toLowerCase().trim();
    if (!q) return phoneCalls;
    return phoneCalls.filter(c =>
      c.caller_name?.toLowerCase().includes(q) ||
      c.caller_phone?.toLowerCase().includes(q) ||
      c.purpose?.toLowerCase().includes(q) ||
      c.handler_name?.toLowerCase().includes(q)
    );
  }, [phoneCalls, search]);

  const followUpsPending = useMemo(
    () => phoneCalls.filter(c => Number(c.follow_up_required) === 1).length,
    [phoneCalls]
  );

  const resetForm = () => {
    setForm(emptyForm());
    setEditingId(null);
  };

  const setDateRange = (days: number) => {
    const end = new Date();
    const start = new Date();
    start.setDate(end.getDate() - days);
    
    // For 'Today', start and end are the same
    if (days === 0) {
      setFrom(end.toISOString().split('T')[0]);
      setTo(end.toISOString().split('T')[0]);
      return;
    }
    
    setFrom(start.toISOString().split('T')[0]);
    setTo(end.toISOString().split('T')[0]);
  };

  const handleEdit = (c: PhoneCall) => {
    setEditingId(c.id);
    const formatDateTimeLocal = (dateStr: string | null | undefined) => {
      if (!dateStr) return '';
      const d = new Date(dateStr);
      d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
      return d.toISOString().slice(0, 16);
    };
    const formatDate = (dateStr: string | null | undefined) => {
      if (!dateStr) return '';
      return new Date(dateStr).toISOString().split('T')[0];
    };

    setForm({
      caller_name: c.caller_name || '',
      caller_phone: c.caller_phone || '',
      caller_type: (c.caller_type || 'other') as FormState['caller_type'],
      direction: (c.direction || 'incoming') as FormState['direction'],
      call_time: formatDateTimeLocal(c.call_time),
      duration_minutes: c.duration_seconds ? Math.round(c.duration_seconds / 60) : 0,
      purpose: c.purpose || '',
      response: c.response || '',
      follow_up_required: Number(c.follow_up_required) === 1,
      follow_up_date: formatDate(c.follow_up_date),
      notes: c.notes || '',
    });
    setShowAdd(true);
  };

  const handleDelete = async (id: number) => {
    if (!window.confirm('Are you sure you want to delete this call log?')) return;
    try {
      await deletePhoneCall(id);
      setSuccessMsg('Call log deleted.');
      setTimeout(() => setSuccessMsg(null), 3000);
    } catch (err: any) {
      console.error('delete error', err);
      alert(err.response?.data?.error || 'Failed to delete call log');
    }
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!form.caller_name.trim()) return;
    setSubmitting(true);
    try {
      const payload: PhoneCallCreate = {
        caller_name: form.caller_name.trim(),
        caller_phone: form.caller_phone.trim() || undefined,
        caller_type: form.caller_type,
        direction: form.direction,
        call_time: form.call_time ? new Date(form.call_time).toISOString() : undefined,
        duration_seconds: Math.max(0, Math.round(form.duration_minutes * 60)),
        purpose: form.purpose.trim() || undefined,
        response: form.response.trim() || undefined,
        follow_up_required: form.follow_up_required,
        follow_up_date: form.follow_up_required && form.follow_up_date ? form.follow_up_date : undefined,
        notes: form.notes.trim() || undefined,
      };
      
      if (editingId) {
        await updatePhoneCall(editingId, payload);
        setSuccessMsg('Call log updated.');
      } else {
        await createPhoneCall(payload);
        setSuccessMsg('Call logged.');
      }
      
      setShowAdd(false);
      resetForm();
      setTimeout(() => setSuccessMsg(null), 3000);
    } catch (err) {
      console.error('submit error', err);
    } finally {
      setSubmitting(false);
    }
  };

  const handleFollowUpDone = async (id: number) => {
    setFollowUpBusyId(id);
    try {
      await markFollowUpDone(id);
      setSuccessMsg('Follow-up marked done.');
      setTimeout(() => setSuccessMsg(null), 3000);
    } catch (err) {
      console.error('markFollowUpDone error', err);
    } finally {
      setFollowUpBusyId(null);
    }
  };

  const formatDuration = (s: number | null | undefined) => {
    if (!s || s <= 0) return '—';
    const m = Math.floor(s / 60);
    const sec = s % 60;
    return m > 0 ? `${m}m ${sec}s` : `${sec}s`;
  };

  const BulkImportModal = () => {
    const [file, setFile] = useState<File | null>(null);
    const [importing, setImporting] = useState(false);
    const [isDragging, setIsDragging] = useState(false);
    const [progress, setProgress] = useState(0);
    const [result, setResult] = useState<any>(null);
    const [preview, setPreview] = useState<any[]>([]);
    const fileRef = React.useRef<HTMLInputElement>(null);

    const processFile = (f: File) => {
      setFile(f);
      const reader = new FileReader();
      reader.onload = (event) => {
        const text = event.target?.result as string;
        const rows = text.split('\n').slice(1, 6).map(row => row.split(','));
        setPreview(rows.map(r => ({ name: r[0], phone: r[1], type: r[2], direction: r[3] })));
      };
      reader.readAsText(f);
    };

    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      const f = e.target.files?.[0];
      if (f) processFile(f);
    };

    const handleDragOver = (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragging(true);
    };

    const handleDragLeave = () => {
      setIsDragging(false);
    };

    const handleDrop = (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragging(false);
      const f = e.dataTransfer.files?.[0];
      if (f) processFile(f);
    };

    const runImport = async () => {
      if (!file) return;
      
      setImporting(true);
      setProgress(10);
      
      const progressInterval = setInterval(() => {
        setProgress(prev => {
          if (prev >= 90) return prev;
          return prev + (90 - prev) * 0.1;
        });
      }, 500);

      try {
        const reader = new FileReader();
        reader.onload = async (event) => {
          const text = event.target?.result as string;
          const rows = text.split('\n').map(row => row.split(',').map(cell => cell.trim()));
          const headers = rows[0].map(h => h.toLowerCase().replace(/ /g, '_'));
          const callsToImport = rows.slice(1).filter(r => r.length > 1).map(row => {
            const obj: any = {};
            headers.forEach((h, i) => { obj[h] = row[i]; });
            return obj;
          });
          
          try {
            const res = await api.post('/front-office/phone-calls/bulk', { calls: callsToImport });
            clearInterval(progressInterval);
            setProgress(100);
            setTimeout(() => {
              setResult(res.data);
              setImporting(false);
              fetchPhoneCalls();
            }, 500);
          } catch (err: any) {
            clearInterval(progressInterval);
            setImporting(false);
            alert(err.response?.data?.error || 'Import failed');
          }
        };
        reader.readAsText(file);
      } catch (err) {
        clearInterval(progressInterval);
        setImporting(false);
        alert('File reading failed');
      }
    };

    return createPortal(
      <div className="fixed inset-0 bg-[#002147]/80 backdrop-blur-md z-[150] flex items-center justify-center p-4" onClick={() => setShowBulkModal(false)}>
        <div className="bg-card rounded-[2.5rem] w-full max-w-2xl shadow-2xl overflow-hidden animate-in zoom-in-95 duration-200 border border-border max-h-[90vh] flex flex-col" onClick={(e) => e.stopPropagation()}>
          <div className="px-10 py-8 bg-muted/50 border-b border-border flex justify-between items-center relative overflow-hidden shrink-0">
            <div className="absolute right-[-20px] top-[-20px] opacity-[0.03] rotate-12">
                <Upload size={180} />
            </div>
            <div className="relative z-10">
              <h2 className="text-2xl font-black text-text tracking-tight flex items-center gap-3 uppercase">
                Bulk Call Import
              </h2>
              <p className="text-xs font-bold text-text-muted uppercase tracking-widest mt-1">Import CSV call log</p>
            </div>
            <button onClick={() => setShowBulkModal(false)} className="relative z-10 w-10 h-10 flex items-center justify-center rounded-xl bg-card border border-border text-text-muted hover:text-rose-500 transition-all shadow-sm">
              <X size={20} />
            </button>
          </div>

          <div className="p-10 space-y-8 overflow-y-auto flex-1 custom-scrollbar">
            {!result && !importing && (
              <div className="bg-primary/5 rounded-2xl p-6 border border-primary/10">
                <h4 className="text-[0.65rem] font-black uppercase tracking-[2px] text-primary mb-4 flex items-center gap-2">
                  <FileText size={14} /> Column Protocol (Required Headers)
                </h4>
                <div className="flex flex-wrap gap-2">
                  {['caller_name', 'caller_phone', 'caller_type', 'direction', 'call_time', 'duration_seconds', 'purpose', 'response', 'follow_up_required', 'follow_up_date', 'notes'].map(h => (
                    <span key={h} className="px-3 py-1 bg-card border border-border text-primary rounded-lg text-[0.65rem] font-bold font-mono">
                      {h}
                    </span>
                  ))}
                </div>
                <p className="text-[0.65rem] text-text-muted mt-4 italic font-medium">
                  * caller_type: parent, student, vendor, government, other. direction: incoming, outgoing.
                </p>
              </div>
            )}

            {importing && (
              <div className="py-20 text-center space-y-6 animate-in fade-in">
                <div className="w-16 h-16 bg-primary/10 text-primary rounded-2xl flex items-center justify-center mx-auto animate-bounce">
                  <Sparkles size={32} />
                </div>
                <div className="space-y-2">
                  <h3 className="text-xl font-black text-text uppercase">Processing Records</h3>
                  <p className="text-xs font-bold text-text-muted uppercase tracking-widest">Integrating call logs...</p>
                </div>
                <div className="max-w-xs mx-auto space-y-2">
                  <div className="h-2 w-full bg-muted rounded-full overflow-hidden border border-border">
                    <div 
                      className="h-full bg-primary transition-all duration-500 ease-out"
                      style={{ width: `${progress}%` }}
                    />
                  </div>
                  <p className="text-[0.6rem] font-black text-primary text-right uppercase">{Math.round(progress)}% Complete</p>
                </div>
              </div>
            )}

            {result ? (
              <div className="space-y-6 text-center py-10 animate-in fade-in slide-in-from-bottom-4">
                <div className={`w-20 h-20 rounded-full flex items-center justify-center mx-auto shadow-inner ${result.failed > 0 ? 'bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400' : 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400'}`}>
                  {result.failed > 0 ? <AlertCircle size={40} strokeWidth={3} /> : <Check size={40} strokeWidth={3} />}
                </div>
                <div>
                  <h3 className="text-2xl font-black text-text uppercase tracking-tight">
                    {result.failed > 0 ? 'Import with Exceptions' : 'Import Complete!'}
                  </h3>
                  <p className="text-text-muted font-medium mt-2">Successfully processed call logs.</p>
                </div>
                <div className="grid grid-cols-2 gap-4 max-w-xs mx-auto">
                  <div className="bg-emerald-50/10 p-4 rounded-2xl border border-emerald-100/20">
                    <p className="text-2xl font-black text-emerald-500">{result.created}</p>
                    <p className="text-[0.6rem] font-black uppercase tracking-widest text-emerald-500">Created</p>
                  </div>
                  <div className="bg-rose-50/10 p-4 rounded-2xl border border-rose-100/20">
                    <p className="text-2xl font-black text-rose-500">{result.failed}</p>
                    <p className="text-[0.6rem] font-black uppercase tracking-widest text-rose-500">Errors</p>
                  </div>
                </div>

                {result.results.filter((r: any) => !r.success).length > 0 && (
                  <div className="text-left space-y-2 mt-6">
                    <p className="text-[0.6rem] font-black uppercase tracking-[2px] text-rose-500 px-1">Failed Rows</p>
                    <div className="bg-rose-50/5 rounded-xl border border-rose-100/10 max-h-40 overflow-y-auto custom-scrollbar">
                      {result.results.filter((r: any) => !r.success).map((r: any, i: number) => (
                        <div key={i} className="px-4 py-2 border-b border-rose-100/5 last:border-0 flex justify-between items-center gap-4">
                          <span className="text-[0.65rem] font-bold text-text truncate">{r.caller_name}</span>
                          <span className="text-[0.6rem] font-black text-rose-500 uppercase shrink-0">{r.error}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                )}

                <button 
                  onClick={() => setShowBulkModal(false)}
                  className="mt-6 px-12 py-4 bg-primary hover:bg-primary/90 text-white font-black uppercase tracking-widest text-[0.7rem] rounded-2xl transition-all shadow-xl"
                >
                  Done
                </button>
              </div>
            ) : !importing && (
              <div className="space-y-6">
                <div 
                  onClick={() => fileRef.current?.click()}
                  onDragOver={handleDragOver}
                  onDragLeave={handleDragLeave}
                  onDrop={handleDrop}
                  className={`border-2 border-dashed rounded-3xl p-12 text-center transition-all cursor-pointer group ${isDragging ? 'border-primary bg-primary/10 scale-[1.02]' : 'border-border hover:border-primary hover:bg-primary/5'}`}
                >
                  <input type="file" ref={fileRef} className="hidden" accept=".csv,.txt" onChange={handleFileChange} />
                  <div className="w-16 h-16 bg-muted rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
                    <Upload className={`transition-colors ${isDragging ? 'text-primary' : 'text-text-muted group-hover:text-primary'}`} size={32} />
                  </div>
                  <p className="text-sm font-bold text-text">{file ? file.name : 'Select CSV file to import'}</p>
                  <p className="text-xs text-text-muted mt-1 font-medium uppercase tracking-widest">Drag and drop or click to browse</p>
                </div>

                {preview.length > 0 && (
                  <div className="space-y-3">
                    <p className="text-[0.6rem] font-black uppercase tracking-[2px] text-text-muted px-1">Data Preview (Top 5 rows)</p>
                    <div className="bg-muted/50 rounded-2xl border border-border overflow-hidden overflow-x-auto">
                      <table className="w-full text-left text-[0.65rem]">
                        <thead className="bg-muted border-b border-border">
                          <tr>
                            {Object.keys(preview[0]).map(h => <th key={h} className="px-4 py-2 font-black uppercase text-text-muted">{h}</th>)}
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-border">
                          {preview.map((row, i) => (
                            <tr key={i}>
                              {Object.values(row).map((v: any, j) => <td key={j} className="px-4 py-2 font-medium text-text-secondary">{v}</td>)}
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                )}

                <div className="flex gap-4 pt-4">
                  <button 
                    disabled={!file || importing}
                    onClick={runImport}
                    className="flex-1 py-5 bg-primary hover:bg-primary/90 disabled:bg-muted disabled:text-text-muted text-white font-black uppercase tracking-widest text-[0.7rem] rounded-2xl transition-all shadow-xl active:scale-95 flex items-center justify-center gap-2"
                  >
                    <Sparkles size={16} />
                    Run Directory Import
                  </button>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    ,
      document.body
    );
  };

  return (
    <div className="p-6">
      {/* Header */}
      <div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-8">
        <div>
          <h1 className="text-2xl font-bold text-text flex items-center gap-2">
            <Phone className="text-primary" />
            Phone Call Log
          </h1>
          <p className="text-text-muted text-sm mt-1">
            Record incoming and outgoing calls. {followUpsPending > 0 && (
              <span className="text-amber-500 font-semibold ml-1">
                {followUpsPending} pending follow-up{followUpsPending === 1 ? '' : 's'}.
              </span>
            )}
          </p>
        </div>
        <div className="flex gap-3">
          <button 
            className="flex items-center gap-2 px-5 py-2.5 bg-card border border-border text-text rounded-xl font-bold text-sm hover:bg-muted/50 transition-all shadow-sm active:scale-95"
            onClick={() => setShowBulkModal(true)}
          >
            <Upload size={18} className="text-primary" />
            Bulk Import
          </button>
          <button
            onClick={() => { resetForm(); setShowAdd(true); }}
            className="flex items-center justify-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors shadow-sm"
          >
            <Plus size={20} />
            Log a Call
          </button>
        </div>
      </div>

      {successMsg && (
        <div className="mb-4 px-4 py-2 bg-emerald-500/10 text-emerald-600 border border-emerald-500/20 rounded-lg text-sm font-semibold flex items-center gap-2 animate-in fade-in duration-200">
          <CheckCircle2 size={16} /> {successMsg}
        </div>
      )}
      {error && (
        <div className="mb-4 px-4 py-2 bg-rose-500/10 text-rose-600 border border-rose-500/20 rounded-lg text-sm font-semibold flex items-center gap-2">
          <AlertCircle size={16} /> {error}
        </div>
      )}

      {/* Filters */}
      <div className="bg-card rounded-xl shadow-sm border border-border overflow-hidden">
        <div className="p-4 border-b border-border flex flex-col md:flex-row gap-3 items-stretch md:items-center justify-between bg-background-alt/50">
          <div className="relative w-full md:w-96">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted" size={18} />
            <input
              type="text"
              placeholder="Search caller, phone, purpose, handler…"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              className="w-full pl-10 pr-4 py-2 bg-background border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all text-sm text-text"
            />
          </div>
          <div className="flex flex-col md:flex-row items-stretch md:items-center gap-2">
            <div className="flex gap-1.5">
              <button
                onClick={() => setDateRange(0)}
                className="px-3 py-1.5 bg-background-alt hover:bg-muted border border-border rounded-lg text-xs font-bold text-text-secondary transition-colors whitespace-nowrap"
              >
                Today
              </button>
              <button
                onClick={() => setDateRange(7)}
                className="px-3 py-1.5 bg-background-alt hover:bg-muted border border-border rounded-lg text-xs font-bold text-text-secondary transition-colors whitespace-nowrap"
              >
                Last 7 Days
              </button>
              <button
                onClick={() => setDateRange(30)}
                className="px-3 py-1.5 bg-background-alt hover:bg-muted border border-border rounded-lg text-xs font-bold text-text-secondary transition-colors whitespace-nowrap"
              >
                Last Month
              </button>
            </div>
            
            <div className="flex items-center gap-2 bg-background p-1.5 rounded-xl border border-border shrink-0">
              <div className="flex items-center gap-1.5 px-2 text-xs font-bold uppercase tracking-widest text-text-muted">
                <Calendar size={14} />
                <span>Custom</span>
              </div>
              <input
                type="date"
                value={from}
                onChange={(e) => setFrom(e.target.value)}
                className="px-3 py-1 bg-background-alt border border-border rounded-lg text-xs font-semibold focus:outline-none focus:border-primary transition-all text-text"
              />
              <span className="text-text-muted text-xs font-bold">TO</span>
              <input
                type="date"
                value={to}
                onChange={(e) => setTo(e.target.value)}
                className="px-3 py-1 bg-background-alt border border-border rounded-lg text-xs font-semibold focus:outline-none focus:border-primary transition-all text-text"
              />
              {(from || to) && (
                <button
                  onClick={() => { setFrom(''); setTo(''); }}
                  className="p-1 text-text-muted hover:text-rose-500 hover:bg-rose-500/10 rounded-lg transition-all"
                  title="Clear Dates"
                >
                  <X size={14} />
                </button>
              )}
            </div>
          </div>
        </div>

        {/* Table */}
        <div className="overflow-x-auto">
          <table className="w-full text-left">
            <thead>
              <tr className="bg-background-alt/50 border-b border-border text-xs uppercase tracking-wider text-text-muted font-semibold">
                <th className="px-6 py-4">Caller</th>
                <th className="px-6 py-4">Type / Direction</th>
                <th className="px-6 py-4">Purpose / Response</th>
                <th className="px-6 py-4">When / Duration</th>
                <th className="px-6 py-4">Handler</th>
                <th className="px-6 py-4">Follow-up</th>
                <th className="px-6 py-4 text-right">Actions</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-border/50 text-sm">
              {loading ? (
                <tr>
                  <td colSpan={7} className="px-6 py-12 text-center text-text-muted">
                    <div className="flex flex-col items-center gap-2">
                      <div className="w-8 h-8 border-4 border-primary border-t-transparent rounded-full animate-spin"></div>
                      <span>Loading calls…</span>
                    </div>
                  </td>
                </tr>
              ) : filtered.length === 0 ? (
                <tr>
                  <td colSpan={7} className="px-6 py-12 text-center text-text-muted">
                    <Phone size={48} className="mx-auto mb-4 opacity-20" />
                    <p>No phone calls match your filters.</p>
                  </td>
                </tr>
              ) : (
                filtered.map((c) => {
                  const needsFollowUp = Number(c.follow_up_required) === 1;
                  return (
                    <tr key={c.id} className="hover:bg-background-alt/40 transition-colors">
                      <td className="px-6 py-4">
                        <div className="flex items-center gap-3">
                          <div className="w-10 h-10 rounded-full bg-primary/10 text-primary flex items-center justify-center font-bold">
                            {c.caller_name?.[0]?.toUpperCase() || '?'}
                          </div>
                          <div>
                            <p className="font-semibold text-text">{c.caller_name}</p>
                            <p className="text-xs text-text-muted mt-0.5">{c.caller_phone || '—'}</p>
                          </div>
                        </div>
                      </td>
                      <td className="px-6 py-4">
                        <div className="space-y-1">
                          <span className="capitalize px-1.5 py-0.5 bg-background-alt rounded text-text-secondary border border-border text-xs">
                            {c.caller_type}
                          </span>
                          <div className="flex items-center gap-1 text-xs text-text-muted">
                            {c.direction === 'incoming' ? (
                              <><PhoneIncoming size={12} /> Incoming</>
                            ) : (
                              <><PhoneOutgoing size={12} /> Outgoing</>
                            )}
                          </div>
                        </div>
                      </td>
                      <td className="px-6 py-4 max-w-xs">
                        <p className="text-text">{c.purpose || '—'}</p>
                        {c.response && (
                          <p className="text-xs text-text-muted mt-1 flex items-start gap-1">
                            <FileText size={12} className="mt-0.5 shrink-0" />
                            <span className="truncate">{c.response}</span>
                          </p>
                        )}
                      </td>
                      <td className="px-6 py-4">
                        <div className="space-y-1 text-xs">
                          <div className="flex items-center gap-1.5 text-text-secondary">
                            <Calendar size={12} className="text-primary" />
                            {c.call_time ? new Date(c.call_time).toLocaleDateString() : '—'}
                          </div>
                          <div className="flex items-center gap-1.5 text-text-muted">
                            <Clock size={12} />
                            {c.call_time ? new Date(c.call_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''}
                            <span className="mx-1">·</span>
                            {formatDuration(c.duration_seconds)}
                          </div>
                        </div>
                      </td>
                      <td className="px-6 py-4 text-text-secondary text-xs">
                        <div className="flex items-center gap-1.5">
                          <User size={12} className="text-text-muted" />
                          {c.handler_name || '—'}
                        </div>
                      </td>
                      <td className="px-6 py-4">
                        {needsFollowUp ? (
                          <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[0.65rem] font-black uppercase bg-amber-500/10 text-amber-600 border border-amber-500/20">
                            <AlertCircle size={10} />
                            {c.follow_up_date ? new Date(c.follow_up_date).toLocaleDateString() : 'Pending'}
                          </span>
                        ) : (
                          <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[0.65rem] font-black uppercase bg-emerald-500/10 text-emerald-600 border border-emerald-500/20">
                            <CheckCircle2 size={10} /> Done
                          </span>
                        )}
                      </td>
                      <td className="px-6 py-4 text-right">
                        <div className="flex items-center justify-end gap-2">
                          <button
                            onClick={() => handleEdit(c)}
                            className="p-1.5 text-text-muted hover:text-primary hover:bg-primary/10 rounded-lg transition-colors"
                            title="Edit Log"
                          >
                            <Edit2 size={16} />
                          </button>
                          <button
                            onClick={() => handleDelete(c.id)}
                            className="p-1.5 text-text-muted hover:text-rose-600 hover:bg-rose-500/10 rounded-lg transition-colors"
                            title="Delete Log"
                          >
                            <Trash2 size={16} />
                          </button>
                          {needsFollowUp && (
                            <button
                              disabled={followUpBusyId === c.id}
                              onClick={() => handleFollowUpDone(c.id)}
                              className="px-3 py-1.5 bg-background border border-emerald-500/30 text-emerald-600 rounded-lg hover:bg-emerald-500/10 transition-colors text-xs font-semibold flex items-center gap-1.5 ml-2 disabled:opacity-50"
                            >
                              <ArrowUpRight size={14} />
                              {followUpBusyId === c.id ? 'Saving…' : 'Mark Done'}
                            </button>
                          )}
                        </div>
                      </td>
                    </tr>
                  );
                })
              )}
            </tbody>
          </table>
        </div>
      </div>

      {/* Add modal */}
      {showAdd && createPortal(
        <div className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-[1000] flex items-center justify-center p-4" onClick={() => setShowAdd(false)}>
          <div className="bg-card rounded-[2.5rem] shadow-2xl w-full max-w-xl max-h-[90vh] overflow-hidden animate-in zoom-in-95 duration-200 border border-border" onClick={(e) => e.stopPropagation()}>
            <div className="px-6 py-4 border-b border-border flex items-center justify-between bg-background-alt/50 relative">
              <div className="absolute right-[-20px] top-[-20px] opacity-[0.03] rotate-12 text-primary">
                <Plus size={180} />
              </div>
              <div className="relative z-10">
                <h2 className="text-lg font-bold text-text flex items-center gap-2">
                  <Plus className="text-primary" size={20} />
                  {editingId ? 'Edit Phone Call' : 'Log a Phone Call'}
                </h2>
              </div>
              <button
                onClick={() => { setShowAdd(false); resetForm(); }}
                className="relative z-10 p-2 text-text-muted hover:text-text hover:bg-background-alt rounded-lg transition-colors"
                aria-label="Close"
              >
                <X size={20} />
              </button>
            </div>

            <form onSubmit={handleSubmit} className="p-6">
              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                      Caller Name <span className="text-rose-500">*</span>
                    </label>
                    <input
                      required
                      type="text"
                      value={form.caller_name}
                      onChange={e => setForm({ ...form, caller_name: e.target.value })}
                      className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      placeholder="e.g. Mrs Moyo"
                    />
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                        Caller Type
                      </label>
                      <select
                        value={form.caller_type}
                        onChange={e => setForm({ ...form, caller_type: e.target.value as FormState['caller_type'] })}
                        className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      >
                        {CALLER_TYPES.map(t => (
                          <option key={t.value} value={t.value}>{t.label}</option>
                        ))}
                      </select>
                    </div>
                    <div>
                      <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                        Direction
                      </label>
                      <select
                        value={form.direction}
                        onChange={e => setForm({ ...form, direction: e.target.value as FormState['direction'] })}
                        className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      >
                        <option value="incoming">Incoming</option>
                        <option value="outgoing">Outgoing</option>
                      </select>
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                        Phone
                      </label>
                      <input
                        type="text"
                        value={form.caller_phone}
                        onChange={e => setForm({ ...form, caller_phone: e.target.value })}
                        className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                        placeholder="+263…"
                      />
                    </div>
                    <div>
                      <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                        Duration (min)
                      </label>
                      <input
                        type="number"
                        min={0}
                        step={1}
                        value={form.duration_minutes}
                        onChange={e => setForm({ ...form, duration_minutes: Number(e.target.value) })}
                        className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      />
                    </div>
                  </div>
                </div>

                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                      When
                    </label>
                    <input
                      type="datetime-local"
                      value={form.call_time}
                      onChange={e => setForm({ ...form, call_time: e.target.value })}
                      className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                      Purpose
                    </label>
                    <input
                      type="text"
                      value={form.purpose}
                      onChange={e => setForm({ ...form, purpose: e.target.value })}
                      className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      placeholder="e.g. Fee enquiry"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                      Response
                    </label>
                    <input
                      type="text"
                      value={form.response}
                      onChange={e => setForm({ ...form, response: e.target.value })}
                      className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text"
                      placeholder="e.g. Forwarded to bursar"
                    />
                  </div>
                </div>
              </div>

              <div className="mt-6 grid grid-cols-1 md:grid-cols-3 gap-4 items-end">
                <label className="flex items-center gap-2 text-sm text-text cursor-pointer select-none">
                  <input
                    type="checkbox"
                    checked={form.follow_up_required}
                    onChange={e => setForm({ ...form, follow_up_required: e.target.checked })}
                    className="w-4 h-4 rounded border-border text-primary focus:ring-primary"
                  />
                  <span className="font-semibold">Follow-up required</span>
                </label>
                <div className="md:col-span-2">
                  <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                    Follow-up date {form.follow_up_required && <span className="text-rose-500">*</span>}
                  </label>
                  <input
                    type="date"
                    disabled={!form.follow_up_required}
                    min={todayIso()}
                    value={form.follow_up_date}
                    onChange={e => setForm({ ...form, follow_up_date: e.target.value })}
                    className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text disabled:opacity-50"
                  />
                </div>
              </div>

              <div className="mt-4">
                <label className="block text-sm font-semibold text-text-secondary mb-1.5">
                  Notes
                </label>
                <textarea
                  rows={3}
                  value={form.notes}
                  onChange={e => setForm({ ...form, notes: e.target.value })}
                  className="form-input w-full px-3 py-2 bg-background border border-border rounded-lg text-text resize-none"
                  placeholder="Any additional context…"
                />
              </div>

              <div className="mt-8 pt-6 border-t border-border flex items-center justify-end gap-3">
                <button
                  type="button"
                  onClick={() => { setShowAdd(false); resetForm(); }}
                  className="px-6 py-2 text-text-secondary hover:bg-background-alt rounded-lg transition-colors font-semibold"
                >
                  Cancel
                </button>
                <button
                  type="submit"
                  disabled={submitting}
                  className="px-8 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors shadow-lg shadow-primary/20 font-semibold disabled:opacity-50"
                >
                  {submitting ? 'Saving…' : 'Log Call'}
                </button>
              </div>
            </form>
          </div>
        </div>
      ,
        document.body
      )}
    </div>
  );
}
