import { useState, useRef, useEffect } from "react";
import {
  Bot,
  X,
  ChevronRight,
  Stethoscope,
  Calendar,
  FileText,
  MessageSquare,
  Send,
  Loader2,
  RotateCcw,
  Paperclip,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { useLocation } from "wouter";
import { cn } from "@/lib/utils";
import { apiRequest } from "@/lib/queryClient";
import { setChatbotPendingFiles } from "@/lib/chatbotFileStore";

type Step =
  | "menu"
  | "eligibility-input"
  | "eligibility-confirm"
  | "ai-loading"
  | "patient-found"
  | "eligibility-id-ready"
  | "batch-eligibility-ready"
  | "check-and-claim-ready"
  | "need-insurance-clarification"
  | "need-appointment-selection"
  | "need-cdt-clarification"
  | "claim-ready"
  | "batch-claim-ready"
  | "batch-check-and-claim-ready"
  | "preauth-ready";

interface Message {
  id: number;
  role: "bot" | "user";
  text: string;
  isLoading?: boolean;
}

interface PatientResult {
  id: number;
  firstName: string;
  lastName: string;
  insuranceId: string | null;
  insuranceProvider: string | null;
  dateOfBirth: string | null;
}

interface EligibilityData {
  memberId: string;
  dob: string;
  dobISO: string;
}

interface CheckAndClaimData {
  patient: PatientResult | null;
  memberId: string;
  dob: string;          // ISO YYYY-MM-DD
  siteKey: string;
  autoCheck: string;
  matchedCodes: { code: string; description: string }[];
  serviceDate?: string | null;
  renderingProvider?: string | null;
}

let msgCounter = 0;
function makeMsg(role: "bot" | "user", text: string, isLoading = false): Message {
  return { id: ++msgCounter, role, text, isLoading };
}

function getAutoCheck(dobISO: string): "mh" | "cmsp" {
  const [y, m, d] = dobISO.split("-").map(Number);
  const today = new Date();
  let age = today.getFullYear() - (y ?? 0);
  const monthDiff = today.getMonth() + 1 - (m ?? 0);
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < (d ?? 0))) age--;
  return age >= 21 ? "mh" : "cmsp";
}

function parseEligibilityInput(
  raw: string
): { memberId: string; display: string; iso: string } | null {
  const dateMatch = raw.match(/\b(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})\b/);
  if (!dateMatch) return null;
  const m = dateMatch[1];
  const d = dateMatch[2];
  const y = dateMatch[3];
  if (!m || !d || !y) return null;
  const month = parseInt(m, 10);
  const day = parseInt(d, 10);
  const year = parseInt(y, 10);
  if (month < 1 || month > 12 || day < 1 || day > 31 || year < 1900) return null;

  const withoutDate = raw.replace(dateMatch[0], "");
  const memberId = (withoutDate.match(/[a-zA-Z0-9]/g) ?? []).join("");
  if (!memberId) return null;

  return {
    memberId,
    display: `${m.padStart(2, "0")}/${d.padStart(2, "0")}/${y}`,
    iso: `${y}-${m.padStart(2, "0")}-${d.padStart(2, "0")}`,
  };
}

const CHAT_STORAGE_KEY = "chatbot_messages";
const CHATBOT_JOB_TS_KEY = "chatbot_job_started_at";

function markJobStarted() {
  try { sessionStorage.setItem(CHATBOT_JOB_TS_KEY, String(Date.now())); } catch {}
}

function shouldAutoReset(): boolean {
  try {
    const ts = sessionStorage.getItem(CHATBOT_JOB_TS_KEY);
    if (!ts) return false;
    return Date.now() - Number(ts) > 60_000;
  } catch { return false; }
}

function loadSavedMessages(): Message[] {
  try {
    const raw = sessionStorage.getItem(CHAT_STORAGE_KEY);
    if (raw) return JSON.parse(raw) as Message[];
  } catch {}
  return [makeMsg("bot", "Hi! What can I help you with today?")];
}

const WELCOME = [makeMsg("bot", "Hi! What can I help you with today?")];

let saveTimer: ReturnType<typeof setTimeout> | null = null;
function saveChatHistoryToServer(msgs: Message[]) {
  if (saveTimer) clearTimeout(saveTimer);
  saveTimer = setTimeout(() => {
    const saveable = msgs.filter((m) => !m.isLoading);
    fetch("/api/ai/chat-history", {
      method: "PUT",
      headers: { "Content-Type": "application/json", Authorization: `Bearer ${localStorage.getItem("token") ?? ""}` },
      body: JSON.stringify({ messages: saveable }),
    }).catch(() => {});
  }, 500);
}

function clearChatHistoryOnServer() {
  fetch("/api/ai/chat-history", {
    method: "DELETE",
    headers: { Authorization: `Bearer ${localStorage.getItem("token") ?? ""}` },
  }).catch(() => {});
}

export function ChatbotButton() {
  const [open, setOpen] = useState(false);
  const [step, setStep] = useState<Step>("menu");
  const [messages, setMessages] = useState<Message[]>(loadSavedMessages);
  const [pasteInput, setPasteInput] = useState("");
  const [parseError, setParseError] = useState("");
  const [eligibilityData, setEligibilityData] = useState<EligibilityData | null>(null);
  const [freeTextInput, setFreeTextInput] = useState("");
  const [patientResult, setPatientResult] = useState<PatientResult | null>(null);
  const [eligibilityIdData, setEligibilityIdData] = useState<{ memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null; appointmentDate?: string | null } | null>(null);
  const [batchEligibilityData, setBatchEligibilityData] = useState<{ memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null }[] | null>(null);
  const [checkAndClaimData, setCheckAndClaimData] = useState<CheckAndClaimData | null>(null);
  const [clarificationData, setClarificationData] = useState<{ memberId: string; dob: string; patient: PatientResult | null; procedureNames: string[]; options: string[] } | null>(null);
  const [apptSelectionData, setApptSelectionData] = useState<{
    patient: PatientResult;
    siteKey: string;
    matchedCodes: { code: string; description: string }[];
    options: { label: string; appointmentId: number; serviceDate: string }[];
  } | null>(null);
  const [cdtClarificationData, setCdtClarificationData] = useState<{
    unknownPhrases: string[];
    codeInputs: Record<string, string>;
    originalMessage: string;
  } | null>(null);
  const [claimReadyData, setClaimReadyData] = useState<{
    patient: PatientResult | null;
    matchedCodes: { code: string; description: string }[];
    siteKey: string;
    serviceDate: string;
    appointmentId: number | null;
    renderingProvider: string | null;
  } | null>(null);
  const [batchCheckAndClaimData, setBatchCheckAndClaimData] = useState<{
    queue: { memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null }[];
    matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
    renderingProvider: string | null;
  } | null>(null);
  const [batchClaimData, setBatchClaimData] = useState<{
    queue: { patient: PatientResult; siteKey: string; serviceDate: string | null; appointmentId: number | null }[];
    matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
    renderingProvider: string | null;
  } | null>(null);
  const [preauthReadyData, setPreauthReadyData] = useState<{
    patient: PatientResult | null;
    matchedCodes: { code: string; description: string; toothNumber?: string }[];
    siteKey: string;
    serviceDate: string;
    renderingProvider: string | null;
  } | null>(null);
  const [pendingFiles, setPendingFiles] = useState<File[]>([]);
  const [, setLocation] = useLocation();
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const pasteRef = useRef<HTMLTextAreaElement>(null);
  const freeTextRef = useRef<HTMLTextAreaElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Load chat history from server on first mount (server is source of truth)
  const serverLoaded = useRef(false);
  useEffect(() => {
    if (serverLoaded.current) return;
    serverLoaded.current = true;
    const token = localStorage.getItem("token");
    if (!token) return;
    fetch("/api/ai/chat-history", {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then((data) => {
        if (Array.isArray(data.messages) && data.messages.length > 0) {
          setMessages(data.messages);
          try { sessionStorage.setItem(CHAT_STORAGE_KEY, JSON.stringify(data.messages)); } catch {}
        }
      })
      .catch(() => {});
  }, []);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages, step]);

  // Persist messages to sessionStorage AND server
  useEffect(() => {
    try {
      const saveable = messages.filter((m) => !m.isLoading);
      sessionStorage.setItem(CHAT_STORAGE_KEY, JSON.stringify(saveable));
      saveChatHistoryToServer(messages);
    } catch {}
  }, [messages]);

  useEffect(() => {
    if (step === "eligibility-input") {
      setTimeout(() => pasteRef.current?.focus(), 50);
    }
    if (step === "menu") {
      setTimeout(() => freeTextRef.current?.focus(), 50);
    }
  }, [step]);

  const addMsg = (role: "bot" | "user", text: string, isLoading = false) =>
    setMessages((prev) => [...prev, makeMsg(role, text, isLoading)]);

  const replaceLastMsg = (text: string) =>
    setMessages((prev) => {
      const next = [...prev];
      const last = next[next.length - 1];
      if (last) next[next.length - 1] = { ...last, text, isLoading: false };
      return next;
    });

  // Resets step/data only — keeps message history
  const resetStep = () => {
    setStep("menu");
    setPasteInput("");
    setParseError("");
    setEligibilityData(null);
    setFreeTextInput("");
    setPatientResult(null);
    setEligibilityIdData(null);
    setBatchEligibilityData(null);
    setCheckAndClaimData(null);
    setClarificationData(null);
    setApptSelectionData(null);
    setCdtClarificationData(null);
    setClaimReadyData(null);
    setBatchClaimData(null);
    setBatchCheckAndClaimData(null);
    setPreauthReadyData(null);
  };

  // Full reset including message history and stored session
  const reset = () => {
    resetStep();
    setPendingFiles([]);
    const fresh = [makeMsg("bot", "Hi! What can I help you with today?")];
    try {
      sessionStorage.setItem(CHAT_STORAGE_KEY, JSON.stringify(fresh));
    } catch {}
    clearChatHistoryOnServer();
    setMessages(fresh);
  };

  const handleClose = () => {
    setOpen(false);
    resetStep();
  };

  const handleOptionSelect = (option: "eligibility" | "schedule" | "claims") => {
    if (option === "schedule") {
      addMsg("user", "Schedule an appointment");
      addMsg("bot", "Opening the appointments page...");
      setTimeout(() => { setLocation("/appointments"); setOpen(false); resetStep(); }, 600);
    } else if (option === "claims") {
      addMsg("user", "View claims");
      addMsg("bot", "Opening the claims page...");
      setTimeout(() => { setLocation("/claims"); setOpen(false); resetStep(); }, 600);
    } else if (option === "eligibility") {
      addMsg("user", "Check Eligibility");
      addMsg("bot", "Please enter the patient's Member ID and Date of Birth:");
      setStep("eligibility-input");
    }
  };

  const handleEligibilitySubmit = () => {
    const parsed = parseEligibilityInput(pasteInput);
    if (!parsed) {
      setParseError("Couldn't find both a Member ID and a date. Try: 123456789  01/15/1985");
      return;
    }
    setParseError("");
    const data: EligibilityData = { memberId: parsed.memberId, dob: parsed.display, dobISO: parsed.iso };
    setEligibilityData(data);
    addMsg("user", pasteInput.trim());
    addMsg("bot", `Ready to check MassHealth eligibility for:\n• Member ID: ${parsed.memberId}\n• Date of Birth: ${parsed.display}\n\nShall I proceed?`);
    setStep("eligibility-confirm");
  };

  const handleConfirm = () => {
    if (!eligibilityData) return;
    addMsg("user", "Yes, check now");
    addMsg("bot", "Opening the eligibility check page with this patient...");
    sessionStorage.setItem("chatbot_eligibility", JSON.stringify({
      memberId: eligibilityData.memberId,
      dob: eligibilityData.dobISO,
      autoCheck: getAutoCheck(eligibilityData.dobISO),
    }));
    window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
    setTimeout(() => { setLocation("/insurance-status"); setOpen(false); resetStep(); }, 600);
  };

  const handleEligibilityFromPatient = () => {
    if (!patientResult?.insuranceId || !patientResult?.dateOfBirth) return;
    addMsg("user", "Check eligibility now");
    addMsg("bot", "Opening the eligibility check page...");
    prefillAndNavigate(patientResult.insuranceId, patientResult.dateOfBirth, getAutoCheck(patientResult.dateOfBirth));
  };

  const handleEligibilityAndAppointmentFromPatient = async () => {
    if (!patientResult?.insuranceId || !patientResult?.dateOfBirth) return;
    addMsg("user", "Check eligibility & add to schedule (today)");
    addMsg("bot", "Creating appointment for today...", true);
    try {
      const res = await apiRequest("POST", "/api/ai/create-appointment-today", {
        patientId: patientResult.id,
      });
      const data = await res.json();
      if (!res.ok) {
        replaceLastMsg(data.message ?? "Could not create appointment.");
        return;
      }
      replaceLastMsg(`Appointment added at ${data.startTime} (${data.column ?? "Column A"}) — opening eligibility check page...`);
    } catch {
      replaceLastMsg("Could not create appointment — opening eligibility check page...");
    }
    prefillAndNavigate(patientResult.insuranceId, patientResult.dateOfBirth, getAutoCheck(patientResult.dateOfBirth));
  };

  const prefillAndNavigate = (memberId: string, dobISO: string, autoCheck: string) => {
    sessionStorage.setItem("chatbot_eligibility", JSON.stringify({ memberId, dob: dobISO, autoCheck }));
    window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
    markJobStarted();
    setTimeout(() => { setLocation("/insurance-status"); setOpen(false); resetStep(); }, 600);
  };

  const handleEligibilityIdRun = () => {
    if (!eligibilityIdData) return;
    addMsg("user", "Check eligibility now");
    addMsg("bot", "Opening the eligibility check page...");
    prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
  };

  const handleBatchEligibilityRun = () => {
    if (!batchEligibilityData || batchEligibilityData.length === 0) return;
    addMsg("user", `Check all ${batchEligibilityData.length} patients`);
    addMsg("bot", `Checking ${batchEligibilityData.length} patients one by one...`);
    const [first, ...rest] = batchEligibilityData;
    if (rest.length > 0) {
      sessionStorage.setItem("chatbot_eligibility_queue", JSON.stringify(rest));
    }
    prefillAndNavigate(first!.memberId, first!.dob, first!.autoCheck);
  };

  const handleBatchEligibilityAndAppointment = () => {
    if (!batchEligibilityData || batchEligibilityData.length === 0) return;
    addMsg("user", `Check all & appointment today (${batchEligibilityData.length} patients)`);
    addMsg("bot", `Checking ${batchEligibilityData.length} patients — appointments will be created after each check...`);
    sessionStorage.setItem("chatbot_batch_appt_after_eligibility", "true");
    const [first, ...rest] = batchEligibilityData;
    if (rest.length > 0) {
      sessionStorage.setItem("chatbot_eligibility_queue", JSON.stringify(rest));
    }
    prefillAndNavigate(first!.memberId, first!.dob, first!.autoCheck);
  };

  const handleEligibilityAndAppointment = async (targetDate?: string) => {
    if (!eligibilityIdData) return;
    const dateLabel = targetDate
      ? new Date(targetDate + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
      : "today";
    addMsg("user", `Check eligibility & add to schedule (${dateLabel})`);

    if (!eligibilityIdData.patient) {
      addMsg("bot", `Running eligibility check — will add patient and create appointment for ${dateLabel} after...`);
      sessionStorage.setItem("chatbot_appt_after_eligibility", JSON.stringify({ memberId: eligibilityIdData.memberId, date: targetDate ?? null }));
      prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
      return;
    }

    addMsg("bot", `Creating appointment for ${dateLabel}...`, true);
    try {
      const res = await apiRequest("POST", "/api/ai/create-appointment-today", {
        patientId: eligibilityIdData.patient.id,
        date: targetDate ?? undefined,
      });
      const data = await res.json();
      if (!res.ok) {
        replaceLastMsg(data.message ?? "Could not create appointment.");
        return;
      }
      replaceLastMsg(`Appointment added at ${data.startTime} (${data.column ?? "Column A"}) for ${data.dateLabel} — opening eligibility check page...`);
      prefillAndNavigate(eligibilityIdData.memberId, eligibilityIdData.dob, eligibilityIdData.autoCheck);
    } catch {
      replaceLastMsg("Could not create appointment. Please try again.");
    }
  };

  const handleCheckAndClaimRun = () => {
    if (!checkAndClaimData) return;
    addMsg("user", "Run check & claim");
    addMsg("bot", "Opening the eligibility check page...");
    // Store claim codes so the eligibility page can offer auto-claim after ACTIVE result
    sessionStorage.setItem(
      "chatbot_claim_codes",
      JSON.stringify({
        codes: checkAndClaimData.matchedCodes,
        siteKey: checkAndClaimData.siteKey,
        patientId: checkAndClaimData.patient?.id ?? null,
        memberId: checkAndClaimData.memberId,
        dob: checkAndClaimData.dob,
        serviceDate: checkAndClaimData.serviceDate ?? null,
        renderingProvider: checkAndClaimData.renderingProvider ?? null,
      })
    );
    prefillAndNavigate(checkAndClaimData.memberId, checkAndClaimData.dob, checkAndClaimData.autoCheck);
  };

  const handleFreeTextSubmit = async () => {
    const text = freeTextInput.trim();
    if (!text || step === "ai-loading") return;
    setFreeTextInput("");
    addMsg("user", text);
    addMsg("bot", "Thinking...", true);
    setStep("ai-loading");

    try {
      const history = messages
        .filter((m) => !m.isLoading)
        .slice(-15)
        .map((m) => ({ role: m.role === "user" ? "user" : "assistant", text: m.text }));
      const d = new Date();
      const clientDate = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
      const res = await apiRequest("POST", "/api/ai/internal-chat", { message: text, history, clientDate });
      const data = await res.json();

      const claimActions = new Set(["claim_only_ready", "check_and_claim_ready", "need_appointment_selection"]);
      const attachmentSuffix =
        pendingFiles.length > 0 && claimActions.has(data.action)
          ? ` (📎 ${pendingFiles.length} attachment${pendingFiles.length > 1 ? "s" : ""} will be included)`
          : "";
      replaceLastMsg((data.reply ?? "Sorry, I couldn't process that.") + attachmentSuffix);

      if (data.action === "navigate" && data.actionData?.url) {
        setTimeout(() => { setLocation(data.actionData.url); setOpen(false); resetStep(); }, 800);
        return;
      }

      if (
        (data.action === "check_eligibility_prefill" || data.action === "show_patient") &&
        data.actionData?.patient
      ) {
        setPatientResult(data.actionData.patient);
        setStep("patient-found");
        return;
      }

      if (data.action === "batch_eligibility_ready" && data.actionData?.queue) {
        setBatchEligibilityData(data.actionData.queue);
        setStep("batch-eligibility-ready");
        return;
      }

      if (data.action === "eligibility_id_ready" && data.actionData) {
        setEligibilityIdData({
          memberId: data.actionData.memberId,
          dob: data.actionData.dob,
          siteKey: data.actionData.siteKey,
          autoCheck: data.actionData.autoCheck,
          patient: data.actionData.patient ?? null,
          appointmentDate: data.actionData.appointmentDate ?? null,
        });
        setStep("eligibility-id-ready");
        return;
      }

      if (data.action === "check_and_claim_ready" && data.actionData) {
        setCheckAndClaimData({
          patient: data.actionData.patient ?? null,
          memberId: data.actionData.memberId,
          dob: data.actionData.dob,
          siteKey: data.actionData.siteKey,
          autoCheck: data.actionData.autoCheck,
          matchedCodes: data.actionData.matchedCodes ?? [],
          serviceDate: data.actionData.serviceDate ?? null,
          renderingProvider: data.actionData.renderingProvider ?? null,
        });
        setStep("check-and-claim-ready");
        return;
      }

      if (data.action === "need_insurance_clarification" && data.actionData) {
        setClarificationData({
          memberId: data.actionData.memberId,
          dob: data.actionData.dob,
          patient: data.actionData.patient ?? null,
          procedureNames: data.actionData.procedureNames ?? [],
          options: data.actionData.options ?? [],
        });
        setStep("need-insurance-clarification");
        return;
      }

      if (data.action === "appointment_created") {
        setStep("menu");
        return;
      }

      if (data.action === "need_appointment_selection" && data.actionData) {
        setApptSelectionData({
          patient: data.actionData.patient,
          siteKey: data.actionData.siteKey,
          matchedCodes: data.actionData.matchedCodes ?? [],
          options: data.actionData.options ?? [],
        });
        setStep("need-appointment-selection");
        return;
      }

      if (data.action === "need_cdt_clarification" && data.actionData) {
        const phrases: string[] = data.actionData.unknownPhrases ?? [];
        const inputs: Record<string, string> = {};
        for (const p of phrases) inputs[p] = "";
        setCdtClarificationData({ unknownPhrases: phrases, codeInputs: inputs, originalMessage: text });
        setStep("need-cdt-clarification");
        return;
      }

      if (data.action === "batch_check_and_claim_ready" && data.actionData) {
        setBatchCheckAndClaimData({
          queue: data.actionData.queue ?? [],
          matchedCodes: data.actionData.matchedCodes ?? [],
          renderingProvider: data.actionData.renderingProvider ?? null,
        });
        setStep("batch-check-and-claim-ready");
        return;
      }

      if (data.action === "batch_claim_ready" && data.actionData) {
        setBatchClaimData({
          queue: data.actionData.queue ?? [],
          matchedCodes: data.actionData.matchedCodes ?? [],
          renderingProvider: data.actionData.renderingProvider ?? null,
        });
        setStep("batch-claim-ready");
        return;
      }

      if (data.action === "claim_only_ready" && data.actionData) {
        const { patient, matchedCodes, siteKey, serviceDate, appointmentId, renderingProvider } = data.actionData;
        setClaimReadyData({
          patient: patient ?? null,
          matchedCodes: matchedCodes ?? [],
          siteKey,
          serviceDate,
          appointmentId: appointmentId ?? null,
          renderingProvider: renderingProvider ?? null,
        });
        setStep("claim-ready");
        return;
      }

      if (data.action === "preauth_ready" && data.actionData) {
        const { patient, matchedCodes, siteKey, serviceDate, renderingProvider } = data.actionData;
        setPreauthReadyData({
          patient: patient ?? null,
          matchedCodes: matchedCodes ?? [],
          siteKey,
          serviceDate,
          renderingProvider: renderingProvider ?? null,
        });
        setStep("preauth-ready");
        return;
      }

      setStep("menu");
    } catch {
      replaceLastMsg("Sorry, something went wrong. Please try again.");
      setStep("menu");
    }
  };

  const handleFreeTextKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleFreeTextSubmit();
    }
  };

  const showFreeTextInput =
    step === "menu" ||
    step === "ai-loading" ||
    step === "patient-found" ||
    step === "eligibility-id-ready" ||
    step === "batch-eligibility-ready" ||
    step === "check-and-claim-ready" ||
    step === "batch-claim-ready" ||
    step === "batch-check-and-claim-ready" ||
    step === "need-insurance-clarification" ||
    step === "need-appointment-selection";

  return (
    <>
      <Button
        variant="ghost"
        size="sm"
        className="relative h-8 w-8 rounded-full p-0"
        title="Open Assistant"
        onClick={() => { if (shouldAutoReset()) resetStep(); setOpen(true); }}
      >
        <Bot className="h-5 w-5 text-primary" />
      </Button>

      {open && (
        <>
          {/* Backdrop */}
          <div className="fixed inset-0 z-40" onClick={handleClose} aria-hidden />

          {/* Chat panel */}
          <div className="fixed top-16 right-0 z-50 w-80 h-[calc(100vh-4rem)] bg-white border-l shadow-2xl flex flex-col">
            {/* Header */}
            <div className="flex items-center justify-between px-4 py-3 bg-primary text-white shrink-0">
              <div className="flex items-center gap-2">
                <Bot className="h-4 w-4" />
                <span className="font-semibold text-sm">Assistant</span>
              </div>
              <div className="flex items-center gap-3">
                <button
                  type="button"
                  onClick={reset}
                  className="flex items-center gap-1 text-xs hover:opacity-70 transition-opacity rounded px-1.5 py-0.5 border border-white/30 hover:bg-white/10"
                  title="Clear chat history"
                >
                  <RotateCcw className="h-3 w-3" />
                  Clear
                </button>
                <button
                  onClick={handleClose}
                  className="hover:opacity-70 transition-opacity rounded"
                  aria-label="Close"
                >
                  <X className="h-4 w-4" />
                </button>
              </div>
            </div>

            {/* Messages */}
            <div className="flex-1 overflow-y-auto p-4 space-y-3">
              {messages.map((msg) => (
                <div
                  key={msg.id}
                  className={cn("flex", msg.role === "user" ? "justify-end" : "justify-start")}
                >
                  <div
                    className={cn(
                      "max-w-[85%] rounded-2xl px-3 py-2 text-sm whitespace-pre-line leading-relaxed",
                      msg.role === "user"
                        ? "bg-primary text-white rounded-tr-sm"
                        : "bg-gray-100 text-gray-800 rounded-tl-sm"
                    )}
                  >
                    {msg.isLoading ? (
                      <span className="flex items-center gap-1.5">
                        <Loader2 className="h-3 w-3 animate-spin" />
                        Thinking...
                      </span>
                    ) : (
                      msg.text
                    )}
                  </div>
                </div>
              ))}

              {/* Quick-action buttons (menu step) */}
              {step === "menu" && (
                <div className="grid grid-cols-2 gap-2 pt-1">
                  <button
                    onClick={() => handleOptionSelect("eligibility")}
                    className="flex items-center gap-2 p-3 rounded-xl border border-primary/30 hover:bg-primary/5 text-sm text-left transition-colors"
                  >
                    <Stethoscope className="h-4 w-4 text-primary shrink-0" />
                    <span>Check Eligibility</span>
                  </button>
                  <button
                    onClick={() => handleOptionSelect("schedule")}
                    className="flex items-center gap-2 p-3 rounded-xl border border-blue-300 hover:bg-blue-50 text-sm text-left transition-colors"
                  >
                    <Calendar className="h-4 w-4 text-blue-500 shrink-0" />
                    <span>Schedule</span>
                  </button>
                  <button
                    onClick={() => handleOptionSelect("claims")}
                    className="flex items-center gap-2 p-3 rounded-xl border border-orange-300 hover:bg-orange-50 text-sm text-left transition-colors col-span-2"
                  >
                    <FileText className="h-4 w-4 text-orange-500 shrink-0" />
                    <span>Claims</span>
                  </button>
                </div>
              )}

              {/* Eligibility manual input */}
              {step === "eligibility-input" && (
                <div className="space-y-2 bg-gray-50 rounded-xl p-3 border">
                  <Label className="text-xs text-gray-600">Paste Member ID and Date of Birth</Label>
                  <textarea
                    ref={pasteRef}
                    rows={3}
                    placeholder={"e.g. 123456789  01/15/1985\nor  01/15/1985  123456789"}
                    value={pasteInput}
                    onChange={(e) => { setPasteInput(e.target.value); setParseError(""); }}
                    className={cn(
                      "w-full rounded-md border bg-white px-3 py-2 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-ring",
                      parseError && "border-red-400"
                    )}
                  />
                  {parseError && <p className="text-xs text-red-500">{parseError}</p>}
                  <div className="flex gap-2">
                    <Button
                      size="sm"
                      className="flex-1 h-8 text-xs"
                      onClick={handleEligibilitySubmit}
                      disabled={!pasteInput.trim()}
                    >
                      Continue <ChevronRight className="h-3 w-3 ml-1" />
                    </Button>
                    <Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Eligibility confirm */}
              {step === "eligibility-confirm" && (
                <div className="flex gap-2">
                  <Button size="sm" className="flex-1 h-8 text-xs" onClick={handleConfirm}>
                    Yes, Check Now
                  </Button>
                  <Button
                    size="sm"
                    variant="outline"
                    className="h-8 text-xs"
                    onClick={() => {
                      setStep("eligibility-input");
                      setMessages((prev) => prev.slice(0, -2));
                    }}
                  >
                    Edit
                  </Button>
                </div>
              )}

              {/* AI-found patient card */}
              {step === "patient-found" && patientResult && (
                <div className="bg-blue-50 border border-blue-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-blue-800">
                    {patientResult.firstName} {patientResult.lastName}
                  </p>
                  {patientResult.insuranceProvider && (
                    <p className="text-xs text-blue-600">{patientResult.insuranceProvider}</p>
                  )}
                  {patientResult.insuranceId && (
                    <p className="text-xs text-gray-500">ID: {patientResult.insuranceId}</p>
                  )}
                  {patientResult.dateOfBirth && (
                    <p className="text-xs text-gray-500">DOB: {patientResult.dateOfBirth}</p>
                  )}
                  <div className="flex flex-col gap-2 pt-1">
                    {patientResult.insuranceId && patientResult.dateOfBirth && (
                      <>
                        <Button
                          size="sm"
                          className="w-full h-8 text-xs bg-primary hover:bg-primary/90"
                          onClick={handleEligibilityFromPatient}
                        >
                          <Stethoscope className="h-3 w-3 mr-1" />
                          Check Eligibility
                        </Button>
                        <Button
                          size="sm"
                          className="w-full h-8 text-xs bg-emerald-600 hover:bg-emerald-700 text-white"
                          onClick={handleEligibilityAndAppointmentFromPatient}
                        >
                          <Calendar className="h-3 w-3 mr-1" />
                          Eligibility &amp; Appointment Today
                        </Button>
                      </>
                    )}
                    <Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Eligibility by ID ready */}
              {step === "eligibility-id-ready" && eligibilityIdData && (
                <div className="bg-blue-50 border border-blue-200 rounded-xl p-3 space-y-2">
                  {eligibilityIdData.patient && (
                    <p className="text-xs font-semibold text-blue-800">
                      {eligibilityIdData.patient.firstName} {eligibilityIdData.patient.lastName}
                    </p>
                  )}
                  <p className="text-xs text-blue-600">ID: {eligibilityIdData.memberId}</p>
                  <p className="text-xs text-gray-500">DOB: {eligibilityIdData.dob}</p>
                  {eligibilityIdData.patient?.insuranceProvider && (
                    <p className="text-xs text-gray-500">{eligibilityIdData.patient.insuranceProvider}</p>
                  )}
                  <div className="flex flex-col gap-2 pt-1">
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-primary hover:bg-primary/90"
                      onClick={handleEligibilityIdRun}
                    >
                      <Stethoscope className="h-3 w-3 mr-1" />
                      Check Eligibility
                    </Button>
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-emerald-600 hover:bg-emerald-700 text-white"
                      onClick={() => handleEligibilityAndAppointment()}
                    >
                      <Calendar className="h-3 w-3 mr-1" />
                      Eligibility &amp; Appointment Today
                    </Button>
                    {eligibilityIdData.appointmentDate && (
                      <Button
                        size="sm"
                        className="w-full h-8 text-xs bg-teal-600 hover:bg-teal-700 text-white"
                        onClick={() => handleEligibilityAndAppointment(eligibilityIdData!.appointmentDate!)}
                      >
                        <Calendar className="h-3 w-3 mr-1" />
                        Eligibility &amp; Appointment on{" "}
                        {new Date(eligibilityIdData.appointmentDate + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
                      </Button>
                    )}
                    <Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Batch eligibility ready */}
              {step === "batch-eligibility-ready" && batchEligibilityData && (
                <div className="bg-indigo-50 border border-indigo-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-indigo-800">
                    {batchEligibilityData.length} patients to check:
                  </p>
                  {batchEligibilityData.map((item, i) => {
                    const name = item.patient
                      ? `${item.patient.firstName ?? ""} ${item.patient.lastName ?? ""}`.trim()
                      : `ID: ${item.memberId}`;
                    return (
                      <p key={i} className="text-xs text-indigo-600 pl-2">
                        {i + 1}. {name} — DOB: {item.dob}
                      </p>
                    );
                  })}
                  <div className="flex flex-col gap-2 pt-1">
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-indigo-600 hover:bg-indigo-700 text-white"
                      onClick={handleBatchEligibilityRun}
                    >
                      <Stethoscope className="h-3 w-3 mr-1" />
                      Check All ({batchEligibilityData.length} patients)
                    </Button>
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-green-600 hover:bg-green-700 text-white"
                      onClick={handleBatchEligibilityAndAppointment}
                    >
                      <Calendar className="h-3 w-3 mr-1" />
                      Check All & Appointment Today
                    </Button>
                    <Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Check & Claim ready */}
              {step === "check-and-claim-ready" && checkAndClaimData && (
                <div className="bg-teal-50 border border-teal-200 rounded-xl p-3 space-y-2">
                  {checkAndClaimData.patient && (
                    <p className="text-xs font-semibold text-teal-800">
                      {checkAndClaimData.patient.firstName} {checkAndClaimData.patient.lastName}
                    </p>
                  )}
                  <p className="text-xs text-teal-600">ID: {checkAndClaimData.memberId} · DOB: {checkAndClaimData.dob}</p>
                  {checkAndClaimData.matchedCodes.length > 0 && (
                    <div className="space-y-0.5">
                      <p className="text-xs font-medium text-teal-700">Claim after ACTIVE:</p>
                      {checkAndClaimData.matchedCodes.map((c) => (
                        <p key={c.code} className="text-xs text-gray-600 pl-2">
                          {c.code} — {c.description}
                        </p>
                      ))}
                    </div>
                  )}
                  <div className="flex gap-2 pt-1">
                    <Button
                      size="sm"
                      className="flex-1 h-8 text-xs bg-teal-600 hover:bg-teal-700 text-white"
                      onClick={handleCheckAndClaimRun}
                    >
                      <Stethoscope className="h-3 w-3 mr-1" />
                      Check &amp; Claim
                    </Button>
                    <Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Need insurance clarification */}
              {step === "need-insurance-clarification" && clarificationData && (
                <div className="bg-amber-50 border border-amber-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-amber-800">Which insurance?</p>
                  <p className="text-xs text-gray-500">ID: {clarificationData.memberId}</p>
                  <div className="flex flex-col gap-1.5 pt-1">
                    {clarificationData.options.map((opt) => (
                      <button
                        key={opt}
                        className="text-left text-xs px-3 py-1.5 rounded-lg border border-amber-300 hover:bg-amber-100 transition-colors"
                        onClick={() => {
                          addMsg("user", opt);
                          addMsg("bot", "Thinking...", true);
                          setStep("ai-loading");
                          apiRequest("POST", "/api/ai/internal-chat", {
                            message: `check ${opt} for ${clarificationData.memberId}, ${clarificationData.dob}${clarificationData.procedureNames.length > 0 ? " and claim " + clarificationData.procedureNames.join(", ") : ""}`,
                            clientDate: (() => { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`; })(),
                          })
                            .then((r) => r.json())
                            .then((data) => {
                              replaceLastMsg(data.reply ?? "Sorry, I couldn't process that.");
                              if (data.action === "check_and_claim_ready" && data.actionData) {
                                setCheckAndClaimData({
                                  patient: data.actionData.patient ?? null,
                                  memberId: data.actionData.memberId,
                                  dob: data.actionData.dob,
                                  siteKey: data.actionData.siteKey,
                                  autoCheck: data.actionData.autoCheck,
                                  matchedCodes: data.actionData.matchedCodes ?? [],
                                  serviceDate: data.actionData.serviceDate ?? null,
                                  renderingProvider: data.actionData.renderingProvider ?? null,
                                });
                                setStep("check-and-claim-ready");
                              } else if (data.action === "eligibility_id_ready" && data.actionData) {
                                setEligibilityIdData({
                                  memberId: data.actionData.memberId,
                                  dob: data.actionData.dob,
                                  siteKey: data.actionData.siteKey,
                                  autoCheck: data.actionData.autoCheck,
                                  patient: data.actionData.patient ?? null,
                                  appointmentDate: data.actionData.appointmentDate ?? null,
                                });
                                setStep("eligibility-id-ready");
                              } else {
                                setStep("menu");
                              }
                            })
                            .catch(() => {
                              replaceLastMsg("Sorry, something went wrong.");
                              setStep("menu");
                            });
                        }}
                      >
                        {opt}
                      </button>
                    ))}
                  </div>
                  <Button size="sm" variant="ghost" className="h-7 text-xs w-full" onClick={resetStep}>
                    Cancel
                  </Button>
                </div>
              )}

              {/* Appointment selection */}
              {step === "need-appointment-selection" && apptSelectionData && (
                <div className="bg-amber-50 border border-amber-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-amber-800">Which appointment date?</p>
                  <div className="flex flex-col gap-1.5 pt-1">
                    {apptSelectionData.options.map((opt) => (
                      <button
                        key={opt.serviceDate}
                        className="text-left text-xs px-3 py-2 rounded-lg border border-amber-300 hover:bg-amber-100 transition-colors font-medium"
                        onClick={() => {
                          addMsg("user", opt.label);
                          addMsg("bot", `Using ${opt.label} as the service date.`);
                          sessionStorage.setItem(
                            "chatbot_claim_prefill",
                            JSON.stringify({
                              codes: apptSelectionData.matchedCodes,
                              siteKey: apptSelectionData.siteKey,
                              serviceDate: opt.serviceDate,
                              autoSubmit: true,
                              dob: apptSelectionData.patient?.dateOfBirth ?? null,
                            })
                          );
                          setChatbotPendingFiles(pendingFiles);
                          markJobStarted();
                          setTimeout(() => {
                            setLocation(`/claims?appointmentId=${opt.appointmentId}`);
                            setOpen(false);
                            resetStep();
                          }, 600);
                        }}
                      >
                        {opt.label}
                      </button>
                    ))}
                  </div>
                  <Button size="sm" variant="ghost" className="h-7 text-xs w-full" onClick={resetStep}>
                    Cancel
                  </Button>
                </div>
              )}

              {/* Batch check & claim ready */}
              {step === "batch-check-and-claim-ready" && batchCheckAndClaimData && (
                <div className="bg-purple-50 border border-purple-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-purple-800">
                    Check &amp; Claim for {batchCheckAndClaimData.queue.length} patients:
                  </p>
                  {batchCheckAndClaimData.queue.map((item, i) => {
                    const name = item.patient
                      ? `${item.patient.firstName ?? ""} ${item.patient.lastName ?? ""}`.trim()
                      : `ID: ${item.memberId}`;
                    return (
                      <p key={i} className="text-xs text-purple-600 pl-2">
                        {i + 1}. {name} — DOB: {item.dob}
                      </p>
                    );
                  })}
                  {batchCheckAndClaimData.matchedCodes.length > 0 && (
                    <div className="space-y-0.5 pt-0.5">
                      <p className="text-xs font-medium text-purple-700">Claim after ACTIVE:</p>
                      {batchCheckAndClaimData.matchedCodes.map((c) => (
                        <p key={c.code} className="text-xs text-gray-700 pl-2">
                          <span className="font-medium">{c.code}</span> — {c.description}
                        </p>
                      ))}
                    </div>
                  )}
                  <div className="flex flex-col gap-2 pt-1">
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-purple-600 hover:bg-purple-700 text-white"
                      onClick={() => {
                        const { queue, matchedCodes, renderingProvider } = batchCheckAndClaimData;
                        addMsg("user", `Check & claim all ${queue.length} patients`);
                        addMsg("bot", `Checking eligibility and claiming for ${queue.length} patients one by one...`);
                        const [first, ...rest] = queue;
                        if (rest.length > 0) {
                          sessionStorage.setItem("chatbot_check_claim_queue", JSON.stringify({
                            remaining: rest,
                            matchedCodes,
                            renderingProvider,
                          }));
                        }
                        sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
                          codes: matchedCodes,
                          siteKey: first!.siteKey,
                          patientId: first!.patient?.id ?? null,
                          memberId: first!.memberId,
                          dob: first!.dob,
                          serviceDate: null,
                          renderingProvider,
                        }));
                        prefillAndNavigate(first!.memberId, first!.dob, first!.autoCheck);
                      }}
                    >
                      <Stethoscope className="h-3 w-3 mr-1" />
                      Check &amp; Claim All ({batchCheckAndClaimData.queue.length} patients)
                    </Button>
                    <Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Batch claim ready */}
              {step === "batch-claim-ready" && batchClaimData && (
                <div className="bg-orange-50 border border-orange-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-orange-800">
                    Claim for {batchClaimData.queue.length} patients:
                  </p>
                  {batchClaimData.queue.map((item, i) => (
                    <p key={i} className="text-xs text-orange-600 pl-2">
                      {i + 1}. {item.patient.firstName} {item.patient.lastName}
                    </p>
                  ))}
                  {batchClaimData.matchedCodes.length > 0 && (
                    <div className="space-y-0.5 pt-0.5">
                      <p className="text-xs font-medium text-orange-700">Procedures:</p>
                      {batchClaimData.matchedCodes.map((c) => (
                        <p key={c.code} className="text-xs text-gray-700 pl-2">
                          <span className="font-medium">{c.code}</span> — {c.description}
                        </p>
                      ))}
                    </div>
                  )}
                  <div className="flex flex-col gap-2 pt-1">
                    <Button
                      size="sm"
                      className="w-full h-8 text-xs bg-orange-600 hover:bg-orange-700 text-white"
                      onClick={() => {
                        const { queue, matchedCodes, renderingProvider } = batchClaimData;
                        addMsg("user", `Claim all ${queue.length} patients`);
                        addMsg("bot", `Claiming ${queue.length} patients one by one...`);
                        const [first, ...rest] = queue;
                        if (rest.length > 0) {
                          sessionStorage.setItem("chatbot_claim_queue", JSON.stringify({
                            remaining: rest,
                            matchedCodes,
                            renderingProvider,
                          }));
                        }
                        if (first!.patient.id && matchedCodes.length > 0) {
                          sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({
                            codes: matchedCodes,
                            siteKey: first!.siteKey,
                            serviceDate: first!.serviceDate,
                            autoSubmit: true,
                            renderingProvider: renderingProvider ?? null,
                            dob: first!.patient.dateOfBirth ?? null,
                          }));
                        }
                        setChatbotPendingFiles(pendingFiles);
                        markJobStarted();
                        const url = first!.appointmentId
                          ? `/claims?appointmentId=${first!.appointmentId}`
                          : `/claims?newPatient=${first!.patient.id}`;
                        setTimeout(() => { setLocation(url); setOpen(false); resetStep(); }, 600);
                      }}
                    >
                      <FileText className="h-3 w-3 mr-1" />
                      Claim All ({batchClaimData.queue.length} patients)
                    </Button>
                    <Button size="sm" variant="ghost" className="w-full h-8 text-xs" onClick={resetStep}>
                      Cancel
                    </Button>
                  </div>
                </div>
              )}

              {/* Claim ready — confirm before submitting */}
              {step === "claim-ready" && claimReadyData && (() => {
                const [sy, sm, sd] = (claimReadyData.serviceDate ?? "").split("-");
                const dateLabel = sy ? `${sm}/${sd}/${sy}` : claimReadyData.serviceDate;
                return (
                  <div className="bg-green-50 border border-green-200 rounded-xl p-3 space-y-2">
                    <p className="text-xs font-semibold text-green-800">Confirm Claim</p>
                    {claimReadyData.patient && (
                      <p className="text-xs text-green-700 font-medium">
                        {claimReadyData.patient.firstName} {claimReadyData.patient.lastName}
                      </p>
                    )}
                    <p className="text-xs text-gray-500">Service date: {dateLabel}</p>
                    {claimReadyData.matchedCodes.length > 0 && (
                      <div className="space-y-0.5 pt-0.5">
                        {claimReadyData.matchedCodes.map((c) => (
                          <p key={c.code} className="text-xs text-gray-700 pl-1">
                            <span className="font-medium">{c.code}</span> — {c.description}
                          </p>
                        ))}
                      </div>
                    )}
                    <div className="flex gap-2 pt-1">
                      <Button
                        size="sm"
                        className="flex-1 h-8 text-xs bg-green-600 hover:bg-green-700 text-white"
                        onClick={() => {
                          const { patient, matchedCodes, siteKey, serviceDate, appointmentId, renderingProvider } = claimReadyData;
                          addMsg("user", "Confirm & submit claim");
                          addMsg("bot", "Opening claim...");
                          if (patient?.id && matchedCodes.length > 0) {
                            sessionStorage.setItem(
                              "chatbot_claim_prefill",
                              JSON.stringify({ codes: matchedCodes, siteKey, serviceDate, autoSubmit: true, renderingProvider: renderingProvider ?? null, dob: patient?.dateOfBirth ?? null })
                            );
                          }
                          setChatbotPendingFiles(pendingFiles);
                          markJobStarted();
                          const url = appointmentId
                            ? `/claims?appointmentId=${appointmentId}`
                            : `/claims?newPatient=${patient?.id}`;
                          setTimeout(() => { setLocation(url); setOpen(false); resetStep(); }, 600);
                        }}
                      >
                        <FileText className="h-3 w-3 mr-1" />
                        Confirm &amp; Submit
                      </Button>
                      <Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>Cancel</Button>
                    </div>
                  </div>
                );
              })()}

              {/* PreAuth confirmation card */}
              {step === "preauth-ready" && preauthReadyData && (() => {
                const [sy, sm, sd] = (preauthReadyData.serviceDate ?? "").split("-");
                const dateLabel = sy ? `${sm}/${sd}/${sy}` : preauthReadyData.serviceDate;
                return (
                  <div className="bg-blue-50 border border-blue-200 rounded-xl p-3 space-y-2">
                    <p className="text-xs font-semibold text-blue-800">Confirm Pre-Authorization</p>
                    {preauthReadyData.patient && (
                      <p className="text-xs text-blue-700 font-medium">
                        {preauthReadyData.patient.firstName} {preauthReadyData.patient.lastName}
                      </p>
                    )}
                    <p className="text-xs text-gray-500">Tentative date: {dateLabel}</p>
                    {preauthReadyData.matchedCodes.length > 0 && (
                      <div className="space-y-0.5 pt-0.5">
                        {preauthReadyData.matchedCodes.map((c) => (
                          <p key={c.code} className="text-xs text-gray-700 pl-1">
                            <span className="font-medium">{c.code}</span>{c.toothNumber ? ` #${c.toothNumber}` : ""} — {c.description}
                          </p>
                        ))}
                      </div>
                    )}
                    <div className="flex gap-2 pt-1">
                      <Button
                        size="sm"
                        className="flex-1 h-8 text-xs bg-blue-600 hover:bg-blue-700 text-white"
                        onClick={() => {
                          const { patient, matchedCodes, siteKey, serviceDate, renderingProvider } = preauthReadyData;
                          addMsg("user", "Confirm & open pre-auth");
                          addMsg("bot", "Opening pre-auth form...");
                          if (patient?.id && matchedCodes.length > 0) {
                            sessionStorage.setItem(
                              "chatbot_preauth_prefill",
                              JSON.stringify({ codes: matchedCodes, siteKey, serviceDate, renderingProvider: renderingProvider ?? null })
                            );
                          }
                          setChatbotPendingFiles(pendingFiles);
                          const url = `/claims?newPatient=${patient?.id}&tab=preauth`;
                          setTimeout(() => { setLocation(url); setOpen(false); resetStep(); }, 600);
                        }}
                      >
                        <FileText className="h-3 w-3 mr-1" />
                        Confirm &amp; Open PreAuth
                      </Button>
                      <Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>Cancel</Button>
                    </div>
                  </div>
                );
              })()}

              {/* CDT clarification — unknown procedure terms */}
              {step === "need-cdt-clarification" && cdtClarificationData && (
                <div className="bg-amber-50 border border-amber-200 rounded-xl p-3 space-y-2">
                  <p className="text-xs font-semibold text-amber-800">Unknown procedure term{cdtClarificationData.unknownPhrases.length > 1 ? "s" : ""}</p>
                  <div className="space-y-2">
                    {cdtClarificationData.unknownPhrases.map((phrase) => (
                      <div key={phrase} className="flex items-center gap-2">
                        <span className="text-xs text-gray-700 font-medium shrink-0">"{phrase}"→</span>
                        <input
                          type="text"
                          placeholder="D0272"
                          value={cdtClarificationData.codeInputs[phrase] ?? ""}
                          onChange={(e) => setCdtClarificationData((prev) => prev ? {
                            ...prev,
                            codeInputs: { ...prev.codeInputs, [phrase]: e.target.value.toUpperCase() },
                          } : prev)}
                          className="flex-1 rounded border border-amber-300 bg-white px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-amber-400"
                        />
                      </div>
                    ))}
                  </div>
                  <div className="flex gap-2 pt-1">
                    <Button
                      size="sm"
                      className="flex-1 h-8 text-xs bg-amber-600 hover:bg-amber-700 text-white"
                      disabled={Object.values(cdtClarificationData.codeInputs).some((v) => !v.trim())}
                      onClick={async () => {
                        const entries = Object.entries(cdtClarificationData.codeInputs);
                        for (const [phrase, code] of entries) {
                          await apiRequest("POST", "/api/ai/cdt-aliases/add", { phrase, cdtCode: code.trim() });
                        }
                        const savedPairs = entries.map(([p, c]) => `"${p}" = ${c.trim()}`).join(", ");
                        addMsg("user", entries.map(([p, c]) => `${p} = ${c.trim()}`).join(", "));
                        addMsg("bot", `Got it! Saved ${savedPairs}. Retrying...`, true);
                        setStep("ai-loading");
                        setCdtClarificationData(null);
                        const origMsg = cdtClarificationData.originalMessage;
                        try {
                          const history = messages.filter((m) => !m.isLoading).slice(-15).map((m) => ({ role: m.role === "user" ? "user" : "assistant", text: m.text }));
                          const _d = new Date();
                          const _cd = `${_d.getFullYear()}-${String(_d.getMonth()+1).padStart(2,"0")}-${String(_d.getDate()).padStart(2,"0")}`;
                          const res = await apiRequest("POST", "/api/ai/internal-chat", { message: origMsg, history, clientDate: _cd });
                          const data = await res.json();
                          replaceLastMsg(data.reply ?? "Sorry, I couldn't process that.");
                          if (data.action === "claim_only_ready" && data.actionData) {
                            const { patient, matchedCodes, siteKey, serviceDate, appointmentId, renderingProvider } = data.actionData;
                            if (patient?.id && matchedCodes?.length > 0) {
                              sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({ codes: matchedCodes, siteKey, serviceDate, autoSubmit: true, renderingProvider: renderingProvider ?? null, dob: patient?.dateOfBirth ?? null }));
                            }
                            setChatbotPendingFiles(pendingFiles);
                            const url = appointmentId ? `/claims?appointmentId=${appointmentId}` : `/claims?newPatient=${patient?.id}`;
                            setTimeout(() => { setLocation(url); setOpen(false); resetStep(); }, 600);
                          } else {
                            setStep("menu");
                          }
                        } catch {
                          replaceLastMsg("Sorry, something went wrong. Please try again.");
                          setStep("menu");
                        }
                      }}
                    >
                      Save &amp; Retry
                    </Button>
                    <Button size="sm" variant="ghost" className="h-8 text-xs" onClick={resetStep}>Cancel</Button>
                  </div>
                </div>
              )}

              <div ref={messagesEndRef} />
            </div>

            {/* Persistent free-text input */}
            {showFreeTextInput && (
              <div className="shrink-0 border-t bg-white px-3 py-2">
                {/* Attached file chips */}
                {pendingFiles.length > 0 && (
                  <div className="flex flex-wrap gap-1 pb-1.5">
                    {pendingFiles.map((f, i) => (
                      <span
                        key={i}
                        className="flex items-center gap-1 text-[10px] bg-blue-50 border border-blue-200 rounded px-1.5 py-0.5 text-blue-700 max-w-[140px]"
                      >
                        <Paperclip className="h-2.5 w-2.5 shrink-0" />
                        <span className="truncate">{f.name}</span>
                        <button
                          type="button"
                          onClick={() => setPendingFiles((prev) => prev.filter((_, j) => j !== i))}
                          className="shrink-0 hover:text-red-500 ml-0.5"
                        >
                          <X className="h-2.5 w-2.5" />
                        </button>
                      </span>
                    ))}
                  </div>
                )}
                <div className="flex items-end gap-1.5">
                  <textarea
                    ref={freeTextRef}
                    rows={2}
                    placeholder='e.g. "check MARIA GONZALES" or "open claims"'
                    value={freeTextInput}
                    onChange={(e) => setFreeTextInput(e.target.value)}
                    onKeyDown={handleFreeTextKeyDown}
                    disabled={step === "ai-loading"}
                    className="flex-1 resize-none rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
                  />
                  <Button
                    size="sm"
                    variant="ghost"
                    className="h-9 w-9 p-0 shrink-0 text-gray-400 hover:text-gray-600"
                    title="Attach X-ray or document"
                    onClick={() => fileInputRef.current?.click()}
                    disabled={step === "ai-loading"}
                  >
                    <Paperclip className="h-4 w-4" />
                  </Button>
                  <Button
                    size="sm"
                    className="h-9 w-9 p-0 shrink-0"
                    onClick={handleFreeTextSubmit}
                    disabled={!freeTextInput.trim() || step === "ai-loading"}
                  >
                    {step === "ai-loading" ? (
                      <Loader2 className="h-4 w-4 animate-spin" />
                    ) : (
                      <Send className="h-4 w-4" />
                    )}
                  </Button>
                </div>
                <p className="text-[10px] text-gray-400 mt-1 pl-1">Enter to send · Shift+Enter for new line · 📎 attach files</p>
                <input
                  ref={fileInputRef}
                  type="file"
                  multiple
                  accept="image/*,application/pdf"
                  className="hidden"
                  onChange={(e) => {
                    const files = Array.from(e.target.files ?? []);
                    if (files.length > 0) {
                      setPendingFiles((prev) => [...prev, ...files].slice(0, 5));
                    }
                    e.target.value = "";
                  }}
                />
              </div>
            )}
          </div>
        </>
      )}
    </>
  );
}
