// encounter.jsx — Encounter screen wired to /api/sessions/{id}.
// The route param can be a session_id directly (from a visit-history click) or
// an appointment_id (from Dashboard / Schedule). For appointments we look up
// the linked session_id from the store; if there's no session yet, we show a
// "Start encounter" placeholder that routes the user to Transcribe.

const { useState: useStateE, useEffect: useEffectE, useRef: useRefE } = React;

function VitalChip({ label, value, unit }) {
  return (
    <div className="ms-vital">
      <div style={{fontSize: 11, color: "var(--ink-4)", textTransform: "uppercase", letterSpacing: 0.5, fontWeight: 600}}>{label}</div>
      <div style={{fontSize: 18, fontWeight: 600, marginTop: 2, fontFamily: "var(--font-display)"}}>
        {value || "—"}
        {unit && value && <span style={{fontSize: 11, color: "var(--ink-4)", fontWeight: 400, marginLeft: 3}}>{unit}</span>}
      </div>
    </div>
  );
}

function copyClinicalNoteText(text, onCopied) {
  const value = text || "";
  const done = () => {
    if (onCopied) onCopied();
  };
  if (navigator.clipboard && window.isSecureContext) {
    navigator.clipboard.writeText(value).then(done).catch(() => {
      const el = document.createElement("textarea");
      el.value = value;
      el.style.position = "fixed";
      el.style.opacity = "0";
      document.body.appendChild(el);
      el.select();
      document.execCommand("copy");
      document.body.removeChild(el);
      done();
    });
    return;
  }
  const el = document.createElement("textarea");
  el.value = value;
  el.style.position = "fixed";
  el.style.opacity = "0";
  document.body.appendChild(el);
  el.select();
  document.execCommand("copy");
  document.body.removeChild(el);
  done();
}

function cleanNoteLine(line) {
  return String(line || "")
    .replace(/^#{1,6}\s+/, "")
    .replace(/^[-*]\s+/, "")
    .replace(/\*\*([^*]+)\*\*/g, "$1")
    .replace(/\*([^*]+)\*/g, "$1")
    .replace(/`([^`]+)`/g, "$1")
    .trim();
}

function presentableNoteSections(text) {
  const lines = (text || "").split(/\r?\n/);
  const sections = [];
  let current = { title: "Summary", items: [] };
  const flush = () => {
    if (current.items.length || current.title !== "Summary") sections.push(current);
  };
  lines.forEach(line => {
    const trimmed = line.trim();
    if (!trimmed) return;
    if (/^#{1,6}\s+/.test(trimmed) || /^\*\*[^*]+:\*\*$/.test(trimmed) || /^[A-Z][A-Za-z /&-]{2,}:$/.test(trimmed)) {
      flush();
      current = { title: cleanNoteLine(trimmed).replace(/:$/, ""), items: [] };
      return;
    }
    current.items.push(cleanNoteLine(trimmed));
  });
  flush();
  return sections.length ? sections : [{ title: "Clinical note", items: [cleanNoteLine(text)] }];
}

function extractFollowupTextFromNote(text) {
  const lines = String(text || "").split(/\r?\n/);
  for (let i = 0; i < lines.length; i++) {
    const cleaned = cleanNoteLine(lines[i]).replace(/^follow[- ]?up\s*/i, "Follow-up").trim();
    if (!/follow[- ]?up/i.test(cleaned)) continue;
    if (cleaned.includes(":")) {
      const value = cleaned.split(":").slice(1).join(":").trim();
      if (value && !/^(not discussed|none|n\/?a)$/i.test(value)) return value;
    }
    for (let j = i + 1; j < Math.min(lines.length, i + 4); j++) {
      const value = cleanNoteLine(lines[j]);
      if (value && !/^(not discussed|none|n\/?a)$/i.test(value)) return value;
    }
  }
  const match = String(text || "").match(/(follow[- ]?up[^.\n]*(?:in|on|within|after)\s+[^.\n]+)/i);
  return match ? cleanNoteLine(match[1]) : "";
}

function followupTextFromSession(sessionData, noteText) {
  const note = (sessionData && sessionData.clinical_note) || {};
  const structured = note.structured_data || {};
  const structuredFollow = structured && typeof structured === "object" ? String(structured.follow_up || "").trim() : "";
  if (structuredFollow && !/^(not discussed|none|n\/?a)$/i.test(structuredFollow)) return structuredFollow;
  const noteFollow = extractFollowupTextFromNote(noteText || note.note_text || "");
  if (noteFollow) return noteFollow;
  const transcriptText = ((sessionData && sessionData.transcripts) || [])
    .map(seg => seg.corrected_text || seg.auto_corrected_text || seg.text || "")
    .join("\n");
  return extractFollowupTextFromNote(transcriptText);
}

function MarkdownPreview({ text, followupText }) {
  const sections = presentableNoteSections(text);
  const icons = [Icon.Clipboard, Icon.Pulse, Icon.Pill, Icon.CalendarPlus, Icon.Heart, Icon.Document];
  return (
    <div className="ms-note-preview">
      <div className="ms-note-preview-hero">
        <div className="ms-note-preview-hero-icon"><Icon.Document size={22}/></div>
        <div>
          <div className="ms-note-preview-title">Clinical Note Preview</div>
          <div className="dim" style={{fontSize: 12}}>Formatted for review and printing</div>
        </div>
      </div>
      {followupText && (
        <section className="ms-note-followup-card">
          <span className="ms-note-section-icon"><Icon.CalendarPlus size={15}/></span>
          <div>
            <h2>Follow-up</h2>
            <p>{followupText}</p>
          </div>
        </section>
      )}
      <div className="ms-note-section-grid">
        {sections.map((section, i) => {
          const I = icons[i % icons.length];
          return (
            <section key={i} className="ms-note-section-card">
              <div className="ms-note-section-head">
                <span className="ms-note-section-icon"><I size={15}/></span>
                <h2>{section.title}</h2>
              </div>
              <div className="ms-note-section-body">
                {section.items.map((item, j) => (
                  <p key={j}>{item}</p>
                ))}
              </div>
            </section>
          );
        })}
      </div>
    </div>
  );
}

function escapeHtml(value) {
  return String(value || "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

function noteMarkdownToHtml(text) {
  return presentableNoteSections(text).map(section => `
    <section>
      <h2>${escapeHtml(section.title)}</h2>
      ${section.items.map(item => `<p>${escapeHtml(item)}</p>`).join("")}
    </section>
  `).join("");
}

function ClinicalNotePreviewModal({ open, noteText, patientName, followupText, onClose }) {
  const [copied, setCopied] = useStateE(false);
  if (!open) return null;
  const title = patientName ? `Clinical note - ${patientName}` : "Clinical note";
  function handleCopy() {
    copyClinicalNoteText(noteText, () => {
      setCopied(true);
      setTimeout(() => setCopied(false), 1600);
    });
  }
  function handlePrint() {
    const printWindow = window.open("", "_blank", "width=900,height=720");
    if (!printWindow) {
      const printRoot = document.createElement("div");
      printRoot.className = "ms-print-note-root";
      printRoot.innerHTML = `<main><h1>${escapeHtml(title)}</h1>${noteMarkdownToHtml(noteText)}</main>`;
      document.body.appendChild(printRoot);
      document.body.classList.add("print-note-preview");
      window.print();
      setTimeout(() => {
        document.body.classList.remove("print-note-preview");
        printRoot.remove();
      }, 300);
      return;
    }
    printWindow.document.write(`<!doctype html><html><head><title>${escapeHtml(title)}</title><style>
      body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#111;margin:40px;line-height:1.6}
      main{max-width:760px;margin:0 auto}
      h1{font-size:24px;margin:0 0 20px} h2{font-size:18px;margin:22px 0 8px;border-bottom:1px solid #ddd;padding-bottom:6px}
      h3{font-size:15px;margin:16px 0 6px} p{font-size:13.5px;margin:6px 0;white-space:pre-wrap}
      .bullet{padding-left:18px;position:relative}.bullet:before{content:"•";position:absolute;left:4px}.blank{height:8px}
    </style></head><body><main><h1>${escapeHtml(title)}</h1>${noteMarkdownToHtml(noteText)}</main></body></html>`);
    printWindow.document.close();
    printWindow.focus();
    printWindow.print();
  }
  return (
    <div className="ms-modal-backdrop" role="dialog" aria-modal="true" aria-label={title}>
      <div className="ms-note-modal">
        <div className="ms-note-modal-head">
          <div>
            <div className="card-title">{title}</div>
            <div className="dim" style={{fontSize: 12, marginTop: 2}}>Formatted preview</div>
          </div>
          <div className="row ms-note-modal-actions">
            <button className="btn btn-sm" onClick={handleCopy}><Icon.Copy size={13}/>{copied ? "Copied" : "Copy"}</button>
            <button className="btn btn-sm" onClick={handlePrint}><Icon.Print size={13}/>Print</button>
            <button className="btn btn-ghost btn-icon btn-sm" onClick={onClose} aria-label="Close"><Icon.X size={15}/></button>
          </div>
        </div>
        <div className="ms-note-modal-body scroll">
          <MarkdownPreview text={noteText} followupText={followupText}/>
        </div>
      </div>
    </div>
  );
}

window.ClinicalNotePreviewModal = ClinicalNotePreviewModal;
window.copyClinicalNoteText = copyClinicalNoteText;
window.MSExtractFollowupText = extractFollowupTextFromNote;
window.MSFollowupTextFromSession = followupTextFromSession;

function Encounter({ appointmentId, onClose }) {
  const store = window.MSStore.useStore();
  const [session, setSession] = useStateE(null);
  const [loading, setLoading] = useStateE(true);
  const [error, setError] = useStateE(null);
  const [noteText, setNoteText] = useStateE("");
  const [savingNote, setSavingNote] = useStateE(false);
  const [savedNote, setSavedNote] = useStateE(false);
  const [appointment, setAppointment] = useStateE(null);
  const [previewOpen, setPreviewOpen] = useStateE(false);
  const [copiedNote, setCopiedNote] = useStateE(false);

  // Resolve which session to load from the route param.
  useEffectE(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    setSession(null);
    setAppointment(null);
    setNoteText("");

    (async () => {
      // First, see if the param matches an appointment in the store.
      const appt = (store.appointments || []).find(a => a.id === appointmentId);
      if (appt) setAppointment(appt);
      const candidateSessionId = appt && appt.sessionId ? appt.sessionId : appointmentId;
      try {
        const data = await store.getSession(candidateSessionId);
        if (cancelled) return;
        setSession(data);
        setNoteText((data && data.clinical_note && data.clinical_note.note_text) || "");
        setLoading(false);
      } catch (e) {
        if (cancelled) return;
        setError(e && e.message || "Could not load encounter");
        setLoading(false);
      }
    })();

    return () => { cancelled = true; };
  }, [appointmentId, store.appointments]);

  async function saveNote() {
    if (!session || !session.id || !noteText.trim() || savingNote) return;
    setSavingNote(true);
    try {
      await store.saveClinicalNote(session.id, noteText);
      setSavedNote(true);
      setTimeout(() => setSavedNote(false), 1800);
    } catch (e) {
      // Surfaced via error state if needed.
    } finally {
      setSavingNote(false);
    }
  }

  function copyNote() {
    if (!noteText.trim()) return;
    window.copyClinicalNoteText(noteText, () => {
      setCopiedNote(true);
      setTimeout(() => setCopiedNote(false), 1600);
    });
  }

  // Loading
  if (loading) {
    return (
      <div className="ms-enc fade-in">
        <div className="ms-enc-banner">
          <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon.ChevronLeft size={14}/>Back</button>
        </div>
        <div style={{padding: 60, textAlign: "center", color: "var(--ink-4)"}}>
          <Icon.Sparkle size={28}/>
          <div style={{marginTop: 10, fontSize: 13}}>Loading encounter…</div>
        </div>
      </div>
    );
  }

  // No session yet — appointment-only path
  if (error || !session) {
    const patientName = appointment ? appointment.patientName : null;
    return (
      <div className="ms-enc fade-in">
        <div className="ms-enc-banner">
          <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon.ChevronLeft size={14}/>Back</button>
          <div className="row" style={{gap: 12, flex: 1, marginLeft: 8}}>
            {patientName && (
              <div className="row" style={{gap: 12, alignItems: "center"}}>
                <div className="avatar avatar-lg" style={{width: 44, height: 44, fontSize: 14}}>
                  {(patientName || "?").split(" ").map(s => s[0]).slice(0, 2).join("").toUpperCase()}
                </div>
                <div>
                  <h2 className="h2" style={{fontSize: 18}}>{patientName}</h2>
                  {appointment && <div className="dim" style={{fontSize: 12.5, marginTop: 2}}>{appointment.type} · {appointment.duration}m · {appointment.time}</div>}
                </div>
              </div>
            )}
          </div>
        </div>
        <div style={{padding: 60, textAlign: "center", color: "var(--ink-4)", maxWidth: 520, margin: "0 auto"}}>
          <Icon.Mic size={32}/>
          <div style={{marginTop: 12, fontWeight: 600, color: "var(--ink)", fontSize: 15}}>No recorded session yet</div>
          <div style={{marginTop: 6, fontSize: 13}}>{error ? error : "Start a transcription session from the Transcribe tab to capture this visit."}</div>
        </div>
      </div>
    );
  }

  // Real session view ───────────────────────────────────────────────────────
  const patientName = session.patient_name || (appointment && appointment.patientName) || "Patient";
  const initials = (patientName || "?").split(" ").map(s => s[0]).slice(0, 2).join("").toUpperCase();
  const transcripts = session.transcripts || [];
  const note = session.clinical_note;
  const followupText = window.MSFollowupTextFromSession ? window.MSFollowupTextFromSession(session, noteText) : "";
  const startedAt = session.started_at ? new Date(session.started_at) : null;
  const duration = session.duration_seconds ? `${Math.round(session.duration_seconds / 60)}m` : "";

  return (
    <div className="ms-enc fade-in">
      {/* Top patient banner */}
      <div className="ms-enc-banner">
        <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon.ChevronLeft size={14}/>Back</button>
        <div className="row" style={{gap: 12, flex: 1, marginLeft: 8}}>
          <div className="avatar avatar-lg" style={{width: 44, height: 44, fontSize: 14}}>{initials}</div>
          <div style={{flex: 1, minWidth: 0}}>
            <div className="row" style={{gap: 8, alignItems: "baseline"}}>
              <h2 className="h2" style={{fontSize: 18}}>{patientName}</h2>
              {session.patient_age && <span className="dim" style={{fontSize: 13}}>· {session.patient_age}</span>}
            </div>
            <div className="row" style={{gap: 8, marginTop: 3}}>
              {note && <span className="badge badge-success"><span className="dot dot-success"/>Note generated</span>}
              {!note && <span className="badge">Awaiting note</span>}
            </div>
          </div>
          <div className="col" style={{alignItems: "flex-end", gap: 4}}>
            <span className="badge">{startedAt ? startedAt.toLocaleString("en-US", { dateStyle: "medium", timeStyle: "short" }) : ""}</span>
            {duration && <div style={{fontSize: 12, color: "var(--ink-4)"}}>{duration} session</div>}
          </div>
        </div>
      </div>

      <div className="ms-enc-body">
        {/* Left rail */}
        <aside className="ms-enc-rail">
          <div className="ms-rail-section">
            <div className="ms-rail-title">Vitals</div>
            <div className="ms-vitals-grid">
              <VitalChip label="BP" value={session.vitals_bp} unit="mmHg"/>
              <VitalChip label="HR" value={session.vitals_hr} unit="bpm"/>
              <VitalChip label="Temp" value={session.vitals_temp}/>
              <VitalChip label="SpO₂" value={session.vitals_spo2} unit="%"/>
              <VitalChip label="Wt" value={session.vitals_weight}/>
            </div>
          </div>

          {note && note.structured_data && (note.structured_data.diagnoses || []).length > 0 && (
            <div className="ms-rail-section">
              <div className="ms-rail-title">Diagnoses</div>
              <div className="col" style={{gap: 4}}>
                {note.structured_data.diagnoses.map((d, i) => (
                  <div key={i} className="ms-rail-item"><Icon.Pulse size={13} style={{color: "var(--ink-4)"}}/>{d}</div>
                ))}
              </div>
            </div>
          )}

          {note && note.structured_data && (note.structured_data.medications_prescribed || []).length > 0 && (
            <div className="ms-rail-section">
              <div className="ms-rail-title">Medications</div>
              <div className="col" style={{gap: 4}}>
                {note.structured_data.medications_prescribed.map((m, i) => (
                  <div key={i} className="ms-rail-item">
                    <Icon.Pill size={13}/>
                    <span style={{fontWeight: 500}}>{typeof m === "string" ? m : m.name}</span>
                    {typeof m !== "string" && m.dose && <span className="dim" style={{marginLeft: "auto", fontSize: 11.5}}>{m.dose}</span>}
                  </div>
                ))}
              </div>
            </div>
          )}
        </aside>

        {/* Main content */}
        <main className="ms-enc-main scroll">
          <div className="ms-enc-tabs">
            <div style={{flex: 1}}/>
            <span className="dim" style={{fontSize: 12.5}}>{savingNote ? "Saving…" : savedNote ? "Saved." : note && note.created_at ? `Generated ${new Date(note.created_at).toLocaleString()}` : ""}</span>
          </div>

          <div className="col" style={{gap: 20}}>
            {/* Clinical note */}
            <div className="ms-soap-pane">
              <div className="ms-soap-head">
                <div className="row" style={{gap: 10}}>
                  <span className="ms-soap-letter">N</span>
                  <span style={{fontWeight: 600, fontSize: 14}}>Clinical note</span>
                </div>
                <div className="row" style={{gap: 4}}>
                  <button className="btn btn-sm" disabled={!noteText.trim()} onClick={() => setPreviewOpen(true)}>
                    <Icon.Eye size={13}/>Preview
                  </button>
                  <button className="btn btn-sm" disabled={!noteText.trim()} onClick={copyNote}>
                    <Icon.Copy size={13}/>{copiedNote ? "Copied" : "Copy"}
                  </button>
                  <button className="btn btn-sm" disabled={savingNote || !noteText.trim()} onClick={saveNote}>
                    <Icon.Document size={13}/>{savingNote ? "Saving…" : "Save"}
                  </button>
                </div>
              </div>
              <textarea className="ms-soap-text" value={noteText} onChange={e => setNoteText(e.target.value)} placeholder="The clinical note will appear here once it's generated." style={{minHeight: 300}}/>
            </div>

            {/* Transcript */}
            <div className="card" style={{padding: 0}}>
              <div className="card-header">
                <div>
                  <div className="card-title">Transcript</div>
                  <div className="dim" style={{fontSize: 12, marginTop: 2}}>{transcripts.length} segment{transcripts.length === 1 ? "" : "s"}</div>
                </div>
              </div>
              <div className="ms-tx-lines scroll" style={{maxHeight: 360}}>
                {transcripts.length === 0 && (
                  <div style={{padding: 24, textAlign: "center", color: "var(--ink-4)", fontSize: 13}}>No transcript captured</div>
                )}
                {transcripts.map((seg, i) => {
                  const speaker = seg.speaker_label || (i % 2 === 0 ? "Provider" : "Patient");
                  const isProvider = String(speaker).toLowerCase().includes("provider") || String(speaker) === "0";
                  const text = seg.corrected_text || seg.auto_corrected_text || seg.text || "";
                  return (
                    <div key={seg.id || i} className={"ms-tx-line " + (isProvider ? "is-prov" : "is-pat")}>
                      <div className="ms-tx-who">
                        <span className="avatar avatar-sm" style={isProvider ? {background: "var(--primary-soft)", color: "var(--primary-ink)", borderColor: "var(--primary-line)"} : {}}>
                          {isProvider ? "Dr" : initials}
                        </span>
                        <div style={{fontWeight: 600, fontSize: 12}}>{isProvider ? "Provider" : "Patient"}</div>
                      </div>
                      <div className="ms-tx-text">{text}</div>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        </main>
      </div>

      {/* Bottom action bar */}
      <div className="ms-enc-foot">
        <div className="row" style={{gap: 10}}>
          <button className="btn" onClick={onClose}><Icon.ChevronLeft size={15}/>Close</button>
        </div>
        <div className="row" style={{gap: 8}}>
          <button className="btn btn-primary btn-lg" disabled={savingNote || !noteText.trim()} onClick={saveNote}>
            <Icon.Check size={16}/>{savingNote ? "Saving…" : "Save & close"}
          </button>
        </div>
      </div>

      <ClinicalNotePreviewModal
        open={previewOpen}
        noteText={noteText}
        patientName={patientName}
        followupText={followupText}
        onClose={() => setPreviewOpen(false)}
      />
    </div>
  );
}

window.Encounter = Encounter;
