import { useState, useEffect, useMemo, useRef } from "react";
import { useMutation } from "@tanstack/react-query";
import {
  Card,
  CardHeader,
  CardTitle,
  CardContent,
  CardDescription,
} from "@/components/ui/card";
import { ClaimForm } from "@/components/claims/claim-form";
import { useToast } from "@/hooks/use-toast";
import { useAuth } from "@/hooks/use-auth";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { useLocation, useSearch } from "wouter";
import { useAppDispatch, useAppSelector } from "@/redux/hooks";
import {
  setTaskStatus,
  clearTaskStatus,
} from "@/redux/slices/seleniumTaskSlice";
import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner";
import { useJobStatus } from "@/hooks/use-job-status";
import ClaimsRecentTable, {
  QK_CLAIMS_BASE,
} from "@/components/claims/claims-recent-table";
import { QK_APPOINTMENTS_BASE } from "@/pages/appointments-page";
import ClaimsOfPatientModal from "@/components/claims/claims-of-patient-table";
import {
  Claim,
  UpdatePatient,
} from "@repo/db/types";
import ClaimDocumentsUploadMultiple from "@/components/claims/claim-document-upload-modal";
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
import { PdfPreviewModal } from "@/components/insurance-status/pdf-preview-modal";
import { socket } from "@/lib/socket";
import { useLicense } from "@/hooks/use-license";

export default function ClaimsPage() {
  const [isClaimFormOpen, setIsClaimFormOpen] = useState(false);
  const [selectedPatientId, setSelectedPatientId] = useState<number | null>(null);
  const [chatbotAutoSubmitSiteKey, setChatbotAutoSubmitSiteKey] = useState<string | undefined>(undefined);
  const [chatbotInitialTab, setChatbotInitialTab] = useState<string | undefined>(undefined);
  const [chatbotAutoSubmitPreauthSiteKey, setChatbotAutoSubmitPreauthSiteKey] = useState<string | undefined>(undefined);
  // for redirect from appointment page directly, then passing to claimform
  const [selectedAppointmentId, setSelectedAppointmentId] = useState<
    number | null
  >(null);
  // PDF preview modal state
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewPdfId, setPreviewPdfId] = useState<number | null>(null);
  const [previewFallbackFilename, setPreviewFallbackFilename] = useState<string | null>(null);
  const dispatch = useAppDispatch();
  const { status, message, show } = useAppSelector(
    (state) => state.seleniumTasks.claimSubmit
  );
  const { isLicensed } = useLicense();

  // Track pending selenium jobs so we can react to completion via socket
  const [pendingClaimJobId, setPendingClaimJobId] = useState<string | null>(null);
  // DDMA claim OTP modal
  const [ddmaClaimOtpOpen, setDdmaClaimOtpOpen] = useState(false);
  const [ddmaClaimOtpSubmitting, setDdmaClaimOtpSubmitting] = useState(false);
  const ddmaClaimSessionIdRef = useRef<string | null>(null);
  const [unitedDHClaimOtpOpen, setUnitedDHClaimOtpOpen] = useState(false);
  const [unitedDHClaimOtpSubmitting, setUnitedDHClaimOtpSubmitting] = useState(false);
  const unitedDHClaimSessionIdRef = useRef<string | null>(null);
  const [unitedDHPreAuthOtpOpen, setUnitedDHPreAuthOtpOpen] = useState(false);
  const [unitedDHPreAuthOtpSubmitting, setUnitedDHPreAuthOtpSubmitting] = useState(false);
  const unitedDHPreAuthSessionIdRef = useRef<string | null>(null);
  const [tuftsSCOClaimOtpOpen, setTuftsSCOClaimOtpOpen] = useState(false);
  const [tuftsSCOClaimOtpSubmitting, setTuftsSCOClaimOtpSubmitting] = useState(false);
  const tuftsSCOClaimSessionIdRef = useRef<string | null>(null);
  const [tuftsSCOPreAuthOtpOpen, setTuftsSCOPreAuthOtpOpen] = useState(false);
  const [tuftsSCOPreAuthOtpSubmitting, setTuftsSCOPreAuthOtpSubmitting] = useState(false);
  const tuftsSCOPreAuthSessionIdRef = useRef<string | null>(null);
  const pendingClaimMeta = useRef<{
    patientId: number | null;
    groupKey: "INSURANCE_CLAIM" | "INSURANCE_CLAIM_PREAUTH";
  }>({ patientId: null, groupKey: "INSURANCE_CLAIM" });
  const { status: jobStatus, result: jobResult, socketId } = useJobStatus(pendingClaimJobId);
  const { toast } = useToast();
  const { user } = useAuth();

  // Update patient mutation
  const updatePatientMutation = useMutation({
    mutationFn: async ({
      id,
      patient,
    }: {
      id: number;
      patient: UpdatePatient;
    }) => {
      const res = await apiRequest("PUT", `/api/patients/${id}`, patient);
      return res.json();
    },
    onSuccess: () => {
      toast({
        title: "Success",
        description: "Patient updated successfully!",
        variant: "default",
      });
      queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
      queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
    },
    onError: (error) => {
      toast({
        title: "Error",
        description: `Failed to update patient: ${error.message}`,
        variant: "destructive",
      });
    },
  });

  // create claim mutation
  const createClaimMutation = useMutation({
    mutationFn: async (claimData: any) => {
      const res = await apiRequest("POST", "/api/claims/", claimData);
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });

      toast({
        title: "Claim created successfully",
        variant: "default",
      });
    },
    onError: (error: any) => {
      toast({
        title: "Error submitting claim",
        description: error.message,
        variant: "destructive",
      });
    },
  });

  // React to selenium job completing via socket
  useEffect(() => {
    if (!pendingClaimJobId) return;
    if (jobStatus === "completed" && jobResult) {
      setPendingClaimJobId(null);
      queryClient.invalidateQueries({ queryKey: ["claims-recent"] });

      // CCA result: pdfFileId is already saved by the processor — open preview directly
      if (jobResult.pdfFileId) {
        advanceAiClaimQueue();
        const advancedToNext = advanceChatbotClaimQueue();
        if (!advancedToNext) {
          setPreviewPdfId(jobResult.pdfFileId);
          setPreviewFallbackFilename(jobResult.pdfFilename ?? `cca_claim_${jobResult.claimNumber ?? "unknown"}.pdf`);
          setPreviewOpen(true);
        }
        dispatch(setTaskStatus({
          key: "claimSubmit",
          status: "success",
          message: jobResult.claimNumber
            ? `CCA claim submitted — Encounter ID: ${jobResult.claimNumber}`
            : "CCA claim submitted successfully",
        }));
      } else {
        // MH claim: needs PDF download step
        handleMHSeleniumPdfDownload(
          jobResult,
          pendingClaimMeta.current.patientId,
          pendingClaimMeta.current.groupKey
        );
      }
    } else if (jobStatus === "failed") {
      setPendingClaimJobId(null);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: "Selenium job failed" }));
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [jobStatus, jobResult, pendingClaimJobId]);

  // small helper: remove given query params from the current URL (silent, no reload)
  const clearUrlParams = (params: string[]) => {
    try {
      const url = new URL(window.location.href);
      let changed = false;
      for (const p of params) {
        if (url.searchParams.has(p)) {
          url.searchParams.delete(p);
          changed = true;
        }
      }
      if (changed) {
        // Use wouter's setLocation so its internal search state updates too
        const newRelative = url.pathname + (url.search ? url.search : "") + url.hash;
        setWouterLocation(newRelative, { replace: true });
      }
    } catch (e) {
      // ignore
    }
  };

  // case1: - this params are set by pdf extraction/patient page or either by patient-add-form. then used in claim page here.
  const [location, setWouterLocation] = useLocation();
  const search = useSearch();

  const { newPatient, mode } = useMemo(() => {
    const params = new URLSearchParams(window.location.search);
    return {
      newPatient: params.get("newPatient"),
      mode: params.get("mode"), // direct | manual | null};
    };
  }, [location, search]);

  const handleNewClaim = (patientId: number, appointmentId?: number) => {
    setSelectedPatientId(patientId);

    // case: when redirect happerns from appointment page.
    if (appointmentId) {
      setSelectedAppointmentId(appointmentId);
    }
    setIsClaimFormOpen(true);
  };

  // if ?newPatient=<id> is present, open claim form directly
  useEffect(() => {
    if (!newPatient) return;

    const id = Number(newPatient);
    if (!Number.isFinite(id) || id <= 0) return;

    // Check if chatbot requested auto-submit with a specific insurance
    try {
      const raw = sessionStorage.getItem("chatbot_claim_prefill");
      if (raw) {
        const parsed = JSON.parse(raw);
        if (parsed?.autoSubmit && parsed?.siteKey) {
          setChatbotAutoSubmitSiteKey(parsed.siteKey);
        }
      }
    } catch {}

    // Check if chatbot requested preauth tab
    try {
      const preauthRaw = sessionStorage.getItem("chatbot_preauth_prefill");
      if (preauthRaw) {
        setChatbotInitialTab("preauth");
        const parsed = JSON.parse(preauthRaw);
        if (parsed?.siteKey) setChatbotAutoSubmitPreauthSiteKey(parsed.siteKey);
      }
    } catch {}

    handleNewClaim(id);
    clearUrlParams(["newPatient"]);
  }, [newPatient]);

  // case2 - redirect from appointment page:
  // If ?appointmentId= is present (and no ?newPatient param), fetch appointment->patient and open claim form
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const appointmentIdParam = params.get("appointmentId");

    // If newPatient flow is present, prefer it and do nothing here
    if (newPatient) return;
    if (!appointmentIdParam) return;

    const appointmentId = Number(appointmentIdParam);
    if (!Number.isFinite(appointmentId) || appointmentId <= 0) return;

    let cancelled = false;

    (async () => {
      try {
        const res = await apiRequest(
          "GET",
          `/api/appointments/${appointmentId}`
        );
        if (!res.ok) {
          let body: any = null;
          try {
            body = await res.json();
          } catch {}
          if (!cancelled) {
            toast({
              title: "Failed to load appointment",
              description:
                body?.message ??
                body?.error ??
                `Could not fetch appointment ${appointmentId}.`,
              variant: "destructive",
            });
          }
          return;
        }

        const appointment = await res.json();
        const patientId = appointment?.patientId;

        if (!cancelled && patientId) {
          // Check if chatbot requested auto-submit with a specific insurance
          try {
            const raw = sessionStorage.getItem("chatbot_claim_prefill");
            if (raw) {
              const parsed = JSON.parse(raw);
              if (parsed?.autoSubmit && parsed?.siteKey) {
                setChatbotAutoSubmitSiteKey(parsed.siteKey);
              }
            }
          } catch {}
          handleNewClaim(patientId, appointmentId);
          clearUrlParams(["appointmentId"]);
        }
      } catch (err: any) {
        if (!cancelled) {
          console.error("Error fetching patient for appointment:", err);
          toast({
            title: "Error",
            description: err?.message ?? "Failed to fetch patient.",
            variant: "destructive",
          });
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [location, search, newPatient]);

  // 2. Update Patient ( for insuranceId and Insurance Provider)
  const handleUpdatePatient = (patient: UpdatePatient & { id?: number }) => {
    if (patient) {
      const { id, ...sanitizedPatient } = patient;
      updatePatientMutation.mutate({
        id: Number(patient.id),
        patient: sanitizedPatient,
      });
    } else {
      toast({
        title: "Error",
        description: "Cannot update patient: No patient or user found",
        variant: "destructive",
      });
    }
  };

  // Advance the chatbot_claim_queue / chatbot_check_claim_queue after selenium PDF is saved.
  // NOT called from closeClaim — called only after the selenium job completes and PDF is downloaded.
  // Returns true if it navigated on to another queued patient (caller should skip the PDF
  // preview popup in that case — the form is about to be replaced by the next patient's claim).
  const advanceChatbotClaimQueue = (): boolean => {
    try {
      const raw = sessionStorage.getItem("chatbot_check_claim_queue");
      if (raw) {
        const parsed = JSON.parse(raw);
        const remaining = parsed?.remaining as any[] | undefined;
        const matchedCodes = parsed?.matchedCodes ?? [];
        const renderingProvider = parsed?.renderingProvider ?? null;
        if (remaining && remaining.length > 0) {
          const [next, ...rest] = remaining;
          if (rest.length > 0) {
            sessionStorage.setItem("chatbot_check_claim_queue", JSON.stringify({ remaining: rest, matchedCodes, renderingProvider }));
          } else {
            sessionStorage.removeItem("chatbot_check_claim_queue");
          }
          sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
            codes: matchedCodes,
            siteKey: next.siteKey,
            patientId: next.patient?.id ?? null,
            memberId: next.memberId,
            dob: next.dob,
            serviceDate: null,
            renderingProvider,
          }));
          sessionStorage.setItem("chatbot_eligibility", JSON.stringify({
            memberId: next.memberId,
            dob: next.dob,
            autoCheck: next.autoCheck,
          }));
          setTimeout(() => {
            window.dispatchEvent(new CustomEvent("chatbot:eligibility-prefill"));
            setWouterLocation("/insurance-status");
          }, 500);
          return true;
        }
        sessionStorage.removeItem("chatbot_check_claim_queue");
      }
    } catch {}

    try {
      const raw = sessionStorage.getItem("chatbot_claim_queue");
      if (raw) {
        const parsed = JSON.parse(raw);
        const remaining = parsed?.remaining as any[] | undefined;
        const sharedMatchedCodes = parsed?.matchedCodes ?? [];
        const renderingProvider = parsed?.renderingProvider ?? null;
        if (remaining && remaining.length > 0) {
          const [next, ...rest] = remaining;
          if (rest.length > 0) {
            sessionStorage.setItem("chatbot_claim_queue", JSON.stringify({ remaining: rest, matchedCodes: sharedMatchedCodes, renderingProvider }));
          } else {
            sessionStorage.removeItem("chatbot_claim_queue");
          }
          const codes = next.matchedCodes?.length > 0 ? next.matchedCodes : sharedMatchedCodes;
          if (next.patient?.id && codes.length > 0) {
            sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({
              codes,
              siteKey: next.siteKey,
              serviceDate: next.serviceDate,
              autoSubmit: true,
              renderingProvider,
              dob: next.patient.dateOfBirth ?? null,
            }));
          }
          setTimeout(() => {
            setWouterLocation(`/claims?newPatient=${next.patient.id}`);
          }, 500);
          return true;
        }
        sessionStorage.removeItem("chatbot_claim_queue");
      }
    } catch {}

    return false;
  };

  // Advance the ai_claim_queue by removing the first item (current patient).
  // Called only on successful submission so that cancel leaves the queue intact.
  const advanceAiClaimQueue = () => {
    try {
      const raw = sessionStorage.getItem("ai_claim_queue");
      if (!raw) return;
      const parsed = JSON.parse(raw);
      if (!parsed?.pendingResume || !Array.isArray(parsed.appointments)) return;
      const [, ...rest] = parsed.appointments;
      if (rest.length > 0) {
        sessionStorage.setItem("ai_claim_queue", JSON.stringify({ ...parsed, appointments: rest }));
      } else {
        sessionStorage.removeItem("ai_claim_queue");
      }
    } catch {}
  };

  // 3. create or update claim (update when claimId is present)
  const handleClaimSubmit = async (claimData: any): Promise<Claim> => {
    const { isDraft, claimId, uploadedFiles: _uf, ...cleanData } = claimData;

    if (claimId) {
      // Update existing saved claim (PUT never creates a Payment)
      const res = await apiRequest("PUT", `/api/claims/${claimId}`, cleanData);
      const data = await res.json();
      if (!res.ok) throw new Error(data?.message || "Failed to update claim");
      queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
      if (!isDraft) toast({ title: "Claim updated successfully", variant: "default" });
      return data;
    }

    // New claim: draft saves skip Payment creation
    const url = isDraft ? "/api/claims/?draft=true" : "/api/claims/";
    const res = await apiRequest("POST", url, cleanData);
    const data = await res.json();
    if (!res.ok) throw new Error(data?.message || "Failed to save claim");
    queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
    // NOTE: advanceChatbotClaimQueue() is NOT called here. This function only creates
    // the claim DB record; for selenium-based insurances (MH/CCA/DDMA/Tufts/United) the
    // actual submission + PDF happens afterward. Advancing the queue here would move to
    // the next patient before the current patient's selenium job (and PDF) finishes.
    // The queue is advanced later, once the selenium job completes (see
    // handleMHSeleniumPdfDownload and the CCA branch in the job-status useEffect).
    if (!isDraft) advanceAiClaimQueue();
    return data;
  };

  // 4. handle selenium sybmiting Mass Health claim
  const handleMHClaimSubmitSelenium = async (data: any) => {
    const formData = new FormData();
    formData.append("data", JSON.stringify(data));
    if (socketId) formData.append("socketId", socketId);
    const uploadedFiles: File[] = data.uploadedFiles ?? [];

    uploadedFiles.forEach((file: File) => {
      if (file.type === "application/pdf") {
        formData.append("pdfs", file);
      } else if (file.type.startsWith("image/")) {
        formData.append("images", file);
      }
    });

    try {
      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "pending",
          message: "Submitting claim to Selenium...",
        })
      );
      const response = await apiRequest(
        "POST",
        "/api/claims/selenium-claim",
        formData
      );
      const result1 = await response.json();
      if (result1.error) throw new Error(result1.error);

      // Job is queued — wait for socket completion before downloading PDF
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM" };
      setPendingClaimJobId(result1.jobId);

      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "pending",
          message: "Submitted to Selenium. Awaiting result...",
        })
      );

      toast({
        title: "Selenium service notified",
        description: "Claim submitted to Selenium. Waiting for confirmation...",
        variant: "default",
      });
    } catch (error: any) {
      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "error",
          message: error.message || "Selenium submission failed",
        })
      );
      toast({
        title: "Selenium service error",
        description: error.message || "An error occurred.",
        variant: "destructive",
      });
    }
  };

  // CCA claim selenium handler
  const handleCCAClaimSubmitSelenium = async (data: any) => {
    const formData = new FormData();
    formData.append("data", JSON.stringify(data));
    if (socketId) formData.append("socketId", socketId);
    const uploadedFiles: File[] = data.uploadedFiles ?? [];
    uploadedFiles.forEach((file: File) => {
      if (file.type === "application/pdf") {
        formData.append("pdfs", file);
      } else if (file.type.startsWith("image/")) {
        formData.append("images", file);
      }
    });
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting CCA claim..." }));
      const response = await apiRequest("POST", "/api/claims/cca-claim", formData);
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      // Track job so the completion useEffect fires when Selenium finishes
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM" };
      setPendingClaimJobId(result.jobId);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "CCA claim queued. Awaiting Selenium..." }));
      toast({ title: "CCA Claim queued", description: "Selenium is processing the claim.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "CCA claim failed" }));
      toast({ title: "CCA Claim error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  // DDMA claim OTP submit handler
  const handleDdmaClaimOtpSubmit = async (otp: string) => {
    const sessionId = ddmaClaimSessionIdRef.current;
    if (!sessionId) return;
    try {
      setDdmaClaimOtpSubmitting(true);
      const resp = await apiRequest("POST", "/api/claims/ddma-claim/selenium/submit-otp", {
        session_id: sessionId,
        otp,
        socketId,
      });
      const data = await resp.json();
      if (!resp.ok || data.error) throw new Error(data.error || "Failed to submit OTP");
      setDdmaClaimOtpOpen(false);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP submitted. Continuing DDMA claim..." }));
    } catch (err: any) {
      toast({ title: "Failed to submit OTP", description: err?.message || "Error submitting OTP", variant: "destructive" });
    } finally {
      setDdmaClaimOtpSubmitting(false);
    }
  };

  // DDMA claim selenium handler
  const handleDDMAClaimSubmitSelenium = async (data: any) => {
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting Delta MA claim..." }));
      const response = await apiRequest("POST", "/api/claims/ddma-claim", {
        data,
        socketId,
      });
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM" };
      setPendingClaimJobId(result.jobId);

      // Listen for session_id so we can forward OTP if needed
      const jobId = result.jobId;
      const onSessionStarted = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        ddmaClaimSessionIdRef.current = ev.session_id ?? null;
      };
      const onOtpRequired = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        if (ev.session_id) ddmaClaimSessionIdRef.current = ev.session_id;
        setDdmaClaimOtpOpen(true);
        dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP required for Delta MA. Please enter the code." }));
      };
      const onDone = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        socket.off("selenium:ddma_claim_started", onSessionStarted);
        socket.off("selenium:otp_required", onOtpRequired);
        socket.off("job:update", onDone);
        setDdmaClaimOtpOpen(false);
        ddmaClaimSessionIdRef.current = null;
      };
      socket.on("selenium:ddma_claim_started", onSessionStarted);
      socket.on("selenium:otp_required", onOtpRequired);
      socket.on("job:update", onDone);

      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Delta MA claim queued. Awaiting Selenium..." }));
      toast({ title: "Delta MA Claim queued", description: "Selenium is opening the claim form.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "Delta MA claim failed" }));
      toast({ title: "Delta MA Claim error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  const handleUnitedDHClaimOtpSubmit = async (otp: string) => {
    const sessionId = unitedDHClaimSessionIdRef.current;
    if (!sessionId) return;
    try {
      setUnitedDHClaimOtpSubmitting(true);
      const resp = await apiRequest("POST", "/api/claims/uniteddh-claim/selenium/submit-otp", {
        session_id: sessionId,
        otp,
        socketId,
      });
      const data = await resp.json();
      if (!resp.ok || data.error) throw new Error(data.error || "Failed to submit OTP");
      setUnitedDHClaimOtpOpen(false);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP submitted. Continuing United/DentalHub claim..." }));
    } catch (err: any) {
      toast({ title: "Failed to submit OTP", description: err?.message || "Error submitting OTP", variant: "destructive" });
    } finally {
      setUnitedDHClaimOtpSubmitting(false);
    }
  };

  const handleUnitedDHPreAuthOtpSubmit = async (otp: string) => {
    const sessionId = unitedDHPreAuthSessionIdRef.current;
    if (!sessionId) return;
    try {
      setUnitedDHPreAuthOtpSubmitting(true);
      const resp = await apiRequest("POST", "/api/claims/uniteddh-preauth/selenium/submit-otp", {
        session_id: sessionId,
        otp,
        socketId,
      });
      const data = await resp.json();
      if (!resp.ok || data.error) throw new Error(data.error || "Failed to submit OTP");
      setUnitedDHPreAuthOtpOpen(false);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP submitted. Continuing United/DentalHub pre-authorization..." }));
    } catch (err: any) {
      toast({ title: "Failed to submit OTP", description: err?.message || "Error submitting OTP", variant: "destructive" });
    } finally {
      setUnitedDHPreAuthOtpSubmitting(false);
    }
  };

  // United/DentalHub pre-auth selenium handler
  const handleUnitedDHPreAuthSubmitSelenium = async (data: any) => {
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting United/DentalHub pre-authorization..." }));
      const response = await apiRequest("POST", "/api/claims/uniteddh-preauth", {
        data,
        socketId,
      });
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM_PREAUTH" };
      setPendingClaimJobId(result.jobId);

      const jobId = result.jobId;
      const onSessionStarted = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        unitedDHPreAuthSessionIdRef.current = ev.session_id ?? null;
      };
      const onOtpRequired = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        if (ev.session_id) unitedDHPreAuthSessionIdRef.current = ev.session_id;
        setUnitedDHPreAuthOtpOpen(true);
        dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP required for United/DentalHub. Please enter the code." }));
      };
      const onDone = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        socket.off("selenium:uniteddh_preauth_started", onSessionStarted);
        socket.off("selenium:otp_required", onOtpRequired);
        socket.off("job:update", onDone);
        setUnitedDHPreAuthOtpOpen(false);
        unitedDHPreAuthSessionIdRef.current = null;
      };
      socket.on("selenium:uniteddh_preauth_started", onSessionStarted);
      socket.on("selenium:otp_required", onOtpRequired);
      socket.on("job:update", onDone);

      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "United/DentalHub pre-auth queued. Awaiting Selenium..." }));
      toast({ title: "United/DentalHub PreAuth queued", description: "Selenium is opening the pre-authorization form.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "United/DentalHub pre-auth failed" }));
      toast({ title: "United/DentalHub PreAuth error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  const handleTuftsSCOPreAuthOtpSubmit = async (otp: string) => {
    const sessionId = tuftsSCOPreAuthSessionIdRef.current;
    if (!sessionId) return;
    try {
      setTuftsSCOPreAuthOtpSubmitting(true);
      const resp = await apiRequest("POST", "/api/claims/tuftssco-preauth/selenium/submit-otp", {
        session_id: sessionId,
        otp,
        socketId,
      });
      const data = await resp.json();
      if (!resp.ok || data.error) throw new Error(data.error || "Failed to submit OTP");
      setTuftsSCOPreAuthOtpOpen(false);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP submitted. Continuing Tufts SCO pre-authorization..." }));
    } catch (err: any) {
      toast({ title: "Failed to submit OTP", description: err?.message || "Error submitting OTP", variant: "destructive" });
    } finally {
      setTuftsSCOPreAuthOtpSubmitting(false);
    }
  };

  // Tufts SCO pre-auth selenium handler
  const handleTuftsSCOPreAuthSubmitSelenium = async (data: any) => {
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting Tufts SCO pre-authorization..." }));
      const response = await apiRequest("POST", "/api/claims/tuftssco-preauth", {
        data,
        socketId,
      });
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM_PREAUTH" };
      setPendingClaimJobId(result.jobId);

      const jobId = result.jobId;
      const onSessionStarted = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        tuftsSCOPreAuthSessionIdRef.current = ev.session_id ?? null;
      };
      const onOtpRequired = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        if (ev.session_id) tuftsSCOPreAuthSessionIdRef.current = ev.session_id;
        setTuftsSCOPreAuthOtpOpen(true);
        dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP required for Tufts SCO. Please enter the code." }));
      };
      const onDone = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        socket.off("selenium:tuftssco_preauth_started", onSessionStarted);
        socket.off("selenium:otp_required", onOtpRequired);
        socket.off("job:update", onDone);
        setTuftsSCOPreAuthOtpOpen(false);
        tuftsSCOPreAuthSessionIdRef.current = null;
      };
      socket.on("selenium:tuftssco_preauth_started", onSessionStarted);
      socket.on("selenium:otp_required", onOtpRequired);
      socket.on("job:update", onDone);

      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Tufts SCO pre-auth queued. Awaiting Selenium..." }));
      toast({ title: "Tufts SCO PreAuth queued", description: "Selenium is opening the pre-authorization form.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "Tufts SCO pre-auth failed" }));
      toast({ title: "Tufts SCO PreAuth error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  // United/DentalHub claim selenium handler
  const handleUnitedDHClaimSubmitSelenium = async (data: any) => {
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting United/DentalHub claim..." }));
      const response = await apiRequest("POST", "/api/claims/uniteddh-claim", {
        data,
        socketId,
      });
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM" };
      setPendingClaimJobId(result.jobId);

      const jobId = result.jobId;
      const onSessionStarted = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        unitedDHClaimSessionIdRef.current = ev.session_id ?? null;
      };
      const onOtpRequired = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        if (ev.session_id) unitedDHClaimSessionIdRef.current = ev.session_id;
        setUnitedDHClaimOtpOpen(true);
        dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP required for United/DentalHub. Please enter the code." }));
      };
      const onDone = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        socket.off("selenium:uniteddh_claim_started", onSessionStarted);
        socket.off("selenium:otp_required", onOtpRequired);
        socket.off("job:update", onDone);
        setUnitedDHClaimOtpOpen(false);
        unitedDHClaimSessionIdRef.current = null;
      };
      socket.on("selenium:uniteddh_claim_started", onSessionStarted);
      socket.on("selenium:otp_required", onOtpRequired);
      socket.on("job:update", onDone);

      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "United/DentalHub claim queued. Awaiting Selenium..." }));
      toast({ title: "United/DentalHub Claim queued", description: "Selenium is opening the claim form.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "United/DentalHub claim failed" }));
      toast({ title: "United/DentalHub Claim error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  const handleTuftsSCOClaimOtpSubmit = async (otp: string) => {
    const sessionId = tuftsSCOClaimSessionIdRef.current;
    if (!sessionId) return;
    try {
      setTuftsSCOClaimOtpSubmitting(true);
      const resp = await apiRequest("POST", "/api/claims/tuftssco-claim/selenium/submit-otp", {
        session_id: sessionId,
        otp,
        socketId,
      });
      const data = await resp.json();
      if (!resp.ok || data.error) throw new Error(data.error || "Failed to submit OTP");
      setTuftsSCOClaimOtpOpen(false);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP submitted. Continuing Tufts SCO claim..." }));
    } catch (err: any) {
      toast({ title: "Failed to submit OTP", description: err?.message || "Error submitting OTP", variant: "destructive" });
    } finally {
      setTuftsSCOClaimOtpSubmitting(false);
    }
  };

  // Tufts SCO claim selenium handler
  const handleTuftsSCOClaimSubmitSelenium = async (data: any) => {
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting Tufts SCO claim..." }));
      const response = await apiRequest("POST", "/api/claims/tuftssco-claim", {
        data,
        socketId,
      });
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM" };
      setPendingClaimJobId(result.jobId);

      const jobId = result.jobId;
      const onSessionStarted = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        tuftsSCOClaimSessionIdRef.current = ev.session_id ?? null;
      };
      const onOtpRequired = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        if (ev.session_id) tuftsSCOClaimSessionIdRef.current = ev.session_id;
        setTuftsSCOClaimOtpOpen(true);
        dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "OTP required for Tufts SCO. Please enter the code." }));
      };
      const onDone = (ev: any) => {
        if (String(ev?.jobId) !== String(jobId)) return;
        socket.off("selenium:tuftssco_claim_started", onSessionStarted);
        socket.off("selenium:otp_required", onOtpRequired);
        socket.off("job:update", onDone);
        setTuftsSCOClaimOtpOpen(false);
        tuftsSCOClaimSessionIdRef.current = null;
      };
      socket.on("selenium:tuftssco_claim_started", onSessionStarted);
      socket.on("selenium:otp_required", onOtpRequired);
      socket.on("job:update", onDone);

      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Tufts SCO claim queued. Awaiting Selenium..." }));
      toast({ title: "Tufts SCO Claim queued", description: "Selenium is opening the claim form.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "Tufts SCO claim failed" }));
      toast({ title: "Tufts SCO Claim error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  // CCA pre-auth selenium handler
  const handleCCAPreAuthSubmitSelenium = async (data: any) => {
    const formData = new FormData();
    formData.append("data", JSON.stringify(data));
    if (socketId) formData.append("socketId", socketId);
    const uploadedFiles: File[] = data.uploadedFiles ?? [];
    uploadedFiles.forEach((file: File) => {
      if (file.type === "application/pdf") {
        formData.append("pdfs", file);
      } else if (file.type.startsWith("image/")) {
        formData.append("images", file);
      }
    });
    try {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "Submitting CCA PreAuth..." }));
      const response = await apiRequest("POST", "/api/claims/cca-preauth", formData);
      const result = await response.json();
      if (result.error) throw new Error(result.error);
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM_PREAUTH" };
      setPendingClaimJobId(result.jobId);
      dispatch(setTaskStatus({ key: "claimSubmit", status: "pending", message: "CCA PreAuth queued. Awaiting Selenium..." }));
      toast({ title: "CCA PreAuth queued", description: "Selenium is processing the pre-authorization.", variant: "default" });
    } catch (error: any) {
      dispatch(setTaskStatus({ key: "claimSubmit", status: "error", message: error.message || "CCA PreAuth failed" }));
      toast({ title: "CCA PreAuth error", description: error.message || "An error occurred.", variant: "destructive" });
    }
  };

  // 5. selenium pdf download handler
  const handleMHSeleniumPdfDownload = async (
    data: any,
    selectedPatientId: number | null,
    groupTitleKey: "INSURANCE_CLAIM" | "INSURANCE_CLAIM_PREAUTH"
  ) => {
    try {
      if (!selectedPatientId) {
        throw new Error("Missing patientId");
      }

      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "pending",
          message: "Downloading PDF from Selenium...",
        })
      );

      const res = await apiRequest("POST", "/api/claims/selenium/fetchpdf", {
        patientId: selectedPatientId,
        pdf_url: data.pdf_url,
        groupTitleKey,
      });
      const result = await res.json();
      if (result.error) throw new Error(result.error);

      // Invalidate queries to refresh the Documents area
      queryClient.invalidateQueries({ queryKey: ["groupPdfs"] });
      queryClient.invalidateQueries({ queryKey: ["pdf-groups"] });
      queryClient.invalidateQueries({ queryKey: ["claims-recent"] });
      // Invalidate appointments so the schedule page picks up the new claim color
      queryClient.invalidateQueries({ queryKey: QK_APPOINTMENTS_BASE });

      const isPreAuth = groupTitleKey === "INSURANCE_CLAIM_PREAUTH";
      const preAuthNumber = data.preAuthNumber ?? data.result?.preAuthNumber ?? null;
      const claimNumberForToast = data.claimNumber ?? null;

      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "success",
          message: isPreAuth
            ? `PreAuth submitted & PDF saved.${preAuthNumber ? ` PreAuth #: ${preAuthNumber}` : ""}`
            : claimNumberForToast
              ? `Claim submitted — Claim #: ${claimNumberForToast}`
              : "Claim submitted & PDF downloaded successfully.",
        })
      );

      toast({
        title: isPreAuth ? "PreAuth Submitted" : "Success",
        description: isPreAuth
          ? preAuthNumber
            ? `PreAuth Number: ${preAuthNumber} — PDF saved to Documents.`
            : "PreAuth submitted! PDF saved to Documents page."
          : claimNumberForToast
            ? `Claim #: ${claimNumberForToast} — PDF saved to Documents.`
            : "Claim submitted successfully! PDF saved to Documents page.",
        duration: isPreAuth ? 10000 : 5000,
      });

      let advancedToNext = false;
      if (!isPreAuth) {
        advanceAiClaimQueue();
        advancedToNext = advanceChatbotClaimQueue();
      }

      // Pop up the final PDF so the user doesn't need to navigate to Documents
      // (skip if we're about to navigate to the next queued patient's claim)
      if (result.pdfFileId && !advancedToNext) {
        setPreviewPdfId(result.pdfFileId);
        setPreviewFallbackFilename(result.fileName ?? null);
        setPreviewOpen(true);
      }

      return result;
    } catch (error: any) {
      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "error",
          message: error.message || "Failed to download PDF",
        })
      );
      toast({
        title: "Error",
        description: error.message || "Failed to fetch PDF",
        variant: "destructive",
      });
    }
  };

  // 6. close claim
  const closeClaim = () => {
    setSelectedPatientId(null);
    setSelectedAppointmentId(null);
    setChatbotAutoSubmitSiteKey(undefined);
    setChatbotInitialTab(undefined);
    setChatbotAutoSubmitPreauthSiteKey(undefined);
    setIsClaimFormOpen(false);

    clearUrlParams(["newPatient", "appointmentId"]);

    // If an AI claim queue is pending resume, go straight back to appointments
    try {
      const raw = sessionStorage.getItem("ai_claim_queue");
      if (raw) {
        const parsed = JSON.parse(raw);
        if (parsed?.pendingResume && Array.isArray(parsed.appointments) && parsed.appointments.length > 0) {
          setWouterLocation("/appointments");
          return;
        }
      }
    } catch {}

    // Chatbot batch queues (chatbot_claim_queue, chatbot_check_claim_queue) are NOT
    // advanced here — they are advanced in advanceChatbotClaimQueue() which is called
    // only after the selenium job completes and PDF is downloaded. This prevents the
    // next patient's claim from starting before the current patient's PDF is saved.
  };

  // Pre Auth section
  const handleMHClaimPreAuthSubmitSelenium = async (data: any) => {
    const formData = new FormData();
    formData.append("data", JSON.stringify(data));
    if (socketId) formData.append("socketId", socketId);
    const uploadedFiles: File[] = data.uploadedFiles ?? [];

    uploadedFiles.forEach((file: File) => {
      if (file.type === "application/pdf") {
        formData.append("pdfs", file);
      } else if (file.type.startsWith("image/")) {
        formData.append("images", file);
      }
    });

    try {
      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "pending",
          message: "Submitting claim pre auth to Selenium...",
        })
      );
      const response = await apiRequest(
        "POST",
        "/api/claims/selenium-claim-pre-auth",
        formData
      );
      const result1 = await response.json();
      if (result1.error) throw new Error(result1.error);

      // Job is queued — wait for socket completion before downloading PDF
      pendingClaimMeta.current = { patientId: selectedPatientId, groupKey: "INSURANCE_CLAIM_PREAUTH" };
      setPendingClaimJobId(result1.jobId);

      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "pending",
          message: "Submitted to Selenium. Awaiting result...",
        })
      );

      toast({
        title: "Selenium service notified",
        description: "Pre-auth submitted to Selenium. Waiting for confirmation...",
        variant: "default",
      });
    } catch (error: any) {
      dispatch(
        setTaskStatus({
          key: "claimSubmit",
          status: "error",
          message: error.message || "Selenium submission failed",
        })
      );
      toast({
        title: "Selenium service error",
        description: error.message || "An error occurred.",
        variant: "destructive",
      });
    }
  };
  return (
    <div>
      <SeleniumTaskBanner
        status={status}
        message={message}
        show={show}
        onClear={() => dispatch(clearTaskStatus("claimSubmit"))}
      />

      <div className="container mx-auto space-y-6">
        <div className="flex justify-between items-center">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">
              Insurance Claims
            </h1>
            <p className="text-muted-foreground">
              Manage and submit insurance claims for patients
            </p>
          </div>
        </div>
      </div>

      {/* Recent Claims by Patients also handles new claims */}
      <ClaimsOfPatientModal onNewClaim={handleNewClaim} />

      {/* Recent Claims Section */}
      <Card>
        <CardHeader>
          <CardTitle>Recently Submitted Claims</CardTitle>
          <CardDescription>
            View and manage all recent claims information
          </CardDescription>
        </CardHeader>
        <CardContent>
          <ClaimsRecentTable
            allowEdit={true}
            allowView={true}
            allowDelete={true}
          />
        </CardContent>
      </Card>

      {/* File Upload Zone */}
      <ClaimDocumentsUploadMultiple />

      {/* Claim Form Modal */}
      {isClaimFormOpen && selectedPatientId !== null && (
        <ClaimForm
          patientId={selectedPatientId}
          appointmentId={selectedAppointmentId ?? undefined}
          autoSubmit={mode === "direct" || !!chatbotAutoSubmitSiteKey}
          autoSubmitSiteKey={chatbotAutoSubmitSiteKey}
          initialTab={chatbotInitialTab}
          autoSubmitPreauth={chatbotAutoSubmitPreauthSiteKey}
          proceduresOnly={mode === "procedures"}
          onClose={closeClaim}
          onSubmit={handleClaimSubmit}
          onHandleUpdatePatient={handleUpdatePatient}
          onHandleForMHSeleniumClaim={handleMHClaimSubmitSelenium}
          onHandleForMHSeleniumClaimPreAuth={handleMHClaimPreAuthSubmitSelenium}
          onHandleForCCASeleniumClaim={handleCCAClaimSubmitSelenium}
          onHandleForCCASeleniumPreAuth={handleCCAPreAuthSubmitSelenium}
          onHandleForUnitedDHSeleniumPreAuth={handleUnitedDHPreAuthSubmitSelenium}
          onHandleForDDMASeleniumClaim={handleDDMAClaimSubmitSelenium}
          onHandleForUnitedDHSeleniumClaim={handleUnitedDHClaimSubmitSelenium}
          onHandleForTuftsSCOSeleniumPreAuth={handleTuftsSCOPreAuthSubmitSelenium}
          onHandleForTuftsSCOSeleniumClaim={handleTuftsSCOClaimSubmitSelenium}
          isLicensed={isLicensed}
        />
      )}

      {/* PDF Preview Modal */}
      <PdfPreviewModal
        open={previewOpen}
        onClose={() => {
          setPreviewOpen(false);
          setPreviewPdfId(null);
          setPreviewFallbackFilename(null);
        }}
        pdfId={previewPdfId}
        fallbackFilename={previewFallbackFilename}
      />

      {/* DDMA Claim OTP Modal */}
      {ddmaClaimOtpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
          <div className="bg-white dark:bg-slate-900 rounded-xl shadow-lg w-full max-w-md p-6">
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-lg font-semibold">Enter OTP — Delta MA Claim</h2>
              <button type="button" onClick={() => setDdmaClaimOtpOpen(false)} className="text-slate-500 hover:text-slate-800">✕</button>
            </div>
            <p className="text-sm text-slate-500 mb-4">
              The Delta Dental MA portal requires a one-time password (OTP) to continue claim submission.
            </p>
            <form onSubmit={(e) => {
              e.preventDefault();
              const input = (e.currentTarget.elements.namedItem("otp") as HTMLInputElement);
              if (input?.value.trim()) handleDdmaClaimOtpSubmit(input.value.trim());
            }} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="ddma-claim-otp" className="text-sm font-medium">OTP</label>
                <input
                  id="ddma-claim-otp"
                  name="otp"
                  placeholder="Enter OTP code"
                  autoFocus
                  className="w-full border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
                />
              </div>
              <div className="flex justify-end gap-3">
                <button type="button" onClick={() => setDdmaClaimOtpOpen(false)} disabled={ddmaClaimOtpSubmitting}
                  className="px-4 py-2 text-sm border rounded-md hover:bg-slate-50 disabled:opacity-50">Cancel</button>
                <button type="submit" disabled={ddmaClaimOtpSubmitting}
                  className="px-4 py-2 text-sm bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50">
                  {ddmaClaimOtpSubmitting ? "Submitting..." : "Submit OTP"}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* Tufts SCO Claim OTP Modal */}
      {tuftsSCOClaimOtpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
          <div className="bg-white dark:bg-slate-900 rounded-xl shadow-lg w-full max-w-md p-6">
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-lg font-semibold">Enter OTP — Tufts SCO Claim</h2>
              <button type="button" onClick={() => setTuftsSCOClaimOtpOpen(false)} className="text-slate-500 hover:text-slate-800">✕</button>
            </div>
            <p className="text-sm text-slate-500 mb-4">
              The Tufts SCO (DentaQuest) portal requires a one-time password (OTP) to continue claim submission.
            </p>
            <form onSubmit={(e) => {
              e.preventDefault();
              const input = (e.currentTarget.elements.namedItem("otp") as HTMLInputElement);
              if (input?.value.trim()) handleTuftsSCOClaimOtpSubmit(input.value.trim());
            }} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="tuftssco-claim-otp" className="text-sm font-medium">OTP</label>
                <input
                  id="tuftssco-claim-otp"
                  name="otp"
                  placeholder="Enter OTP code"
                  autoFocus
                  className="w-full border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
                />
              </div>
              <div className="flex justify-end gap-3">
                <button type="button" onClick={() => setTuftsSCOClaimOtpOpen(false)} disabled={tuftsSCOClaimOtpSubmitting}
                  className="px-4 py-2 text-sm border rounded-md hover:bg-slate-50 disabled:opacity-50">Cancel</button>
                <button type="submit" disabled={tuftsSCOClaimOtpSubmitting}
                  className="px-4 py-2 text-sm bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50">
                  {tuftsSCOClaimOtpSubmitting ? "Submitting..." : "Submit OTP"}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* United/DentalHub PreAuth OTP Modal */}
      {unitedDHPreAuthOtpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
          <div className="bg-white dark:bg-slate-900 rounded-xl shadow-lg w-full max-w-md p-6">
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-lg font-semibold">Enter OTP — United/DentalHub PreAuth</h2>
              <button type="button" onClick={() => setUnitedDHPreAuthOtpOpen(false)} className="text-slate-500 hover:text-slate-800">✕</button>
            </div>
            <p className="text-sm text-slate-500 mb-4">
              The United/DentalHub portal requires a one-time password (OTP) to continue pre-authorization submission.
            </p>
            <form onSubmit={(e) => {
              e.preventDefault();
              const input = (e.currentTarget.elements.namedItem("otp") as HTMLInputElement);
              if (input?.value.trim()) handleUnitedDHPreAuthOtpSubmit(input.value.trim());
            }} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="uniteddh-preauth-otp" className="text-sm font-medium">OTP</label>
                <input
                  id="uniteddh-preauth-otp"
                  name="otp"
                  placeholder="Enter OTP code"
                  autoFocus
                  className="w-full border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
                />
              </div>
              <div className="flex justify-end gap-3">
                <button type="button" onClick={() => setUnitedDHPreAuthOtpOpen(false)} disabled={unitedDHPreAuthOtpSubmitting}
                  className="px-4 py-2 text-sm border rounded-md hover:bg-slate-50 disabled:opacity-50">Cancel</button>
                <button type="submit" disabled={unitedDHPreAuthOtpSubmitting}
                  className="px-4 py-2 text-sm bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50">
                  {unitedDHPreAuthOtpSubmitting ? "Submitting..." : "Submit OTP"}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* Tufts SCO PreAuth OTP Modal */}
      {tuftsSCOPreAuthOtpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
          <div className="bg-white dark:bg-slate-900 rounded-xl shadow-lg w-full max-w-md p-6">
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-lg font-semibold">Enter OTP — Tufts SCO PreAuth</h2>
              <button type="button" onClick={() => setTuftsSCOPreAuthOtpOpen(false)} className="text-slate-500 hover:text-slate-800">✕</button>
            </div>
            <p className="text-sm text-slate-500 mb-4">
              The Tufts SCO (DentaQuest) portal requires a one-time password (OTP) to continue pre-authorization submission.
            </p>
            <form onSubmit={(e) => {
              e.preventDefault();
              const input = (e.currentTarget.elements.namedItem("otp") as HTMLInputElement);
              if (input?.value.trim()) handleTuftsSCOPreAuthOtpSubmit(input.value.trim());
            }} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="tuftssco-preauth-otp" className="text-sm font-medium">OTP</label>
                <input
                  id="tuftssco-preauth-otp"
                  name="otp"
                  placeholder="Enter OTP code"
                  autoFocus
                  className="w-full border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
                />
              </div>
              <div className="flex justify-end gap-3">
                <button type="button" onClick={() => setTuftsSCOPreAuthOtpOpen(false)} disabled={tuftsSCOPreAuthOtpSubmitting}
                  className="px-4 py-2 text-sm border rounded-md hover:bg-slate-50 disabled:opacity-50">Cancel</button>
                <button type="submit" disabled={tuftsSCOPreAuthOtpSubmitting}
                  className="px-4 py-2 text-sm bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50">
                  {tuftsSCOPreAuthOtpSubmitting ? "Submitting..." : "Submit OTP"}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* United/DentalHub Claim OTP Modal */}
      {unitedDHClaimOtpOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
          <div className="bg-white dark:bg-slate-900 rounded-xl shadow-lg w-full max-w-md p-6">
            <div className="flex items-center justify-between mb-4">
              <h2 className="text-lg font-semibold">Enter OTP — United/DentalHub Claim</h2>
              <button type="button" onClick={() => setUnitedDHClaimOtpOpen(false)} className="text-slate-500 hover:text-slate-800">✕</button>
            </div>
            <p className="text-sm text-slate-500 mb-4">
              The United/DentalHub portal requires a one-time password (OTP) to continue claim submission.
            </p>
            <form onSubmit={(e) => {
              e.preventDefault();
              const input = (e.currentTarget.elements.namedItem("otp") as HTMLInputElement);
              if (input?.value.trim()) handleUnitedDHClaimOtpSubmit(input.value.trim());
            }} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="uniteddh-claim-otp" className="text-sm font-medium">OTP</label>
                <input
                  id="uniteddh-claim-otp"
                  name="otp"
                  placeholder="Enter OTP code"
                  autoFocus
                  className="w-full border rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
                />
              </div>
              <div className="flex justify-end gap-3">
                <button type="button" onClick={() => setUnitedDHClaimOtpOpen(false)} disabled={unitedDHClaimOtpSubmitting}
                  className="px-4 py-2 text-sm border rounded-md hover:bg-slate-50 disabled:opacity-50">Cancel</button>
                <button type="submit" disabled={unitedDHClaimOtpSubmitting}
                  className="px-4 py-2 text-sm bg-primary text-white rounded-md hover:bg-primary/90 disabled:opacity-50">
                  {unitedDHClaimOtpSubmitting ? "Submitting..." : "Submit OTP"}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}
    </div>
  );
}
