// Molara — Dentist portal shell
//
// Used when the signed-in user is a dentist. Has its OWN sidebar nav
// (Home, Appointments, Dental Records, Payments, Profile) and never shows
// the patient topbar. Routes are /doctor-dashboard?tab=<tab>.

const DOC_TABS = [
  { k: 'home',         label: 'Home',           icon: 'pulse' },
  { k: 'appointments', label: 'Appointments',   icon: 'calendar' },
  { k: 'records',      label: 'Dental Records', icon: 'doc' },
  { k: 'payments',     label: 'Payments',       icon: 'card' },
  { k: 'profile',      label: 'Profile',        icon: 'user' },
];

function doctorTabFromRoute(route) {
  const q = (route.split('?')[1] || '');
  const t = new URLSearchParams(q).get('tab');
  return DOC_TABS.find((x) => x.k === t) ? t : 'home';
}

function setDoctorTab(tab) {
  window.location.hash = `/doctor-dashboard?tab=${encodeURIComponent(tab)}`;
}

// ---------- Helpers ----------
function groupConsultsByPatient(consults) {
  const map = new Map();
  consults.forEach((c) => {
    const key = c.patientName || 'Unknown patient';
    if (!map.has(key)) map.set(key, { name: key, initials: c.patientInitials || 'PT', items: [] });
    map.get(key).items.push(c);
  });
  return Array.from(map.values()).sort((a, b) => b.items.length - a.items.length);
}

function consultStatus(c) {
  // 'completed' if endedAt set, else if startedAt set 'in-progress', else 'upcoming'
  if (c.completed || c.endedAt) return 'completed';
  if (c.inProgress || c.startedAt) return 'in-progress';
  return 'upcoming';
}

// ---------- Layout ----------
function DoctorPortal({ user, route, onSignOut }) {
  const tab = doctorTabFromRoute(route);
  const consults = useConsults();
  const records = useRecords();
  const [profilePatient, setProfilePatient] = React.useState(null);
  React.useEffect(() => {
    const onOpen = (e) => setProfilePatient(e.detail);
    window.addEventListener('molara:open-patient-profile', onOpen);
    window.openPatientProfile = (p) => setProfilePatient(p);
    return () => window.removeEventListener('molara:open-patient-profile', onOpen);
  }, []);
  const TabComp = {
    home:         DoctorHome,
    appointments: DoctorAppointments,
    records:      DoctorDentalRecords,
    payments:     DoctorPayments,
    profile:      DoctorProfileTab,
  }[tab] || DoctorHome;

  return (
    <div className="ml-doc-portal" style={{
      minHeight: '100vh', background: 'var(--paper-2)', display: 'flex',
      fontFamily: 'var(--sans)',
    }}>
      <DoctorSidebar tab={tab} user={user} onSignOut={onSignOut}/>
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
        <DoctorTopStrip user={user}/>
        <WorkflowStepper
          role="doctor"
          route={route}
          consults={consults}
          onStepClick={(s) => window.doctorStepClick(s)}
        />
        <main style={{ flex: 1, padding: '32px 44px 56px', maxWidth: 1240, width: '100%', margin: '0 auto' }}>
          <TabComp consults={consults} records={records} user={user}/>
        </main>
      </div>
      {profilePatient && (
        <PatientProfileModal
          patient={profilePatient}
          consults={consults}
          records={records}
          onClose={() => setProfilePatient(null)}
        />
      )}
    </div>
  );
}

function DoctorSidebar({ tab, user, onSignOut }) {
  return (
    <aside style={{
      width: 248, flexShrink: 0,
      background: '#fff',
      borderRight: '1px solid var(--line)',
      padding: '20px 14px',
      display: 'flex', flexDirection: 'column',
      position: 'sticky', top: 0, height: '100vh',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '6px 10px 18px' }}>
        <div style={{ width: 28, height: 28, borderRadius: 8, background: 'var(--blue)', color: '#fff', display: 'grid', placeItems: 'center' }}>
          <I.pulse size={15}/>
        </div>
        <div style={{ fontFamily: 'var(--display)', fontSize: 19, letterSpacing: '-0.02em' }}>molara</div>
        <span className="ml-pill ml-pill--ghost" style={{ marginLeft: 'auto', fontSize: 10, padding: '2px 7px' }}>Dentist</span>
      </div>

      <nav style={{ display: 'grid', gap: 2 }}>
        {DOC_TABS.map((t) => {
          const Icon = I[t.icon] || I.pulse;
          const on = t.k === tab;
          return (
            <button key={t.k} onClick={() => setDoctorTab(t.k)} style={{
              display: 'flex', alignItems: 'center', gap: 11,
              padding: '9px 12px', borderRadius: 9,
              background: on ? 'var(--blue-soft)' : 'transparent',
              color: on ? 'var(--blue-deep)' : 'var(--ink-2)',
              border: 'none', cursor: 'pointer',
              fontSize: 13.5, fontFamily: 'inherit', textAlign: 'left',
              fontWeight: on ? 500 : 450,
            }}>
              <Icon size={15}/> {t.label}
            </button>
          );
        })}
      </nav>

      <div style={{ flex: 1 }}/>

      <div style={{
        padding: 14, borderRadius: 12, background: 'var(--paper-2)',
        display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8,
      }}>
        <div className="ml-avatar" style={{ width: 36, height: 36, borderRadius: '50%', fontSize: 12 }}>
          {user?.initials || 'DR'}
        </div>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontSize: 12.5, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {user?.name || 'Dentist'}
          </div>
          <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>
            <span className="ml-live"/> Online
          </div>
        </div>
      </div>
      <button onClick={onSignOut} style={{
        display: 'flex', alignItems: 'center', gap: 9,
        padding: '8px 12px', borderRadius: 8,
        background: 'transparent', border: 'none', cursor: 'pointer',
        color: 'var(--danger)', fontFamily: 'inherit', fontSize: 12.5,
      }}>
        <I.power size={14}/> Sign out
      </button>
    </aside>
  );
}

function DoctorTopStrip({ user }) {
  const today = new Date().toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' });
  return (
    <header style={{
      height: 60, padding: '0 44px',
      display: 'flex', alignItems: 'center', gap: 18,
      background: '#fff', borderBottom: '1px solid var(--line)',
      fontSize: 13, color: 'var(--ink-3)',
    }}>
      <div>{today}</div>
      <div style={{ flex: 1 }}/>
      <button aria-label="Notifications" style={{
        position: 'relative',
        width: 36, height: 36, borderRadius: '50%',
        background: 'transparent', border: '1px solid var(--line)',
        display: 'grid', placeItems: 'center', cursor: 'pointer',
        color: 'var(--ink-2)',
      }}>
        <I.bell size={15}/>
      </button>
    </header>
  );
}

// ---------- Tab: Home ----------
function DoctorHome({ consults, user }) {
  const upcoming = consults.filter((c) => consultStatus(c) === 'upcoming');
  const inProgress = consults.filter((c) => consultStatus(c) === 'in-progress');
  const past = consults.filter((c) => consultStatus(c) === 'completed');
  const greet = (() => {
    const h = new Date().getHours();
    return h < 12 ? 'Good morning' : h < 17 ? 'Good afternoon' : 'Good evening';
  })();
  const firstName = (user?.name || 'Doctor').split(' ').slice(0, 2).join(' ');

  return (
    <>
      <div style={{ marginBottom: 28 }}>
        <h1 style={{ fontSize: 36, marginBottom: 4 }}>{greet}, {firstName}.</h1>
        <p className="ml-muted" style={{ fontSize: 14, margin: 0 }}>
          {consults.length === 0 ? 'No patient consultations booked yet.' : `${consults.length} consultation${consults.length === 1 ? '' : 's'} on your roster.`}
        </p>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 28 }}>
        <DocStat label="Active" value={inProgress.length} hue="oklch(60% 0.18 25)"/>
        <DocStat label="Upcoming" value={upcoming.length} hue="var(--blue-deep)"/>
        <DocStat label="Completed" value={past.length} hue="oklch(55% 0.13 165)"/>
        <DocStat label="Patients" value={new Set(consults.map((c) => c.patientName)).size} hue="var(--ink)"/>
      </div>

      {inProgress.length > 0 && (
        <ConsultSection title="In progress" consults={inProgress} highlight/>
      )}
      <ConsultSection title="Upcoming consultations" consults={upcoming}
        empty="No upcoming consultations. Patients can book you any time you're online."/>
      <ConsultSection title="Past consultations" consults={past}
        empty="No completed consultations yet."/>
    </>
  );
}

function DocStat({ label, value, hue }) {
  return (
    <div className="ml-card" style={{ padding: 18 }}>
      <div className="ml-label" style={{ marginBottom: 8 }}>{label}</div>
      <div style={{ fontFamily: 'var(--display)', fontSize: 32, color: hue, fontWeight: 500 }}>{value}</div>
    </div>
  );
}

function ConsultSection({ title, consults, empty, highlight }) {
  return (
    <section style={{ marginBottom: 28 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginBottom: 12 }}>
        <h2 style={{ fontSize: 18, fontWeight: 500, margin: 0 }}>{title}</h2>
        <span className="ml-muted" style={{ fontSize: 13 }}>{consults.length}</span>
      </div>
      {consults.length === 0 ? (
        <div className="ml-card" style={{ padding: 22, color: 'var(--ink-3)', fontSize: 13.5 }}>
          {empty || 'Nothing here yet.'}
        </div>
      ) : (
        <div style={{ display: 'grid', gap: 10 }}>
          {consults.map((c) => <ConsultRow key={c.id} c={c} highlight={highlight}/>)}
        </div>
      )}
    </section>
  );
}

function ConsultRow({ c, highlight }) {
  const status = consultStatus(c);
  const statusPill = {
    'in-progress': { label: 'In progress', cls: 'ml-pill--mint' },
    'upcoming':    { label: 'Upcoming',    cls: 'ml-pill--ghost' },
    'completed':   { label: 'Completed',   cls: 'ml-pill--ghost' },
  }[status];
  return (
    <div className="ml-card" style={{
      padding: 16, display: 'grid',
      gridTemplateColumns: '46px 1fr auto',
      gap: 14, alignItems: 'center',
      borderColor: highlight ? 'var(--blue)' : 'var(--line)',
      background: highlight ? 'var(--blue-tint)' : '#fff',
    }}>
      <button
        onClick={() => window.openPatientProfile && window.openPatientProfile({
          name: c.patientName || 'Patient',
          initials: c.patientInitials || 'PT',
          patientId: c.patientId,
          patientEmail: c.patientEmail,
        })}
        title={`View ${c.patientName || 'patient'}'s profile`}
        className="ml-avatar"
        style={{ width: 46, height: 46, borderRadius: 12, fontSize: 14, border: 'none', cursor: 'pointer' }}>
        {c.patientInitials || 'PT'}
      </button>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 3, flexWrap: 'wrap' }}>
          <button
            onClick={() => window.openPatientProfile && window.openPatientProfile({
              name: c.patientName || 'Patient',
              initials: c.patientInitials || 'PT',
              patientId: c.patientId,
              patientEmail: c.patientEmail,
            })}
            style={{
              fontSize: 15, fontWeight: 500, background: 'none', border: 'none', padding: 0,
              cursor: 'pointer', color: 'var(--ink)', fontFamily: 'inherit', textDecoration: 'underline', textDecorationColor: 'transparent', textUnderlineOffset: 3,
            }}
            onMouseEnter={(e) => e.currentTarget.style.textDecorationColor = 'var(--ink-3)'}
            onMouseLeave={(e) => e.currentTarget.style.textDecorationColor = 'transparent'}>
            {c.patientName || 'Patient'}
          </button>
          <span className={`ml-pill ${statusPill.cls}`} style={{ fontSize: 11 }}>
            {status === 'in-progress' && <span className="ml-live"/>} {statusPill.label}
          </span>
          {c.followUp && (
            <span className="ml-pill" style={{ background: 'oklch(95% 0.06 165)', color: 'oklch(38% 0.10 165)', fontSize: 11 }}>
              Follow-up
            </span>
          )}
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-3)' }}>
          {c.reason} · {c.careType || 'Consultation'} · pain {c.severity || '—'}/10
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 3, fontFamily: 'var(--mono)' }}>
          {c.id} · {c.date} · {c.time}
        </div>
        {c.note && (
          <div style={{
            marginTop: 10,
            padding: '10px 12px',
            borderRadius: 8,
            background: 'var(--paper-2)',
            border: '1px solid var(--line-2)',
            color: 'var(--ink-2)',
            fontSize: 12.5,
            lineHeight: 1.45,
          }}>
            <div className="ml-label" style={{ marginBottom: 4 }}>Patient note</div>
            {c.note}
          </div>
        )}
      </div>
      <div style={{ display: 'flex', gap: 8 }}>
        {status !== 'completed' && (
          <button onClick={() => window.navigate(`/visit?consult=${c.id}&role=doctor`)}
            className="ml-btn ml-btn--primary" style={{ padding: '8px 14px', fontSize: 13 }}>
            <I.video size={13}/> {status === 'in-progress' ? 'Rejoin' : 'Start'}
          </button>
        )}
        {status === 'completed' && (
          <button onClick={() => window.navigate(`/visit/summary?consult=${c.id}`)}
            className="ml-btn ml-btn--ghost" style={{ padding: '8px 14px', fontSize: 13 }}>
            View summary
          </button>
        )}
      </div>
    </div>
  );
}

// ---------- Tab: Appointments — grouped by patient ----------
function DoctorAppointments({ consults }) {
  const groups = groupConsultsByPatient(consults);
  return (
    <>
      <PageHeader title="Appointments" subtitle="Every consultation booked with you, grouped by patient."/>
      {groups.length === 0 ? (
        <EmptyCard icon="calendar" title="No appointments yet" body="Once a patient books with you, they'll appear here."/>
      ) : (
        <div style={{ display: 'grid', gap: 18 }}>
          {groups.map((g) => (
            <div key={g.name} className="ml-card" style={{ padding: 22 }}>
              <PatientHeader g={g}/>
              <div style={{ display: 'grid', gap: 8, marginTop: 14 }}>
                {g.items.map((c) => <ConsultRow key={c.id} c={c}/>)}
              </div>
            </div>
          ))}
        </div>
      )}
    </>
  );
}

// ---------- Tab: Dental Records — per patient ----------
function DoctorDentalRecords({ consults, records }) {
  // Group records by their patientName (server tags this on upload).
  const groups = (() => {
    const map = new Map();
    records.forEach((r) => {
      const key = r.patientName || 'Unknown patient';
      if (!map.has(key)) {
        const fromConsult = consults.find((c) => c.patientName === key);
        map.set(key, { name: key, initials: fromConsult?.patientInitials || (key.split(' ').map((s) => s[0]).join('').slice(0, 2).toUpperCase() || 'PT'), items: [] });
      }
      map.get(key).items.push(r);
    });
    return Array.from(map.values());
  })();

  return (
    <>
      <PageHeader title="Dental records" subtitle="Files your patients have uploaded — X-rays, photos, scans, prescriptions."/>
      {groups.length === 0 ? (
        <EmptyCard icon="doc" title="No records uploaded yet" body="When patients upload images or PDFs from their portal, they'll show up here organized per patient."/>
      ) : (
        <div style={{ display: 'grid', gap: 18 }}>
          {groups.map((g) => (
            <div key={g.name} className="ml-card" style={{ padding: 22 }}>
              <PatientHeader g={g} count={`${g.items.length} file${g.items.length === 1 ? '' : 's'}`}/>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 10, marginTop: 14 }}>
                {g.items.map((r) => (
                  <a key={r.id} href={r.url || r.dataUrl || '#'} target="_blank" rel="noreferrer"
                    style={{
                      display: 'flex', alignItems: 'center', gap: 10,
                      padding: 12, borderRadius: 10, background: 'var(--paper-2)',
                      textDecoration: 'none', color: 'var(--ink)', border: '1px solid var(--line)',
                    }}>
                    <div style={{ width: 36, height: 36, borderRadius: 8, background: '#fff', display: 'grid', placeItems: 'center', color: 'var(--blue-deep)' }}>
                      <I.file size={15}/>
                    </div>
                    <div style={{ minWidth: 0, flex: 1 }}>
                      <div style={{ fontSize: 12.5, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {r.name || 'Untitled'}
                      </div>
                      <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>
                        {r.type || 'file'}{r.uploadedAt ? ` · ${new Date(r.uploadedAt).toLocaleDateString()}` : ''}
                      </div>
                    </div>
                  </a>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}
    </>
  );
}

// ---------- Tab: Payments — per patient ----------
function DoctorPayments({ consults }) {
  const groups = groupConsultsByPatient(consults);
  const total = consults.reduce((sum, c) => sum + (Number(c.fee) || 0), 0);

  return (
    <>
      <PageHeader title="Payments" subtitle="Earnings from consultations, broken down by patient."/>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 22 }}>
        <DocStat label="Lifetime earnings" value={`₹${total.toLocaleString()}`} hue="oklch(55% 0.13 165)"/>
        <DocStat label="Consultations" value={consults.length} hue="var(--blue-deep)"/>
        <DocStat label="Patients" value={groups.length} hue="var(--ink)"/>
      </div>
      {groups.length === 0 ? (
        <EmptyCard icon="card" title="No earnings yet" body="When you complete consultations, payments will appear here."/>
      ) : (
        <div style={{ display: 'grid', gap: 12 }}>
          {groups.map((g) => {
            const subtotal = g.items.reduce((sum, c) => sum + (Number(c.fee) || 0), 0);
            return (
              <div key={g.name} className="ml-card" style={{ padding: 18, display: 'grid', gridTemplateColumns: '1fr auto', gap: 16, alignItems: 'center' }}>
                <PatientHeader g={g} count={`${g.items.length} consult${g.items.length === 1 ? '' : 's'}`}/>
                <div style={{ textAlign: 'right' }}>
                  <div style={{ fontFamily: 'var(--display)', fontSize: 22 }}>₹{subtotal.toLocaleString()}</div>
                  <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>
                    {g.items.filter((c) => consultStatus(c) === 'completed').length} paid
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </>
  );
}

// ---------- Tab: Profile ----------
function DoctorProfileTab({ user }) {
  const doc = user?.doctorId ? DOC_BY_ID(user.doctorId) : null;
  return (
    <>
      <PageHeader title="Profile" subtitle="What patients see when they look you up."/>
      <div className="ml-card" style={{ padding: 28, display: 'grid', gridTemplateColumns: '1fr 360px', gap: 28 }}>
        <div>
          <div style={{ display: 'flex', gap: 18, alignItems: 'center', marginBottom: 22 }}>
            <div className="ml-avatar" style={{ width: 84, height: 84, borderRadius: '50%', fontSize: 26 }}>
              {user?.initials || 'DR'}
            </div>
            <div>
              <h2 style={{ fontSize: 26, marginBottom: 4 }}>{user?.name || 'Dentist'}</h2>
              <div style={{ color: 'var(--ink-3)', fontSize: 14 }}>
                {doc ? `${doc.creds} · ${doc.spec} · ${doc.y} yrs` : 'Dental practitioner'}
              </div>
            </div>
          </div>

          {doc && (
            <>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginBottom: 22 }}>
                <ProfileStat k="Specialty" v={doc.spec}/>
                <ProfileStat k="Experience" v={`${doc.y} years`}/>
                <ProfileStat k="Consult fee" v={`₹${doc.fee}`}/>
              </div>
              <div style={{ marginBottom: 18 }}>
                <div className="ml-label" style={{ marginBottom: 6 }}>Bio</div>
                <p style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ink-2)', margin: 0 }}>{doc.bio}</p>
              </div>
              <div>
                <div className="ml-label" style={{ marginBottom: 8 }}>Languages</div>
                <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {(doc.langs || []).map((l) => <span key={l} className="ml-pill ml-pill--ghost">{l}</span>)}
                </div>
              </div>
            </>
          )}
        </div>

        <aside style={{ display: 'grid', gap: 12, alignContent: 'start' }}>
          <div style={{ padding: 16, borderRadius: 10, background: 'var(--paper-2)' }}>
            <div className="ml-label" style={{ marginBottom: 6 }}>Status</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13.5 }}>
              <span className="ml-live"/> Online — visible to patients
            </div>
          </div>
          {doc && (
            <button onClick={() => window.navigate(`/doctor?id=${doc.id}`)}
              className="ml-btn ml-btn--ghost" style={{ justifyContent: 'center', padding: '10px 14px', fontSize: 13 }}>
              <I.arrowR size={13}/> View public profile
            </button>
          )}
        </aside>
      </div>
    </>
  );
}

function ProfileStat({ k, v }) {
  return (
    <div style={{ padding: 14, background: 'var(--paper-2)', borderRadius: 8 }}>
      <div className="ml-label" style={{ marginBottom: 5 }}>{k}</div>
      <div style={{ fontSize: 14.5, fontWeight: 500 }}>{v}</div>
    </div>
  );
}

// ---------- Shared bits ----------
function PageHeader({ title, subtitle }) {
  return (
    <div style={{ marginBottom: 22 }}>
      <h1 style={{ fontSize: 32, marginBottom: 4 }}>{title}</h1>
      {subtitle && <p className="ml-muted" style={{ fontSize: 14, margin: 0 }}>{subtitle}</p>}
    </div>
  );
}

function PatientHeader({ g, count }) {
  const open = () => window.openPatientProfile && window.openPatientProfile({
    name: g.name, initials: g.initials, patientId: g.items[0]?.patientId, patientEmail: g.items[0]?.patientEmail,
  });
  return (
    <button onClick={open}
      style={{ display: 'flex', alignItems: 'center', gap: 12, background: 'none', border: 'none', padding: 0, cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit' }}>
      <div className="ml-avatar" style={{ width: 42, height: 42, borderRadius: 12, fontSize: 13 }}>
        {g.initials}
      </div>
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ fontSize: 16, fontWeight: 500, color: 'var(--ink)' }}>{g.name}</div>
        <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>
          {count || `${g.items.length} consult${g.items.length === 1 ? '' : 's'}`} · click to view profile
        </div>
      </div>
    </button>
  );
}

function EmptyCard({ icon, title, body }) {
  const Icon = I[icon] || I.calendar;
  return (
    <div className="ml-card" style={{ padding: 56, textAlign: 'center' }}>
      <div style={{ width: 56, height: 56, borderRadius: 16, background: 'var(--blue-soft)', color: 'var(--blue-deep)', display: 'grid', placeItems: 'center', margin: '0 auto 16px' }}>
        <Icon size={24}/>
      </div>
      <h2 style={{ fontSize: 22, marginBottom: 6 }}>{title}</h2>
      <p className="ml-muted" style={{ maxWidth: 460, margin: '0 auto', fontSize: 13.5, lineHeight: 1.55 }}>
        {body}
      </p>
    </div>
  );
}

// ---------- Patient profile modal ----------
// Triggered from any consult-card avatar/name (or a patient grouping header).
// Shows the patient's full record set + every consult on file with this dentist.
function PatientProfileModal({ patient, consults, records, onClose }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  // Match by patientId where available; fall back to patientName.
  const matchesPatient = (item) => {
    if (patient.patientId && item.patientId) return item.patientId === patient.patientId;
    if (patient.patientEmail && item.patientEmail) return item.patientEmail === patient.patientEmail;
    return (item.patientName || '').toLowerCase() === (patient.name || '').toLowerCase();
  };
  const myConsults = (consults || []).filter(matchesPatient).sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0));
  const myRecords = (records || []).filter(matchesPatient).sort((a, b) => new Date(b.uploadedAt || 0) - new Date(a.uploadedAt || 0));
  const upcoming = myConsults.filter((c) => consultStatus(c) !== 'completed');
  const past = myConsults.filter((c) => consultStatus(c) === 'completed');

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(15, 22, 36, 0.45)',
      display: 'flex', justifyContent: 'flex-end', zIndex: 100,
      backdropFilter: 'blur(2px)',
    }}>
      <div onClick={(e) => e.stopPropagation()}
        style={{
          width: 'min(720px, 100%)', height: '100%', background: 'var(--paper)',
          overflowY: 'auto', boxShadow: '-12px 0 36px rgba(0,0,0,0.18)',
          display: 'flex', flexDirection: 'column',
        }}>
        {/* Header */}
        <div style={{ padding: '22px 28px', borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 14, background: '#fff', position: 'sticky', top: 0, zIndex: 1 }}>
          <div className="ml-avatar" style={{ width: 52, height: 52, borderRadius: 14, fontSize: 17 }}>
            {patient.initials || 'PT'}
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <h2 style={{ fontSize: 22, margin: 0, letterSpacing: '-0.015em' }}>{patient.name || 'Patient'}</h2>
            <div style={{ fontSize: 12.5, color: 'var(--ink-3)', marginTop: 2 }}>
              {myConsults.length} consult{myConsults.length === 1 ? '' : 's'} · {myRecords.length} record{myRecords.length === 1 ? '' : 's'} on file
              {patient.patientEmail ? ` · ${patient.patientEmail}` : ''}
            </div>
          </div>
          <button onClick={onClose} className="ml-btn ml-btn--ghost" style={{ padding: '8px 12px', fontSize: 12.5 }}>
            Close <span style={{ marginLeft: 6, opacity: 0.6 }}>esc</span>
          </button>
        </div>

        <div style={{ padding: '24px 28px 40px', display: 'grid', gap: 28 }}>

          {/* Quick stats */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}>
            <ProfileStat k="Total consults" v={myConsults.length}/>
            <ProfileStat k="Active / upcoming" v={upcoming.length}/>
            <ProfileStat k="Records uploaded" v={myRecords.length}/>
          </div>

          {/* Active consults */}
          {upcoming.length > 0 && (
            <section>
              <div className="ml-label" style={{ marginBottom: 10 }}>ACTIVE / UPCOMING</div>
              <div style={{ display: 'grid', gap: 10 }}>
                {upcoming.map((c) => <PatientConsultCard key={c.id} c={c}/>)}
              </div>
            </section>
          )}

          {/* Records */}
          <section>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10 }}>
              <div className="ml-label">PATIENT RECORDS</div>
              <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>{myRecords.length} file{myRecords.length === 1 ? '' : 's'}</span>
            </div>
            {myRecords.length === 0 ? (
              <div style={{ padding: 24, border: '1px dashed var(--line)', borderRadius: 12, fontSize: 13, color: 'var(--ink-3)', textAlign: 'center' }}>
                No records uploaded by this patient yet.
              </div>
            ) : (
              <div style={{ display: 'grid', gap: 8 }}>
                {myRecords.map((r) => <RecordRow key={r.id} r={r}/>)}
              </div>
            )}
          </section>

          {/* Past consults */}
          <section>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10 }}>
              <div className="ml-label">PAST CONSULTATIONS</div>
              <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>{past.length}</span>
            </div>
            {past.length === 0 ? (
              <div style={{ padding: 20, border: '1px dashed var(--line)', borderRadius: 12, fontSize: 13, color: 'var(--ink-3)', textAlign: 'center' }}>
                No completed consultations yet.
              </div>
            ) : (
              <div style={{ display: 'grid', gap: 10 }}>
                {past.map((c) => <PatientConsultCard key={c.id} c={c}/>)}
              </div>
            )}
          </section>
        </div>
      </div>
    </div>
  );
}

function PatientConsultCard({ c }) {
  const status = consultStatus(c);
  const statusPill = {
    'in-progress': { label: 'In progress', cls: 'ml-pill--mint' },
    'upcoming':    { label: 'Upcoming',    cls: 'ml-pill--ghost' },
    'completed':   { label: 'Completed',   cls: 'ml-pill--ghost' },
  }[status];
  return (
    <div className="ml-card" style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr auto', gap: 10, alignItems: 'center' }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 3 }}>
          <span style={{ fontSize: 14, fontWeight: 500 }}>{c.reason || 'Consultation'}</span>
          <span className={`ml-pill ${statusPill.cls}`} style={{ fontSize: 10.5 }}>{statusPill.label}</span>
          {c.followUp && <span className="ml-pill" style={{ background: 'oklch(95% 0.06 165)', color: 'oklch(38% 0.10 165)', fontSize: 10.5 }}>Follow-up</span>}
          {c.paymentStatus === 'paid' && <span className="ml-pill" style={{ background: 'oklch(95% 0.06 165)', color: 'oklch(38% 0.10 165)', fontSize: 10.5 }}>Paid ₹{c.paidAmount || c.fee}</span>}
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>
          {c.id} · {c.date} · {c.time} · {c.mode}
        </div>
        {c.note && <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 4 }}>{c.note}</div>}
      </div>
      <div style={{ display: 'flex', gap: 6 }}>
        {status !== 'completed'
          ? <button onClick={() => window.navigate(`/visit?consult=${c.id}&role=doctor`)} className="ml-btn ml-btn--primary" style={{ padding: '6px 12px', fontSize: 12 }}><I.video size={12}/> {status === 'in-progress' ? 'Rejoin' : 'Start'}</button>
          : <button onClick={() => window.navigate(`/visit/summary?consult=${c.id}`)} className="ml-btn ml-btn--ghost" style={{ padding: '6px 12px', fontSize: 12 }}>Summary</button>}
      </div>
    </div>
  );
}

function RecordRow({ r }) {
  const fileName = r.name || 'record';
  const sizeKb = r.size ? `${Math.round(r.size / 1024)} KB` : '';
  const when = r.uploadedAt ? new Date(r.uploadedAt).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) : '';
  return (
    <a href={r.url || '#'} target="_blank" rel="noopener"
       style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 12, border: '1px solid var(--line)', borderRadius: 10, background: '#fff', textDecoration: 'none', color: 'inherit' }}>
      <div style={{ width: 36, height: 36, borderRadius: 9, background: 'var(--blue-soft)', color: 'var(--blue-deep)', display: 'grid', placeItems: 'center' }}>
        <I.doc size={16}/>
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13.5, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{fileName}</div>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{[r.kind, sizeKb, when].filter(Boolean).join(' · ')}</div>
      </div>
      <I.download size={14} color="var(--ink-3)"/>
    </a>
  );
}

window.DoctorPortal = DoctorPortal;
