/* eslint-disable */
const { useState, useEffect, useMemo, useCallback } = React;
const Recharts = window.Recharts || {};
const { LineChart, Line, BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid, Legend } = Recharts;
const ChartsAvailable = !!(LineChart && BarChart);

const API = "";  // same origin

// ---------- helpers ----------
const fmt$ = (n) => {
  if (n == null || isNaN(n)) return "—";
  if (n === 0) return "$0";
  return "$" + Math.round(n).toLocaleString();
};
const fmt$Compact = (n) => {
  if (n == null || isNaN(n)) return "—";
  if (Math.abs(n) >= 1_000_000) return "$" + (n / 1_000_000).toFixed(1) + "M";
  if (Math.abs(n) >= 1_000) return "$" + (n / 1_000).toFixed(1) + "k";
  return "$" + n;
};
const fmtDate = (s) => s ? new Date(s + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : "—";
const fmtDateShort = (s) => s ? new Date(s + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric" }) : "—";
const todayISO = () => new Date().toISOString().split("T")[0];
const daysFromToday = (iso) => {
  if (!iso) return null;
  const d = new Date(iso + "T00:00:00");
  const t = new Date(); t.setHours(0,0,0,0);
  return Math.round((d - t) / (1000 * 60 * 60 * 24));
};

const apiGet = async (path) => {
  const r = await fetch(API + path);
  if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
  return r.json();
};
const apiSend = async (path, method, body) => {
  const r = await fetch(API + path, {
    method,
    headers: { "Content-Type": "application/json" },
    body: body ? JSON.stringify(body) : undefined,
  });
  if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
  return r.json();
};

// ---------- root app ----------
function App() {
  const [page, setPage] = useState("dashboard");
  const [dashboard, setDashboard] = useState(null);
  const [stages, setStages] = useState([]);
  const [coordinators, setCoordinators] = useState([]);
  const [toast, setToast] = useState(null);
  const [activePatientId, setActivePatientId] = useState(null);
  const [showAddPatient, setShowAddPatient] = useState(false);

  const loadDashboard = useCallback(() => apiGet("/api/dashboard").then(setDashboard).catch(() => {}), []);

  useEffect(() => {
    loadDashboard();
    apiGet("/api/stages").then(setStages).catch(() => {});
    apiGet("/api/lookups/coordinators").then(setCoordinators).catch(() => {});
  }, [loadDashboard]);

  const showToast = (msg) => {
    setToast(msg);
    setTimeout(() => setToast(null), 2400);
  };

  const refreshAll = useCallback(() => {
    loadDashboard();
    apiGet("/api/lookups/coordinators").then(setCoordinators).catch(() => {});
  }, [loadDashboard]);

  return (
    <div className="app">
      <Sidebar
        page={page}
        setPage={setPage}
        overdueCount={dashboard?.overdue_count || 0}
        dueTodayCount={dashboard?.due_today?.length || 0}
      />
      <main className="main">
        {page === "dashboard" && (
          <Dashboard
            dashboard={dashboard}
            stages={stages}
            onPatientClick={setActivePatientId}
            onAddPatient={() => setShowAddPatient(true)}
            refresh={refreshAll}
          />
        )}
        {page === "follow-ups" && (
          <FollowUps
            stages={stages}
            coordinators={coordinators}
            onPatientClick={setActivePatientId}
            refresh={refreshAll}
          />
        )}
        {page === "patients" && (
          <PatientsList
            stages={stages}
            coordinators={coordinators}
            onPatientClick={setActivePatientId}
            onAddPatient={() => setShowAddPatient(true)}
          />
        )}
        {page === "kpis" && <KPIs />}
        {page === "settings" && <Settings stages={stages} reloadStages={() => apiGet("/api/stages").then(setStages)} showToast={showToast} />}
      </main>

      {activePatientId && (
        <PatientDetailModal
          patientId={activePatientId}
          stages={stages}
          onClose={() => setActivePatientId(null)}
          onUpdate={() => { refreshAll(); }}
          showToast={showToast}
        />
      )}

      {showAddPatient && (
        <AddPatientModal
          stages={stages}
          coordinators={coordinators}
          onClose={() => setShowAddPatient(false)}
          onSaved={() => { setShowAddPatient(false); refreshAll(); showToast("Patient added"); }}
        />
      )}

      {toast && <div className="toast">{toast}</div>}
    </div>
  );
}

// ---------- sidebar ----------
function Sidebar({ page, setPage, overdueCount, dueTodayCount }) {
  const items = [
    { id: "dashboard", label: "Dashboard", section: "Today" },
    { id: "follow-ups", label: "Follow-ups", badge: overdueCount + dueTodayCount, section: "Today" },
    { id: "patients", label: "All Consultations", section: "Pipeline" },
    { id: "kpis", label: "Performance", section: "Pipeline" },
    { id: "settings", label: "Settings", section: "Configure" },
  ];
  let lastSection = null;
  return (
    <aside className="sidebar">
      <div>
        <div className="sidebar-brand">The <span className="accent">Implant</span> Center</div>
        <div className="sidebar-tagline">Treatment Tracker</div>
      </div>
      <nav className="nav">
        {items.map((item) => {
          const sectionHeader = item.section !== lastSection;
          lastSection = item.section;
          return (
            <React.Fragment key={item.id}>
              {sectionHeader && <div className="nav-section">{item.section}</div>}
              <button className={"nav-item " + (page === item.id ? "active" : "")} onClick={() => setPage(item.id)}>
                <span>{item.label}</span>
                {item.badge > 0 && <span className="nav-badge">{item.badge}</span>}
              </button>
            </React.Fragment>
          );
        })}
      </nav>
      <div className="sidebar-footer">
        Built for the TC team — focus on the follow-ups, the production follows.
      </div>
    </aside>
  );
}

// ---------- Dashboard ----------
function Dashboard({ dashboard, stages, onPatientClick, onAddPatient, refresh }) {
  const [period, setPeriod] = useState("month");
  const [kpi, setKpi] = useState(null);

  useEffect(() => {
    apiGet("/api/kpis?period=" + period).then(setKpi).catch(() => {});
  }, [period]);

  if (!dashboard) return <div className="loading">Loading dashboard…</div>;

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">Today, {fmtDate(dashboard.today)}</div>
          <h1 className="page-title">Today's <span className="italic">work</span></h1>
        </div>
        <div className="page-actions">
          <button className="btn btn-primary" onClick={onAddPatient}>+ New Consultation</button>
        </div>
      </div>

      {/* Period selector + KPIs */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
        <div className="page-eyebrow" style={{ marginBottom: 0 }}>Performance — {period}</div>
        <div className="tabs">
          {["day", "week", "month", "quarter", "year"].map((p) => (
            <button key={p} className={"tab " + (period === p ? "active" : "")} onClick={() => setPeriod(p)}>{p}</button>
          ))}
        </div>
      </div>

      <KPICards kpi={kpi} />

      {/* Follow-up panels */}
      <div className="section-grid">
        <FollowUpPanel
          title="Overdue"
          subtitle={`${dashboard.overdue_count} patients awaiting contact`}
          patients={dashboard.overdue}
          chip="overdue"
          empty="Nothing overdue. Beautiful."
          onPatientClick={onPatientClick}
        />
        <FollowUpPanel
          title="Due Today"
          subtitle={`${dashboard.due_today.length} on the schedule`}
          patients={dashboard.due_today}
          chip="due"
          empty="No follow-ups due today."
          onPatientClick={onPatientClick}
        />
      </div>

      <div className="card" style={{ marginBottom: 32 }}>
        <div className="card-header">
          <div>
            <div className="card-subtitle">Coming Up</div>
            <div className="card-title">Next 7 days</div>
          </div>
          <div className="muted" style={{ fontSize: 12, color: "var(--ink-faint)" }}>{dashboard.upcoming_7_days.length} patients</div>
        </div>
        <PatientTable patients={dashboard.upcoming_7_days} onPatientClick={onPatientClick} showFollowUp empty="The next week is clear." />
      </div>

      <div className="card">
        <div className="card-header">
          <div>
            <div className="card-subtitle">Pipeline</div>
            <div className="card-title">Stage breakdown</div>
          </div>
        </div>
        <StageBreakdown breakdown={dashboard.stage_breakdown} stages={stages} />
      </div>
    </>
  );
}

function KPICards({ kpi }) {
  if (!kpi) return null;
  return (
    <div className="kpi-grid">
      <div className="kpi">
        <div className="kpi-label">Consultations</div>
        <div className="kpi-value">{kpi.consults}</div>
        <div className="kpi-sub">{kpi.accepted_count} accepted</div>
      </div>
      <div className="kpi">
        <div className="kpi-label">Treatment Presented</div>
        <div className="kpi-value"><span className="currency-symbol">$</span>{Math.round(kpi.presented).toLocaleString()}</div>
        <div className="kpi-sub">avg case <strong>{fmt$Compact(kpi.average_case_size_presented)}</strong></div>
      </div>
      <div className="kpi">
        <div className="kpi-label">Treatment Accepted</div>
        <div className="kpi-value"><span className="currency-symbol">$</span>{Math.round(kpi.accepted_dollars).toLocaleString()}</div>
        <div className="kpi-sub">avg accepted <strong>{fmt$Compact(kpi.average_case_size_accepted)}</strong></div>
      </div>
      <div className="kpi">
        <div className="kpi-label">Case Acceptance</div>
        <div className="kpi-value">{kpi.case_acceptance_rate.toFixed(0)}<span className="small">%</span></div>
        <div className="kpi-sub"><span className="pos">${(kpi.dollar_acceptance_rate).toFixed(0)}%</span> by dollars</div>
      </div>
      <div className="kpi">
        <div className="kpi-label">Collected Today</div>
        <div className="kpi-value"><span className="currency-symbol">$</span>{Math.round(kpi.paid_collected).toLocaleString()}</div>
        <div className="kpi-sub">deposits + payments</div>
      </div>
    </div>
  );
}

function FollowUpPanel({ title, subtitle, patients, chip, empty, onPatientClick }) {
  return (
    <div className="card">
      <div className="card-header">
        <div>
          <div className="card-subtitle">{subtitle}</div>
          <div className="card-title">{title}</div>
        </div>
      </div>
      {patients.length === 0 ? (
        <div className="empty">
          <div className="empty-icon">∅</div>
          <div>{empty}</div>
        </div>
      ) : (
        <div style={{ maxHeight: 360, overflowY: "auto" }}>
          {patients.slice(0, 12).map((p) => (
            <div key={p.id}
              onClick={() => onPatientClick(p.id)}
              style={{
                padding: "12px 0",
                borderBottom: "1px solid var(--line-soft)",
                cursor: "pointer",
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
              }}
            >
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontWeight: 600, marginBottom: 4 }}>{p.name}</div>
                <div style={{ fontSize: 12, color: "var(--ink-faint)" }}>
                  {p.stage || "—"}<span className="dot-divider">·</span>
                  {fmt$Compact(p.treatment_presented)} presented
                  {p.treatment_coordinator && <><span className="dot-divider">·</span>{p.treatment_coordinator}</>}
                </div>
              </div>
              <span className={"chip chip-" + chip}>
                {chip === "overdue" ? `${Math.abs(daysFromToday(p.next_follow_up_date))}d late` : "today"}
              </span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function StageBreakdown({ breakdown, stages }) {
  const stageMap = Object.fromEntries(stages.map(s => [s.stage_name, s]));
  const sorted = [...breakdown].sort((a, b) => b.count - a.count);
  const total = sorted.reduce((sum, s) => sum + s.count, 0);
  return (
    <div>
      {sorted.map((s) => {
        const cfg = stageMap[s.stage];
        const pct = total ? (s.count / total) * 100 : 0;
        return (
          <div key={s.stage} style={{ marginBottom: 12 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>
                {s.stage}
                {cfg?.is_terminal && <span style={{ fontSize: 10, color: "var(--ink-faint)", marginLeft: 8, textTransform: "uppercase", letterSpacing: "0.1em" }}>terminal</span>}
              </div>
              <div style={{ fontSize: 12, color: "var(--ink-soft)" }}>
                {s.count} <span style={{ color: "var(--ink-faint)" }}>·</span> {fmt$Compact(s.presented)}
              </div>
            </div>
            <div style={{ height: 4, background: "var(--bone-deep)", borderRadius: 2, overflow: "hidden" }}>
              <div style={{ height: "100%", width: pct + "%", background: cfg?.color || "var(--forest)" }} />
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ---------- Follow-ups page ----------
function FollowUps({ stages, coordinators, onPatientClick, refresh }) {
  const [filter, setFilter] = useState("due");
  const [patients, setPatients] = useState([]);
  const [tcFilter, setTcFilter] = useState("");

  const load = useCallback(() => {
    let url = "/api/patients?";
    if (filter === "overdue") url += "overdue=true";
    if (filter === "due") url += "follow_up_due=true";
    if (filter === "upcoming") url += `start_date=${todayISO()}`;
    if (tcFilter) url += "&tc=" + encodeURIComponent(tcFilter);
    apiGet(url).then(setPatients).catch(() => {});
  }, [filter, tcFilter]);

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

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">Follow-up queue</div>
          <h1 className="page-title">Patients <span className="italic">waiting</span> to hear from you</h1>
        </div>
      </div>
      <div className="filters">
        <div className="tabs">
          <button className={"tab " + (filter === "due" ? "active" : "")} onClick={() => setFilter("due")}>Due now</button>
          <button className={"tab " + (filter === "overdue" ? "active" : "")} onClick={() => setFilter("overdue")}>Overdue</button>
          <button className={"tab " + (filter === "upcoming" ? "active" : "")} onClick={() => setFilter("upcoming")}>Upcoming</button>
        </div>
        <select value={tcFilter} onChange={(e) => setTcFilter(e.target.value)}>
          <option value="">All coordinators</option>
          {coordinators.map(c => <option key={c} value={c}>{c}</option>)}
        </select>
      </div>
      <PatientTable patients={patients} onPatientClick={onPatientClick} showFollowUp empty="Nothing here. Good." />
    </>
  );
}

// ---------- Patients list ----------
function PatientsList({ stages, coordinators, onPatientClick, onAddPatient }) {
  const [patients, setPatients] = useState([]);
  const [search, setSearch] = useState("");
  const [stage, setStage] = useState("");
  const [tc, setTc] = useState("");
  const [accepted, setAccepted] = useState("");

  const load = useCallback(() => {
    const params = new URLSearchParams();
    if (search) params.set("search", search);
    if (stage) params.set("stage", stage);
    if (tc) params.set("tc", tc);
    if (accepted === "yes") params.set("accepted", "true");
    if (accepted === "no") params.set("accepted", "false");
    params.set("limit", "1000");
    apiGet("/api/patients?" + params.toString()).then(setPatients).catch(() => {});
  }, [search, stage, tc, accepted]);

  useEffect(() => {
    const t = setTimeout(load, 200);
    return () => clearTimeout(t);
  }, [load]);

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">{patients.length} records</div>
          <h1 className="page-title">All <span className="italic">consultations</span></h1>
        </div>
        <div className="page-actions">
          <a className="btn btn-secondary" href="/api/export/patients.csv">Export CSV</a>
          <button className="btn btn-primary" onClick={onAddPatient}>+ New</button>
        </div>
      </div>
      <div className="filters">
        <input placeholder="Search name, notes…" value={search} onChange={(e) => setSearch(e.target.value)} style={{ minWidth: 220 }} />
        <select value={stage} onChange={(e) => setStage(e.target.value)}>
          <option value="">All stages</option>
          {stages.map(s => <option key={s.stage_name} value={s.stage_name}>{s.stage_name}</option>)}
        </select>
        <select value={tc} onChange={(e) => setTc(e.target.value)}>
          <option value="">All TCs</option>
          {coordinators.map(c => <option key={c} value={c}>{c}</option>)}
        </select>
        <select value={accepted} onChange={(e) => setAccepted(e.target.value)}>
          <option value="">All outcomes</option>
          <option value="yes">Accepted</option>
          <option value="no">Not accepted</option>
        </select>
      </div>
      <PatientTable patients={patients} onPatientClick={onPatientClick} showFollowUp empty="No patients match these filters." />
    </>
  );
}

// ---------- Reusable patient table ----------
function PatientTable({ patients, onPatientClick, showFollowUp, empty }) {
  if (!patients || patients.length === 0) {
    return <div className="empty"><div className="empty-icon">∅</div><div>{empty || "No patients."}</div></div>;
  }
  return (
    <div className="table-wrap">
      <table className="table">
        <thead>
          <tr>
            <th>Consult</th>
            <th>Patient</th>
            <th>Coordinator</th>
            <th>Stage</th>
            <th style={{ textAlign: "right" }}>Presented</th>
            <th style={{ textAlign: "right" }}>Accepted</th>
            {showFollowUp && <th>Next Follow-up</th>}
          </tr>
        </thead>
        <tbody>
          {patients.map((p) => {
            const fuDays = daysFromToday(p.next_follow_up_date);
            let chipClass = "chip-neutral";
            if (p.is_accepted) chipClass = "chip-accepted";
            else if (p.closed_lost) chipClass = "chip-firm";
            else if (fuDays != null && fuDays < 0) chipClass = "chip-overdue";
            else if (fuDays === 0) chipClass = "chip-due";
            else if (fuDays != null && fuDays > 0) chipClass = "chip-upcoming";
            return (
              <tr key={p.id} onClick={() => onPatientClick(p.id)}>
                <td className="num muted">{fmtDateShort(p.consult_date)}</td>
                <td>
                  <div className="name">{p.name}</div>
                  {p.referral_source && <div className="muted">{p.referral_source}</div>}
                </td>
                <td className="muted">{p.treatment_coordinator || "—"}</td>
                <td>
                  {p.stage ? <span className={"chip " + chipClass}>{p.stage}</span> : <span className="muted">—</span>}
                </td>
                <td className="num" style={{ textAlign: "right" }}>{fmt$Compact(p.treatment_presented)}</td>
                <td className="num" style={{ textAlign: "right", color: p.is_accepted ? "var(--moss)" : "var(--ink-faint)" }}>
                  {p.is_accepted ? fmt$Compact(p.treatment_accepted) : "—"}
                </td>
                {showFollowUp && (
                  <td className="num">
                    {p.next_follow_up_date ? (
                      <div>
                        <div>{fmtDateShort(p.next_follow_up_date)}</div>
                        {fuDays != null && (
                          <div className="muted">
                            {fuDays < 0 ? `${Math.abs(fuDays)}d overdue` : fuDays === 0 ? "today" : `in ${fuDays}d`}
                          </div>
                        )}
                      </div>
                    ) : <span className="muted">—</span>}
                  </td>
                )}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ---------- Patient detail modal ----------
function PatientDetailModal({ patientId, stages, onClose, onUpdate, showToast }) {
  const [patient, setPatient] = useState(null);
  const [editing, setEditing] = useState(false);
  const [logging, setLogging] = useState(false);

  const load = useCallback(() => {
    apiGet(`/api/patients/${patientId}`).then(setPatient).catch(() => {});
  }, [patientId]);

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

  if (!patient) return null;

  const fuDays = daysFromToday(patient.next_follow_up_date);

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal modal-large" onClick={(e) => e.stopPropagation()}>
        <div className="modal-header">
          <div>
            <div className="card-subtitle">{fmtDate(patient.consult_date)} consult</div>
            <div className="modal-title">{patient.name}</div>
          </div>
          <button className="modal-close" onClick={onClose}>✕</button>
        </div>
        <div className="modal-body">
          <div className="detail-grid">
            <div>
              <div style={{ marginBottom: 24 }}>
                <div style={{ display: "flex", gap: 8, marginBottom: 16, flexWrap: "wrap" }}>
                  {patient.stage && <span className={"chip " + (patient.is_accepted ? "chip-accepted" : "chip-neutral")}>{patient.stage}</span>}
                  {patient.referral_source && <span className="chip chip-neutral">via {patient.referral_source}</span>}
                  {patient.new_patient && <span className="chip chip-upcoming">New patient</span>}
                </div>
                <div style={{ display: "flex", gap: 8, marginBottom: 16 }}>
                  <button className="btn btn-primary" onClick={() => setLogging(true)}>+ Log contact</button>
                  <button className="btn btn-secondary" onClick={() => setEditing(!editing)}>
                    {editing ? "Cancel edit" : "Edit details"}
                  </button>
                </div>
              </div>
              {editing ? (
                <PatientEditForm patient={patient} stages={stages} onSaved={() => { setEditing(false); load(); onUpdate(); showToast("Patient updated"); }} />
              ) : (
                <>
                  {patient.notes && (
                    <>
                      <div className="card-subtitle" style={{ marginBottom: 8 }}>Consultation Notes</div>
                      <div style={{
                        background: "var(--bone)",
                        padding: 14,
                        borderRadius: 6,
                        whiteSpace: "pre-wrap",
                        fontSize: 13,
                        marginBottom: 24,
                        lineHeight: 1.6,
                      }}>{patient.notes}</div>
                    </>
                  )}
                  <div className="card-subtitle" style={{ marginBottom: 12 }}>Contact History ({patient.contacts.length})</div>
                  <div className="contact-log">
                    {patient.contacts.length === 0 ? (
                      <div className="muted" style={{ fontSize: 13, color: "var(--ink-faint)" }}>No contacts logged yet.</div>
                    ) : patient.contacts.map((c) => (
                      <div key={c.id} className="contact-entry">
                        <div className="contact-entry-head">
                          <div>
                            <span className="contact-entry-type">{c.contact_type}</span>
                            {c.outcome && <span style={{ marginLeft: 10, fontSize: 11, color: "var(--ink-faint)", textTransform: "uppercase", letterSpacing: "0.08em" }}>· {c.outcome}</span>}
                          </div>
                          <span className="contact-entry-date">{c.contact_date ? new Date(c.contact_date).toLocaleString("en-US", { month: "short", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit" }) : "—"}</span>
                        </div>
                        {c.note && <div className="contact-entry-note">{c.note}</div>}
                        {c.new_stage && <div style={{ fontSize: 11, color: "var(--forest)", marginTop: 6, fontWeight: 600 }}>→ Stage: {c.new_stage}</div>}
                        {c.by_user && <div style={{ fontSize: 11, color: "var(--ink-faint)", marginTop: 4 }}>by {c.by_user}</div>}
                      </div>
                    ))}
                  </div>
                </>
              )}
            </div>
            <div>
              <div className="card-subtitle" style={{ marginBottom: 12 }}>Snapshot</div>
              <div className="detail-stat"><span className="label">Treatment Presented</span><span className="value">{fmt$(patient.treatment_presented)}</span></div>
              <div className="detail-stat"><span className="label">Treatment Accepted</span><span className="value" style={{ color: patient.is_accepted ? "var(--moss)" : "var(--ink-faint)" }}>{patient.is_accepted ? fmt$(patient.treatment_accepted) : "—"}</span></div>
              <div className="detail-stat"><span className="label">Paid Today</span><span className="value">{fmt$(patient.amount_paid_today)}</span></div>
              <div className="detail-stat"><span className="label">Records Date</span><span className="value">{fmtDateShort(patient.records_date)}</span></div>
              <div className="detail-stat"><span className="label">Coordinator</span><span className="value">{patient.treatment_coordinator || "—"}</span></div>
              <div className="detail-stat"><span className="label">Assistant</span><span className="value">{patient.assistant || "—"}</span></div>

              <div className="card-subtitle" style={{ marginTop: 24, marginBottom: 12 }}>Follow-up</div>
              <div className="detail-stat">
                <span className="label">Next Follow-up</span>
                <span className="value">
                  {patient.next_follow_up_date ? (
                    <>
                      {fmtDateShort(patient.next_follow_up_date)}
                      {fuDays != null && <div style={{ fontSize: 11, color: fuDays < 0 ? "var(--rust)" : "var(--ink-faint)", fontWeight: 400 }}>
                        {fuDays < 0 ? `${Math.abs(fuDays)}d overdue` : fuDays === 0 ? "today" : `in ${fuDays}d`}
                      </div>}
                    </>
                  ) : "—"}
                </span>
              </div>
              <div className="detail-stat"><span className="label">Last Contact</span><span className="value">{fmtDateShort(patient.last_contact_date)}</span></div>
            </div>
          </div>
        </div>
      </div>

      {logging && (
        <LogContactModal
          patient={patient}
          stages={stages}
          onClose={() => setLogging(false)}
          onSaved={() => { setLogging(false); load(); onUpdate(); showToast("Contact logged"); }}
        />
      )}
    </div>
  );
}

function PatientEditForm({ patient, stages, onSaved }) {
  const [form, setForm] = useState({
    consult_date: patient.consult_date || "",
    name: patient.name || "",
    referral_source: patient.referral_source || "",
    treatment_coordinator: patient.treatment_coordinator || "",
    assistant: patient.assistant || "",
    treatment_presented: patient.treatment_presented || 0,
    records_date: patient.records_date || "",
    amount_paid_today: patient.amount_paid_today || 0,
    treatment_accepted: patient.treatment_accepted || 0,
    stage: patient.stage || "",
    next_follow_up_date: patient.next_follow_up_date || "",
    phone: patient.phone || "",
    email: patient.email || "",
    notes: patient.notes || "",
  });
  const set = (k, v) => setForm({ ...form, [k]: v });

  const save = async () => {
    const body = { ...form };
    body.treatment_presented = parseFloat(body.treatment_presented) || 0;
    body.treatment_accepted = parseFloat(body.treatment_accepted) || 0;
    body.amount_paid_today = parseFloat(body.amount_paid_today) || 0;
    if (!body.records_date) body.records_date = null;
    if (!body.next_follow_up_date) body.next_follow_up_date = null;
    await apiSend(`/api/patients/${patient.id}`, "PATCH", body);
    onSaved();
  };

  return (
    <div>
      <div className="form-grid">
        <div className="field"><label>Consult Date</label><input type="date" value={form.consult_date || ""} onChange={(e) => set("consult_date", e.target.value)} /></div>
        <div className="field"><label>Name</label><input value={form.name} onChange={(e) => set("name", e.target.value)} /></div>
        <div className="field"><label>Referral Source</label><input value={form.referral_source} onChange={(e) => set("referral_source", e.target.value)} /></div>
        <div className="field"><label>Coordinator</label><input value={form.treatment_coordinator} onChange={(e) => set("treatment_coordinator", e.target.value)} /></div>
        <div className="field"><label>Assistant</label><input value={form.assistant} onChange={(e) => set("assistant", e.target.value)} /></div>
        <div className="field">
          <label>Stage</label>
          <select value={form.stage || ""} onChange={(e) => set("stage", e.target.value)}>
            <option value="">— none —</option>
            {stages.map(s => <option key={s.stage_name} value={s.stage_name}>{s.stage_name}</option>)}
          </select>
        </div>
        <div className="field"><label>Treatment Presented ($)</label><input type="number" value={form.treatment_presented} onChange={(e) => set("treatment_presented", e.target.value)} /></div>
        <div className="field"><label>Treatment Accepted ($)</label><input type="number" value={form.treatment_accepted} onChange={(e) => set("treatment_accepted", e.target.value)} /></div>
        <div className="field"><label>Records Date</label><input type="date" value={form.records_date || ""} onChange={(e) => set("records_date", e.target.value)} /></div>
        <div className="field"><label>Paid Today ($)</label><input type="number" value={form.amount_paid_today} onChange={(e) => set("amount_paid_today", e.target.value)} /></div>
        <div className="field"><label>Next Follow-up</label><input type="date" value={form.next_follow_up_date || ""} onChange={(e) => set("next_follow_up_date", e.target.value)} /></div>
        <div className="field"><label>Phone</label><input value={form.phone} onChange={(e) => set("phone", e.target.value)} /></div>
        <div className="field field-full"><label>Email</label><input value={form.email} onChange={(e) => set("email", e.target.value)} /></div>
        <div className="field field-full"><label>Notes</label><textarea rows="6" value={form.notes} onChange={(e) => set("notes", e.target.value)} /></div>
      </div>
      <div style={{ marginTop: 20, display: "flex", gap: 10, justifyContent: "flex-end" }}>
        <button className="btn btn-primary" onClick={save}>Save changes</button>
      </div>
    </div>
  );
}

function LogContactModal({ patient, stages, onClose, onSaved }) {
  const [form, setForm] = useState({
    contact_type: "call",
    outcome: "",
    note: "",
    new_stage: patient.stage || "",
    next_follow_up_date: "",
    by_user: "",
  });
  const set = (k, v) => setForm({ ...form, [k]: v });

  // When stage changes, suggest a follow-up date
  useEffect(() => {
    const cfg = stages.find(s => s.stage_name === form.new_stage);
    if (cfg && !cfg.is_terminal && cfg.follow_up_days > 0) {
      const d = new Date();
      d.setDate(d.getDate() + cfg.follow_up_days);
      set("next_follow_up_date", d.toISOString().split("T")[0]);
    } else if (cfg?.is_terminal) {
      set("next_follow_up_date", "");
    }
    // eslint-disable-next-line
  }, [form.new_stage]);

  const save = async () => {
    const body = { ...form };
    if (!body.next_follow_up_date) body.next_follow_up_date = null;
    if (!body.new_stage) body.new_stage = null;
    await apiSend(`/api/patients/${patient.id}/contacts`, "POST", body);
    onSaved();
  };

  return (
    <div className="modal-backdrop" onClick={onClose} style={{ zIndex: 60 }}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-header">
          <div>
            <div className="card-subtitle">Log contact</div>
            <div className="modal-title">{patient.name}</div>
          </div>
          <button className="modal-close" onClick={onClose}>✕</button>
        </div>
        <div className="modal-body">
          <div className="form-grid">
            <div className="field">
              <label>Contact Type</label>
              <select value={form.contact_type} onChange={(e) => set("contact_type", e.target.value)}>
                <option value="call">Phone Call</option>
                <option value="vm">Voicemail</option>
                <option value="text">Text Message</option>
                <option value="email">Email</option>
                <option value="in-person">In Person</option>
                <option value="other">Other</option>
              </select>
            </div>
            <div className="field">
              <label>Outcome</label>
              <select value={form.outcome} onChange={(e) => set("outcome", e.target.value)}>
                <option value="">—</option>
                <option value="answered">Answered / connected</option>
                <option value="lvm">Left voicemail</option>
                <option value="no-answer">No answer</option>
                <option value="will-call-back">Said they'd call back</option>
                <option value="needs-time">Needs more time</option>
                <option value="declined">Declined</option>
                <option value="scheduled">Scheduled appointment</option>
                <option value="accepted">Accepted treatment</option>
              </select>
            </div>
            <div className="field">
              <label>Move to Stage</label>
              <select value={form.new_stage || ""} onChange={(e) => set("new_stage", e.target.value)}>
                <option value="">— keep current —</option>
                {stages.map(s => <option key={s.stage_name} value={s.stage_name}>{s.stage_name}</option>)}
              </select>
            </div>
            <div className="field">
              <label>Next Follow-up Date</label>
              <input type="date" value={form.next_follow_up_date || ""} onChange={(e) => set("next_follow_up_date", e.target.value)} />
            </div>
            <div className="field field-full">
              <label>Notes</label>
              <textarea rows="5" placeholder="What was discussed? Where do they stand?" value={form.note} onChange={(e) => set("note", e.target.value)} />
            </div>
            <div className="field field-full">
              <label>Logged by (your name)</label>
              <input value={form.by_user} placeholder="Brian N., BK, etc." onChange={(e) => set("by_user", e.target.value)} />
            </div>
          </div>
        </div>
        <div className="modal-footer">
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" onClick={save}>Save contact</button>
        </div>
      </div>
    </div>
  );
}

// ---------- Add patient ----------
function AddPatientModal({ stages, coordinators, onClose, onSaved }) {
  const [form, setForm] = useState({
    consult_date: todayISO(),
    name: "",
    referral_source: "",
    new_patient: true,
    treatment_coordinator: "",
    assistant: "",
    treatment_presented: 0,
    records_date: "",
    amount_paid_today: 0,
    treatment_accepted: 0,
    stage: "First Follow Up",
    phone: "",
    email: "",
    notes: "",
  });
  const set = (k, v) => setForm({ ...form, [k]: v });

  const save = async () => {
    if (!form.name || !form.consult_date) {
      alert("Name and consult date are required.");
      return;
    }
    const body = { ...form };
    body.treatment_presented = parseFloat(body.treatment_presented) || 0;
    body.treatment_accepted = parseFloat(body.treatment_accepted) || 0;
    body.amount_paid_today = parseFloat(body.amount_paid_today) || 0;
    if (!body.records_date) body.records_date = null;
    await apiSend("/api/patients", "POST", body);
    onSaved();
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal modal-large" onClick={(e) => e.stopPropagation()}>
        <div className="modal-header">
          <div>
            <div className="card-subtitle">New consultation</div>
            <div className="modal-title">Add patient</div>
          </div>
          <button className="modal-close" onClick={onClose}>✕</button>
        </div>
        <div className="modal-body">
          <div className="form-grid">
            <div className="field"><label>Consult Date *</label><input type="date" value={form.consult_date} onChange={(e) => set("consult_date", e.target.value)} /></div>
            <div className="field"><label>Patient Name *</label><input value={form.name} onChange={(e) => set("name", e.target.value)} placeholder="J. Smith" /></div>
            <div className="field"><label>Referral Source</label><input value={form.referral_source} onChange={(e) => set("referral_source", e.target.value)} placeholder="VDA, Google, Referral…" /></div>
            <div className="field">
              <label>Coordinator</label>
              <input list="coords" value={form.treatment_coordinator} onChange={(e) => set("treatment_coordinator", e.target.value)} />
              <datalist id="coords">{coordinators.map(c => <option key={c} value={c} />)}</datalist>
            </div>
            <div className="field"><label>Assistant</label><input value={form.assistant} onChange={(e) => set("assistant", e.target.value)} /></div>
            <div className="field">
              <label>Initial Stage</label>
              <select value={form.stage} onChange={(e) => set("stage", e.target.value)}>
                {stages.map(s => <option key={s.stage_name} value={s.stage_name}>{s.stage_name}</option>)}
              </select>
            </div>
            <div className="field"><label>Treatment Presented ($)</label><input type="number" value={form.treatment_presented} onChange={(e) => set("treatment_presented", e.target.value)} /></div>
            <div className="field"><label>Treatment Accepted ($)</label><input type="number" value={form.treatment_accepted} onChange={(e) => set("treatment_accepted", e.target.value)} placeholder="0 if not accepted today" /></div>
            <div className="field"><label>Records Date</label><input type="date" value={form.records_date} onChange={(e) => set("records_date", e.target.value)} /></div>
            <div className="field"><label>Paid Today ($)</label><input type="number" value={form.amount_paid_today} onChange={(e) => set("amount_paid_today", e.target.value)} /></div>
            <div className="field"><label>Phone</label><input value={form.phone} onChange={(e) => set("phone", e.target.value)} /></div>
            <div className="field"><label>Email</label><input value={form.email} onChange={(e) => set("email", e.target.value)} /></div>
            <div className="field field-full"><label>Notes</label><textarea rows="5" value={form.notes} onChange={(e) => set("notes", e.target.value)} placeholder="Treatment plan, financial situation, anything important to remember…" /></div>
          </div>
        </div>
        <div className="modal-footer">
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" onClick={save}>Save consultation</button>
        </div>
      </div>
    </div>
  );
}

// ---------- KPIs / charts page ----------
function KPIs() {
  const [period, setPeriod] = useState("year");
  const [kpi, setKpi] = useState(null);
  const [series, setSeries] = useState([]);

  useEffect(() => {
    apiGet("/api/kpis?period=" + period).then(setKpi).catch(() => {});
  }, [period]);

  useEffect(() => {
    apiGet("/api/kpis/timeseries?granularity=month&months_back=12").then(setSeries).catch(() => {});
  }, []);

  const chartData = series.map(s => ({
    period: new Date(s.period + "T00:00:00").toLocaleDateString("en-US", { month: "short", year: "2-digit" }),
    Presented: Math.round(s.presented),
    Accepted: Math.round(s.accepted),
    Consults: s.consults,
    AcceptedCount: s.accepted_count,
  }));

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">Performance</div>
          <h1 className="page-title">By the <span className="italic">numbers</span></h1>
        </div>
        <div className="tabs">
          {["day", "week", "month", "quarter", "year", "all"].map(p => (
            <button key={p} className={"tab " + (period === p ? "active" : "")} onClick={() => setPeriod(p)}>{p}</button>
          ))}
        </div>
      </div>
      <KPICards kpi={kpi} />
      {!ChartsAvailable && (
        <div className="card" style={{ marginBottom: 24 }}>
          <div className="empty">
            <div className="empty-icon">∅</div>
            <div>Charts library couldn't load. KPI numbers above are accurate — refresh the page to retry charts.</div>
          </div>
        </div>
      )}
      {ChartsAvailable && (
        <>
          <div className="card" style={{ marginBottom: 24 }}>
            <div className="card-header">
              <div>
                <div className="card-subtitle">Last 12 months</div>
                <div className="card-title">Presented vs. Accepted</div>
              </div>
            </div>
        <div style={{ height: 320 }}>
          <ResponsiveContainer>
            <BarChart data={chartData} margin={{ top: 10, right: 20, left: 0, bottom: 0 }}>
              <CartesianGrid strokeDasharray="3 3" stroke="var(--line-soft)" vertical={false} />
              <XAxis dataKey="period" tick={{ fontSize: 11 }} stroke="var(--ink-faint)" />
              <YAxis tick={{ fontSize: 11 }} stroke="var(--ink-faint)" tickFormatter={(v) => "$" + (v / 1000).toFixed(0) + "k"} />
              <Tooltip formatter={(v) => "$" + v.toLocaleString()} contentStyle={{ background: "var(--paper)", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12 }} />
              <Legend wrapperStyle={{ fontSize: 12 }} />
              <Bar dataKey="Presented" fill="var(--bone-deep)" radius={[3, 3, 0, 0]} />
              <Bar dataKey="Accepted" fill="var(--forest)" radius={[3, 3, 0, 0]} />
            </BarChart>
          </ResponsiveContainer>
        </div>
      </div>
      <div className="card">
        <div className="card-header">
          <div>
            <div className="card-subtitle">Volume</div>
            <div className="card-title">Consults &amp; acceptance count</div>
          </div>
        </div>
        <div style={{ height: 280 }}>
          <ResponsiveContainer>
            <LineChart data={chartData} margin={{ top: 10, right: 20, left: 0, bottom: 0 }}>
              <CartesianGrid strokeDasharray="3 3" stroke="var(--line-soft)" vertical={false} />
              <XAxis dataKey="period" tick={{ fontSize: 11 }} stroke="var(--ink-faint)" />
              <YAxis tick={{ fontSize: 11 }} stroke="var(--ink-faint)" />
              <Tooltip contentStyle={{ background: "var(--paper)", border: "1px solid var(--line)", borderRadius: 6, fontSize: 12 }} />
              <Legend wrapperStyle={{ fontSize: 12 }} />
              <Line type="monotone" dataKey="Consults" stroke="var(--ink)" strokeWidth={2} dot={{ r: 3 }} />
              <Line type="monotone" dataKey="AcceptedCount" stroke="var(--forest)" strokeWidth={2} dot={{ r: 3 }} />
            </LineChart>
              </ResponsiveContainer>
            </div>
          </div>
        </>
      )}
    </>
  );
}

// ---------- Settings ----------
function Settings({ stages, reloadStages, showToast }) {
  const [edits, setEdits] = useState({});
  useEffect(() => {
    setEdits(Object.fromEntries(stages.map(s => [s.id, s.follow_up_days])));
  }, [stages]);

  const save = async (id) => {
    await apiSend(`/api/stages/${id}`, "PATCH", { follow_up_days: parseInt(edits[id]) || 0 });
    await reloadStages();
    showToast("Cadence updated");
  };

  return (
    <>
      <div className="page-header">
        <div>
          <div className="page-eyebrow">Configure</div>
          <h1 className="page-title">Follow-up <span className="italic">cadence</span></h1>
        </div>
      </div>
      <div className="card">
        <div className="card-header">
          <div>
            <div className="card-subtitle">Per-stage rules</div>
            <div className="card-title">When should the TC follow up?</div>
          </div>
        </div>
        <p style={{ fontSize: 13, color: "var(--ink-soft)", marginBottom: 20, lineHeight: 1.6 }}>
          When a patient is moved to a stage, the next follow-up date is automatically set to <em style={{ fontFamily: "var(--serif)" }}>today + N days</em> based on these values. Terminal stages (accepted, declined, do-not-contact) don't trigger follow-ups.
        </p>
        <table className="table">
          <thead>
            <tr>
              <th>Stage</th>
              <th>Description</th>
              <th style={{ textAlign: "right" }}>Days until follow-up</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {stages.map(s => (
              <tr key={s.id} style={{ cursor: "default" }}>
                <td><span className="chip" style={{ background: "var(--bone-deep)", color: s.color || "var(--ink)" }}>{s.stage_name}</span></td>
                <td className="muted">{s.description}</td>
                <td style={{ textAlign: "right" }}>
                  {s.is_terminal ? <span className="muted">— terminal —</span> : (
                    <input
                      type="number"
                      value={edits[s.id] ?? s.follow_up_days}
                      onChange={(e) => setEdits({ ...edits, [s.id]: e.target.value })}
                      style={{ width: 70, textAlign: "right", padding: "5px 8px", border: "1px solid var(--line)", borderRadius: 4, fontFamily: "var(--mono)" }}
                    />
                  )}
                </td>
                <td>
                  {!s.is_terminal && edits[s.id] != s.follow_up_days && (
                    <button className="btn btn-sm btn-primary" onClick={() => save(s.id)}>Save</button>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="card" style={{ marginTop: 24 }}>
        <div className="card-header">
          <div>
            <div className="card-subtitle">Coming soon</div>
            <div className="card-title">Open Dental integration</div>
          </div>
        </div>
        <p style={{ fontSize: 13, color: "var(--ink-soft)", lineHeight: 1.6 }}>
          Once Open Dental's API is connected, the system will reconcile accepted treatment plans against actual production, surface drop-offs between consultation and procedure, and pull patient phone/email automatically. Endpoints are stubbed — wire up <code style={{ background: "var(--bone-deep)", padding: "1px 5px", borderRadius: 3, fontFamily: "var(--mono)", fontSize: 12 }}>OPEN_DENTAL_BASE_URL</code> and <code style={{ background: "var(--bone-deep)", padding: "1px 5px", borderRadius: 3, fontFamily: "var(--mono)", fontSize: 12 }}>OPEN_DENTAL_API_KEY</code> when ready.
        </p>
      </div>
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
