// Appointments — Cal.com Clarity Call bookings, read live from Firestore
// /appointments (written by the calcomWebhook Cloud Function), plus calls booked
// by hand on a deal (stage Call Booked with a clarity call date). Tabs: Today /
// Upcoming / Past / Cancelled. Each booking is linked to its deal, contact or
// inbox lead by email/phone so a rep can jump straight to the record.

// Live subscription to /appointments. Live site only — preview/localhost has no
// Firestore, so it reports 'offline' and the view shows deal-booked calls only.
function useAppointments() {
  const [state, setState] = useState({ appointments: [], status: 'loading' });
  useEffect(() => {
    if (window.INLEARN_IS_PREVIEW || !window.firebase || !window.firebase.firestore) {
      setState({ appointments: [], status: 'offline' });
      return;
    }
    const unsub = window.firebase.firestore().collection('appointments').onSnapshot(
      (snap) => setState({ appointments: snap.docs.map(d => ({ id: d.id, ...d.data() })), status: 'live' }),
      (err) => { console.error('[appointments]', err && err.message); setState(s => ({ ...s, status: 'error' })); }
    );
    return unsub;
  }, []);
  return state;
}
window.useAppointments = useAppointments;

const apptNormEmail = (e) => String(e || '').trim().toLowerCase();
const apptNormPhone = (p) => { const d = String(p || '').replace(/\D/g, ''); return d.length >= 9 ? d.slice(-9) : d; };
const isHttpUrl = (u) => /^https?:\/\//i.test(String(u || ''));
const apptDayKey = (d) => `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
const apptTime = (iso) => iso ? new Date(iso).toLocaleTimeString('en-ZA', { hour: '2-digit', minute: '2-digit', hour12: false }) : '—';
const apptDay = (iso) => iso ? new Date(iso).toLocaleDateString('en-ZA', { weekday: 'short', day: 'numeric', month: 'short' }) : '—';

// Cal.com appointments + hand-booked deal calls, split into the four tabs.
function useAppointmentTabs(appointments, deals, contacts) {
  return useMemo(() => {
    const visible = (appointments || []).filter(a => a.status !== 'rescheduled' && a.startTime);

    // Deals with a manually booked clarity call, unless a Cal.com booking
    // already covers that person (avoid listing the same call twice).
    const bookedKeys = new Set();
    visible.forEach(a => {
      if (a.attendeeEmail) bookedKeys.add('e:' + apptNormEmail(a.attendeeEmail));
      if (a.attendeePhone) bookedKeys.add('p:' + apptNormPhone(a.attendeePhone));
    });
    const manual = (deals || [])
      .filter(d => !d.opportunityDeleted && d.stage === 'CallScheduled' && d.clarityCallDate)
      .map(d => {
        const student = getContact(contacts, d.studentId);
        const payer = getContact(contacts, d.payerId);
        const people = [student, payer].filter(Boolean);
        return { d, people };
      })
      .filter(({ people }) => !people.some(c =>
        bookedKeys.has('e:' + apptNormEmail(c.email)) || bookedKeys.has('p:' + apptNormPhone(c.phone))))
      .map(({ d, people }) => ({
        id: 'deal-' + d.id,
        source: 'crm',
        status: 'booked',
        title: d.title,
        startTime: new Date(`${d.clarityCallDate}T${d.clarityCallTime || '00:00'}`).toISOString(),
        attendeeName: people[0] ? contactFullName(people[0]) : d.title,
        attendeeEmail: people[0] ? people[0].email : '',
        attendeePhone: people[0] ? people[0].phone : '',
        dealId: d.id,
      }));

    const all = [...visible.map(a => ({ ...a, source: 'cal' })), ...manual];
    const now = new Date();
    const todayKey = apptDayKey(now);
    const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
    const byStart = (x, y) => new Date(x.startTime) - new Date(y.startTime);

    const booked = all.filter(a => a.status !== 'cancelled');
    return {
      today: booked.filter(a => apptDayKey(new Date(a.startTime)) === todayKey).sort(byStart),
      upcoming: booked.filter(a => new Date(a.startTime).getTime() >= startOfToday && apptDayKey(new Date(a.startTime)) !== todayKey).sort(byStart),
      past: booked.filter(a => new Date(a.startTime).getTime() < startOfToday).sort((x, y) => byStart(y, x)),
      cancelled: all.filter(a => a.status === 'cancelled').sort((x, y) => byStart(y, x)),
    };
  }, [appointments, deals, contacts]);
}
window.useAppointmentTabs = useAppointmentTabs;

function AppointmentsView({ appointments, status, deals, contacts, rawLeads, onSelectDeal, onSelectContact, onViewRaw }) {
  const [tab, setTab] = useState('today');
  const tabs = useAppointmentTabs(appointments, deals, contacts);

  // email/phone → the CRM record this person belongs to. Deals win over
  // contacts, contacts over inbox leads.
  const index = useMemo(() => {
    const m = new Map();
    const add = (email, phone, rec) => {
      const e = apptNormEmail(email), p = apptNormPhone(phone);
      if (e && e !== '—' && !m.has('e:' + e)) m.set('e:' + e, rec);
      if (p && !m.has('p:' + p)) m.set('p:' + p, rec);
    };
    (deals || []).filter(d => !d.opportunityDeleted).forEach(d => {
      [getContact(contacts, d.studentId), getContact(contacts, d.payerId)].filter(Boolean)
        .forEach(c => add(c.email, c.phone, { kind: 'deal', deal: d, label: d.title }));
    });
    (contacts || []).forEach(c => add(c.email, c.phone, { kind: 'contact', contact: c, label: contactFullName(c) }));
    (rawLeads || []).forEach(l => add(l.email, l.phone, { kind: 'lead', lead: l, label: l.name }));
    return m;
  }, [deals, contacts, rawLeads]);

  const linkFor = (a) => {
    if (a.dealId) {
      const d = (deals || []).find(x => x.id === a.dealId);
      return d ? { kind: 'deal', deal: d, label: d.title } : null;
    }
    return index.get('e:' + apptNormEmail(a.attendeeEmail)) || index.get('p:' + apptNormPhone(a.attendeePhone)) || null;
  };

  const openLink = (link) => {
    if (!link) return;
    if (link.kind === 'deal') onSelectDeal(link.deal);
    else if (link.kind === 'contact') onSelectContact(link.contact);
    else if (link.kind === 'lead') onViewRaw(link.lead);
  };

  const TAB_DEFS = [
    { id: 'today', label: 'Today' },
    { id: 'upcoming', label: 'Upcoming' },
    { id: 'past', label: 'Past' },
    { id: 'cancelled', label: 'Cancelled' },
  ];
  const EMPTY = {
    today: ['No appointments today', 'Clarity calls booked on Cal.com for today will appear here.'],
    upcoming: ['Nothing upcoming', 'Future Clarity Call bookings will appear here as soon as they are made.'],
    past: ['No past appointments', 'Completed Clarity Calls are kept here for reference.'],
    cancelled: ['No cancellations', 'Bookings cancelled on Cal.com will appear here.'],
  };
  const items = tabs[tab];

  return (
    <div className="px-4 sm:px-7 py-5 max-w-[1100px] mx-auto">
      <div className="flex flex-wrap items-center justify-between gap-3 mb-4">
        <div className="overflow-x-auto max-w-full">
          <SegmentedTabs tabs={TAB_DEFS.map(t => ({ ...t, count: tabs[t.id].length }))} value={tab} onChange={setTab}/>
        </div>
        <div className="text-[11px] text-slate-500 inline-flex items-center gap-1.5">
          <span className={`w-1.5 h-1.5 rounded-full ${status === 'live' ? 'bg-emerald-500' : status === 'error' ? 'bg-rose-500' : 'bg-slate-300'}`}/>
          {status === 'live' ? 'Synced live from Cal.com' : status === 'error' ? 'Could not load Cal.com bookings' : status === 'loading' ? 'Connecting…' : 'Cal.com sync runs on the live CRM'}
        </div>
      </div>

      <div className="bg-white border border-slate-200 rounded-xl overflow-hidden">
        {items.length === 0 && <Empty title={EMPTY[tab][0]} hint={EMPTY[tab][1]} icon={<Icon.Calendar size={20}/>}/>}
        <ul className="divide-y divide-slate-100">
          {items.map(a => {
            const link = linkFor(a);
            const cancelled = a.status === 'cancelled';
            return (
              <li key={a.id} className="flex items-center gap-4 px-4 sm:px-5 py-4">
                <div className="text-right shrink-0 w-[72px]">
                  <div className={`text-sm font-semibold tabular-nums ${cancelled ? 'text-slate-400 line-through' : 'text-slate-900'}`}>{apptTime(a.startTime)}</div>
                  <div className="text-[11px] text-slate-500">{apptDay(a.startTime)}</div>
                </div>
                <Avatar name={a.attendeeName || '?'} size={36}/>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2 flex-wrap">
                    <span className="text-sm font-medium text-slate-900 truncate">{a.attendeeName || 'Unknown attendee'}</span>
                    {a.source === 'crm' && <span className="text-[10px] px-1.5 py-0.5 rounded-full font-semibold bg-slate-100 text-slate-600">Booked in CRM</span>}
                    {a.rescheduledFrom && !cancelled && <span className="text-[10px] px-1.5 py-0.5 rounded-full font-semibold bg-amber-50 text-amber-700">Rescheduled</span>}
                  </div>
                  <div className="text-[11px] text-slate-500 truncate">
                    {[a.attendeeEmail, a.attendeePhone].filter(x => x && x !== '—').join(' · ') || '—'}
                  </div>
                  {cancelled && a.cancellationReason && (
                    <div className="text-[11px] text-rose-600 mt-0.5 truncate">Reason: {a.cancellationReason}</div>
                  )}
                  {!cancelled && a.notes && (
                    <div className="text-[11px] text-slate-600 italic mt-0.5 line-clamp-1">"{a.notes}"</div>
                  )}
                  {link && (
                    <button onClick={() => openLink(link)} className="sm:hidden mt-1 text-[11px] font-medium text-indigo-700 truncate max-w-full">
                      {link.kind === 'deal' ? 'Deal' : link.kind === 'contact' ? 'Contact' : 'Lead'}: {link.label} →
                    </button>
                  )}
                </div>
                <div className="hidden sm:flex flex-col items-end gap-1.5 shrink-0">
                  {link ? (
                    <button onClick={() => openLink(link)}
                      className="text-[11px] px-2 py-1 rounded-md font-medium bg-indigo-50 text-indigo-700 hover:bg-indigo-100 max-w-[220px] truncate">
                      {link.kind === 'deal' ? 'Deal' : link.kind === 'contact' ? 'Contact' : 'Lead'}: {link.label}
                    </button>
                  ) : (
                    <span className="text-[11px] px-2 py-1 rounded-md font-medium bg-slate-100 text-slate-500">Not in CRM yet</span>
                  )}
                  {isHttpUrl(a.meetingUrl) && !cancelled && tab !== 'past' && (
                    <a href={a.meetingUrl} target="_blank" rel="noopener noreferrer"
                      className="text-[11px] font-medium text-slate-600 hover:text-slate-900 underline">Join call</a>
                  )}
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </div>
  );
}
window.AppointmentsView = AppointmentsView;
