'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslations } from 'next-intl';
import { AppointmentsStrip } from '@/components/ui/treatment/AppointmentsStrip';
import { FdiToothChart } from '@/components/ui/treatment/FdiToothChart';
import { LabCasesDispatchPanel } from '@/components/ui/treatment/LabCasesDispatchPanel';
import { PastTreatmentsPanel } from '@/components/ui/treatment/PastTreatmentsPanel';
import { TreatmentDetailsEditor } from '@/components/ui/treatment/TreatmentDetailsEditor';
import { TreatmentPreviewCard } from '@/components/ui/treatment/TreatmentPreviewCard';
import { ToastStack } from '@/components/ui/shared/Toast';
import { treatmentTypeLabelFromCatalog } from '@/components/ui/treatment/treatmentTypeDisplay';
import {
  addCalendarDays,
  compareLocalDayStart,
  isSameLocalCalendarDay,
  startOfLocalDay,
} from '@/components/appointments/appointmentTime';
import { appointmentsApi } from '@/lib/api/appointments';
import { treatmentCatalogApi } from '@/lib/api/treatment-catalog';
import { treatmentsApi } from '@/lib/api/treatments';
import { pickAutoAppointment } from '@/components/shared/treatmentSelection';
import { canEditTreatment, canViewTreatment } from '@/components/shared/permissions';
import { formatApiErrorMessage } from '@/components/shared/formatApiError';
import { useToast } from '@/lib/hooks/useToast';
import type { Organization } from '@/types/organization';
import type { AppointmentRecord } from '@/types/appointment';
import type { TreatmentCatalogEntry } from '@/types/treatment-catalog';
import type {
  FdiToothId,
  LabCaseDraft,
  LinkedOrganizationOption,
  PastLabCase,
  PastTreatment,
  PastTreatmentCase,
  TreatmentAppointment,
  TreatmentDetailDraft,
} from '@/types/treatment';

type WorkspaceMode = 'live' | 'historical';

function isTreatmentDayHistorical(treatmentAt: string, todayStart: Date): boolean {
  return compareLocalDayStart(new Date(treatmentAt), todayStart) < 0;
}

function labCaseDraftsToPast(
  labCaseDrafts: LabCaseDraft[],
  details: TreatmentDetailDraft[],
): PastLabCase[] {
  return labCaseDrafts.map((lc) => ({
    id: lc.id ?? lc.clientId,
    clientId: lc.clientId,
    destinationOrganizationId: lc.destinationOrganizationId,
    labComment: lc.labComment || null,
    sentAt: lc.sentAt ?? null,
    treatmentDetailIds: lc.detailClientIds
      .map((cid) => details.find((d) => d.clientId === cid)?.id)
      .filter((id): id is string => Boolean(id)),
    details: lc.detailClientIds.map((cid) => {
      const d = details.find((x) => x.clientId === cid);
      return {
        id: d?.id ?? cid,
        clientId: cid,
        treatmentType: d?.treatmentType ?? 'consultation',
        teeth: d?.teeth ?? [],
      };
    }),
    sends: lc.sends ?? [],
  }));
}

function enrichDetailsWithLabSendState(
  details: TreatmentDetailDraft[],
  labCaseDrafts: LabCaseDraft[],
): TreatmentDetailDraft[] {
  return details.map((detail) => {
    const sentLabCase = labCaseDrafts.find(
      (lc) => lc.sentAt && lc.detailClientIds.includes(detail.clientId),
    );
    if (!sentLabCase) return detail;
    return {
      ...detail,
      labCaseId: sentLabCase.id ?? detail.labCaseId,
      sentAt: sentLabCase.sentAt ?? detail.sentAt,
      sends: sentLabCase.sends ?? detail.sends,
      sendToOrganizationIds: sentLabCase.destinationOrganizationId
        ? [sentLabCase.destinationOrganizationId]
        : detail.sendToOrganizationIds,
    };
  });
}

function buildWorkspaceSnapshot(
  appointment: TreatmentAppointment,
  details: TreatmentDetailDraft[],
  labCaseDrafts: LabCaseDraft[],
  title: string,
  id?: string,
): PastTreatment {
  const detailsForPreview = enrichDetailsWithLabSendState(details, labCaseDrafts);
  return {
    ...detailsToPreviewTreatment(detailsForPreview, {
      id: id ?? `preview-${appointment.id}`,
      title,
      patientId: appointment.patientId,
      treatmentAt: appointment.startAt,
    }),
    appointmentId: appointment.id,
    labCases: labCaseDraftsToPast(labCaseDrafts, details),
  };
}

function newDetail(): TreatmentDetailDraft {
  return {
    clientId:
      typeof crypto !== 'undefined' && 'randomUUID' in crypto
        ? crypto.randomUUID()
        : `detail-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
    treatmentType: 'restoration',
    teeth: [],
    comment: '',
    attachmentMetas: [],
    sendToOrganizationIds: [],
    sentAt: null,
  };
}

function newLabCaseDraft(): LabCaseDraft {
  return {
    clientId:
      typeof crypto !== 'undefined' && 'randomUUID' in crypto
        ? crypto.randomUUID()
        : `lab-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
    destinationOrganizationId: null,
    labComment: '',
    detailClientIds: [],
    toothProsthesis: [],
    sentAt: null,
    sends: [],
  };
}

function mapAppointment(record: AppointmentRecord): TreatmentAppointment {
  return {
    id: record.id,
    patientId: record.patientId,
    patientFirstName: record.patient.firstName,
    patientLastName: record.patient.lastName,
    providerUserId: record.providerUserId,
    startAt: record.startAt,
    endAt: record.endAt,
    purpose: record.purpose,
  };
}

function mapDetailFromApi(d: PastTreatmentCase): TreatmentDetailDraft {
  return {
    clientId: d.clientId,
    id: d.id,
    treatmentType: d.treatmentType,
    teeth: d.teeth,
    comment: d.notes ?? '',
    attachmentMetas: d.attachmentMetas ?? [],
    labCaseId: d.labCaseId ?? null,
    sendToOrganizationIds: d.destinationOrganizationId ? [d.destinationOrganizationId] : [],
    sends: d.sends ?? [],
    sentAt: d.sentAt ?? null,
  };
}

function mapLabCaseDraftFromApi(lc: PastLabCase): LabCaseDraft {
  const detailClientById = new Map(lc.details.map((d) => [d.id, d.clientId]));

  return {
    clientId: lc.clientId,
    id: lc.id,
    destinationOrganizationId: lc.destinationOrganizationId,
    labComment: lc.labComment ?? '',
    detailClientIds: lc.details.map((d) => d.clientId),
    toothProsthesis: (lc.toothProsthesis ?? []).map((tp) => ({
      detailClientId:
        detailClientById.get(tp.treatmentDetailId) ?? tp.treatmentDetailId,
      tooth: tp.tooth,
      prosthesisTypeCode: tp.prosthesisTypeCode,
    })),
    sentAt: lc.sentAt ?? null,
    sends: lc.sends ?? [],
  };
}

function serializeDetails(details: TreatmentDetailDraft[]) {
  return JSON.stringify(
    details.map((d) => ({
      clientId: d.clientId,
      id: d.id,
      treatmentType: d.treatmentType,
      teeth: d.teeth,
      comment: d.comment,
      attachmentMetas: d.attachmentMetas,
    })),
  );
}

function isDetailsDirty(
  details: TreatmentDetailDraft[],
  savedSnapshot: string | null,
): boolean {
  if (savedSnapshot === null) {
    return details.length !== 1 || details[0].comment !== '' || details[0].teeth.length > 0;
  }
  return serializeDetails(details) !== savedSnapshot;
}

function detailsToPreviewTreatment(
  details: TreatmentDetailDraft[],
  meta: { title: string; patientId: string; treatmentAt: string; id?: string },
): PastTreatment {
  return {
    id: meta.id ?? 'current-draft',
    patientId: meta.patientId,
    title: meta.title,
    treatmentAt: meta.treatmentAt,
    details: details.map((d, idx) => ({
      id: d.id ?? d.clientId ?? `draft-${idx + 1}`,
      clientId: d.clientId,
      treatmentType: d.treatmentType,
      teeth: d.teeth,
      notes: d.comment || null,
      attachmentMetas: d.attachmentMetas,
      labCaseId: d.labCaseId ?? null,
      destinationOrganizationId: d.sendToOrganizationIds[0] ?? null,
      sends: d.sends ?? [],
      sentAt: d.sentAt ?? null,
    })),
    labCases: [],
    documents: [],
  };
}

interface TreatmentWorkspaceProps {
  userId: string;
  currentOrganization: Organization | null;
}

export function TreatmentWorkspace({ userId, currentOrganization }: TreatmentWorkspaceProps) {
  const t = useTranslations('treatment');
  const { showError, showSuccess, messages: toastMessages } = useToast();
  const canView = canViewTreatment(currentOrganization);
  const canEdit = canEditTreatment(currentOrganization);

  const [stripHidden, setStripHidden] = useState(false);
  const todayStart = useMemo(() => startOfLocalDay(new Date()), []);

  const [selectedDay, setSelectedDay] = useState(() => startOfLocalDay(new Date()));
  const [appointments, setAppointments] = useState<TreatmentAppointment[]>([]);
  const [apptsLoading, setApptsLoading] = useState(false);
  const [selectionLocked, setSelectionLocked] = useState(false);
  const [selectedAppointmentId, setSelectedAppointmentId] = useState<string | null>(null);

  const [history, setHistory] = useState<PastTreatment[]>([]);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [historyPatientId, setHistoryPatientId] = useState<string | null>(null);

  const [orgs, setOrgs] = useState<LinkedOrganizationOption[]>([]);
  const [labDependentCodes, setLabDependentCodes] = useState<Set<string>>(new Set());
  const [treatmentCatalog, setTreatmentCatalog] = useState<TreatmentCatalogEntry[]>([]);
  const treatmentDropdownCatalog = useMemo(
    () => treatmentCatalog.filter((entry) => entry.availableInTreatment),
    [treatmentCatalog],
  );

  const [details, setDetails] = useState<TreatmentDetailDraft[]>(() => [newDetail()]);
  const [labCaseDrafts, setLabCaseDrafts] = useState<LabCaseDraft[]>([]);
  const [activeDetailId, setActiveDetailId] = useState<string>(() => details[0].clientId);
  const [activeLabCaseId, setActiveLabCaseId] = useState<string | null>(null);
  const [savedSnapshot, setSavedSnapshot] = useState<string | null>(null);
  const [saveStatus, setSaveStatus] = useState<'idle' | 'dirty' | 'saving' | 'saved' | 'error'>('idle');
  const [selectedPreviewId, setSelectedPreviewId] = useState<string | null>(null);
  const [workspaceMode, setWorkspaceMode] = useState<WorkspaceMode>('live');

  const selectionLockedRef = useRef(selectionLocked);
  selectionLockedRef.current = selectionLocked;

  const detailsRef = useRef(details);
  detailsRef.current = details;
  const savedSnapshotRef = useRef(savedSnapshot);
  savedSnapshotRef.current = savedSnapshot;
  const autosaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const saveInFlightRef = useRef(false);
  const saveQueuedRef = useRef(false);
  const draftHydratingRef = useRef(false);
  const workspaceModeRef = useRef(workspaceMode);
  workspaceModeRef.current = workspaceMode;
  const labCaseDraftsRef = useRef(labCaseDrafts);
  labCaseDraftsRef.current = labCaseDrafts;
  const skipNextGetDraftRef = useRef(false);

  const [sendBusyId, setSendBusyId] = useState<string | null>(null);
  const [uploadBusyDetailId, setUploadBusyDetailId] = useState<string | null>(null);
  const [organizationSearch, setOrganizationSearch] = useState('');
  const [recentOrganizationIds, setRecentOrganizationIds] = useState<string[]>([]);

  const isDetailLocked = useCallback(
    (detail: TreatmentDetailDraft) =>
      labCaseDrafts.some((lc) => lc.sentAt && lc.detailClientIds.includes(detail.clientId)),
    [labCaseDrafts],
  );

  const isDirty = useMemo(
    () => isDetailsDirty(details, savedSnapshot),
    [details, savedSnapshot],
  );

  const AUTOSAVE_DEBOUNCE_MS = 600;

  const selectedAppointment = useMemo(
    () => appointments.find((a) => a.id === selectedAppointmentId) ?? null,
    [appointments, selectedAppointmentId],
  );

  const isViewingPastDay = useMemo(
    () => compareLocalDayStart(selectedDay, todayStart) < 0,
    [selectedDay, todayStart],
  );

  const canEditTreatmentForDay =
    canEdit &&
    Boolean(selectedAppointment) &&
    !isViewingPastDay &&
    workspaceMode === 'live';

  const historyPanelItems = useMemo(() => {
    return history.filter((item) => {
      if (
        workspaceMode === 'live' &&
        selectedAppointmentId &&
        item.appointmentId === selectedAppointmentId
      ) {
        return false;
      }
      return true;
    });
  }, [history, selectedAppointmentId, workspaceMode]);

  const currentDraftPreview = useMemo<PastTreatment | null>(() => {
    if (!selectedAppointment) return null;
    return buildWorkspaceSnapshot(
      selectedAppointment,
      details,
      labCaseDrafts,
      t('treatmentPlanTitle', {
        patientName: `${selectedAppointment.patientFirstName} ${selectedAppointment.patientLastName}`,
      }),
      'current-draft',
    );
  }, [details, labCaseDrafts, selectedAppointment, t]);

  const previewTreatment = useMemo(() => {
    if (!selectedPreviewId) return currentDraftPreview;
    return historyPanelItems.find((item) => item.id === selectedPreviewId) ?? currentDraftPreview;
  }, [selectedPreviewId, historyPanelItems, currentDraftPreview]);

  const isPreviewAlreadyOpen = useMemo(() => {
    if (!previewTreatment?.appointmentId || !selectedAppointmentId) return false;
    if (selectedAppointmentId !== previewTreatment.appointmentId) return false;
    if (workspaceMode === 'historical') return true;
    if (workspaceMode === 'live' && selectedPreviewId === null) return true;
    if (workspaceMode === 'live' && selectedPreviewId === previewTreatment.id) return true;
    return false;
  }, [previewTreatment, selectedAppointmentId, workspaceMode, selectedPreviewId]);

  const hydrateFromTreatment = useCallback((treatment: PastTreatment) => {
    const mapped = treatment.details.map(mapDetailFromApi);
    setDetails(mapped);
    setActiveDetailId((prev) => {
      const stillExists = mapped.some((d) => d.clientId === prev);
      return stillExists ? prev : mapped[0]?.clientId ?? prev;
    });
    setSavedSnapshot(serializeDetails(mapped));
    const mappedLabCases = (treatment.labCases ?? []).map(mapLabCaseDraftFromApi);
    setLabCaseDrafts(mappedLabCases);
    setActiveLabCaseId(mappedLabCases[0]?.clientId ?? null);
    setOrganizationSearch('');
    setSaveStatus('idle');
  }, []);

  const activeDetail = useMemo(
    () => details.find((d) => d.clientId === activeDetailId) ?? details[0],
    [details, activeDetailId],
  );

  const selectedTeethSet = useMemo(() => new Set(activeDetail?.teeth ?? []), [activeDetail?.teeth]);

  useEffect(() => {
    setSelectionLocked(false);
  }, [selectedDay]);

  useEffect(() => {
    let cancelled = false;
    setApptsLoading(true);
    void (async () => {
      try {
        const dayStart = startOfLocalDay(selectedDay);
        const dayEnd = addCalendarDays(dayStart, 1);
        const response = await appointmentsApi.list({
          from: dayStart.toISOString(),
          to: dayEnd.toISOString(),
        });
        if (cancelled) return;
        const list = response.data
          .filter((a) => a.providerUserId === userId)
          .map(mapAppointment);
        setAppointments(list);
        if (!selectionLockedRef.current) {
          setSelectedAppointmentId(pickAutoAppointment(list, selectedDay));
        }
      } catch (error: unknown) {
        if (!cancelled) {
          showError(formatApiErrorMessage(error, t('errorLoadAppointments')));
        }
      } finally {
        if (!cancelled) setApptsLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [userId, selectedDay, showError, t]);

  useEffect(() => {
    const today = startOfLocalDay(new Date());
    if (!isSameLocalCalendarDay(selectedDay, today) || selectionLocked) return;

    const id = window.setInterval(() => {
      setSelectedAppointmentId((prev) => {
        const next = pickAutoAppointment(appointments, selectedDay);
        return next ?? prev;
      });
    }, 60_000);

    return () => window.clearInterval(id);
  }, [selectedDay, appointments, selectionLocked]);

  useEffect(() => {
    let cancelled = false;
    void (async () => {
      try {
        const [orgsResponse, catalogResponse] = await Promise.all([
          treatmentsApi.listLinkedOrganizations(),
          treatmentCatalogApi.list(),
        ]);
        if (cancelled) return;
        setOrgs(orgsResponse.data);
        setTreatmentCatalog(catalogResponse.data);
        setLabDependentCodes(
          new Set(catalogResponse.data.filter((entry) => entry.labDependent).map((entry) => entry.code)),
        );
      } catch (error: unknown) {
        if (!cancelled) {
          showError(formatApiErrorMessage(error, t('errorLoadOrgs')));
        }
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [showError, t]);

  useEffect(() => {
    if (selectedAppointment?.patientId) {
      setHistoryPatientId(selectedAppointment.patientId);
    }
  }, [selectedAppointment?.patientId]);

  useEffect(() => {
    if (!historyPatientId) return;
    let cancelled = false;
    setHistoryLoading(true);
    void (async () => {
      try {
        const response = await treatmentsApi.listPatientHistory(historyPatientId);
        if (!cancelled) setHistory(response.data);
      } catch (error: unknown) {
        if (!cancelled) {
          showError(formatApiErrorMessage(error, t('errorLoadHistory')));
        }
      } finally {
        if (!cancelled) setHistoryLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [historyPatientId, showError, t]);

  useEffect(() => {
    const appointmentId = selectedAppointment?.id;
    if (!appointmentId || workspaceMode !== 'live') return;

    if (skipNextGetDraftRef.current) {
      skipNextGetDraftRef.current = false;
      return;
    }

    let cancelled = false;
    draftHydratingRef.current = true;
    if (autosaveTimerRef.current) {
      clearTimeout(autosaveTimerRef.current);
      autosaveTimerRef.current = null;
    }

    void (async () => {
      try {
        const response = await treatmentsApi.getDraft(appointmentId);
        if (cancelled) return;

        if (response.data?.details?.length) {
          const mapped = response.data.details.map(mapDetailFromApi);
          setDetails(mapped);
          setActiveDetailId((prev) => {
            const stillExists = mapped.some((d) => d.clientId === prev);
            return stillExists ? prev : mapped[0].clientId;
          });
          setSavedSnapshot(serializeDetails(mapped));
        } else {
          const first = newDetail();
          setDetails([first]);
          setActiveDetailId(first.clientId);
          setSavedSnapshot(serializeDetails([first]));
        }

        const mappedLabCases = (response.data?.labCases ?? []).map(mapLabCaseDraftFromApi);
        setLabCaseDrafts(mappedLabCases);
        setActiveLabCaseId(mappedLabCases[0]?.clientId ?? null);
        setOrganizationSearch('');
        setSaveStatus('idle');
      } catch (error: unknown) {
        if (!cancelled) {
          showError(formatApiErrorMessage(error, t('errorLoadDraft')));
        }
      } finally {
        if (!cancelled) {
          draftHydratingRef.current = false;
        }
      }
    })();
    return () => {
      cancelled = true;
      draftHydratingRef.current = false;
    };
  }, [selectedAppointment?.id, workspaceMode, showError, t]);

  const persistDraft = useCallback(
    async (options?: { force?: boolean }) => {
      if (!selectedAppointment) throw new Error('No appointment selected');

      const currentDetails = detailsRef.current;
      const dirty = isDetailsDirty(currentDetails, savedSnapshotRef.current);

      if (!options?.force && !dirty) {
        return detailsToPreviewTreatment(currentDetails, {
          title: t('treatmentPlanTitle', {
            patientName: `${selectedAppointment.patientFirstName} ${selectedAppointment.patientLastName}`,
          }),
          patientId: selectedAppointment.patientId,
          treatmentAt: selectedAppointment.startAt,
        });
      }

      const response = await treatmentsApi.saveDraft(selectedAppointment.id, {
        details: currentDetails.map(({ clientId, id, treatmentType, teeth, comment, attachmentMetas }) => ({
          clientId,
          id,
          treatmentType,
          teeth,
          comment,
          attachmentIds: attachmentMetas.map((a) => a.id),
        })),
      });
      const mapped = response.data.details.map(mapDetailFromApi);
      setDetails(mapped);
      setActiveDetailId((prev) => {
        const stillExists = mapped.some((d) => d.clientId === prev);
        return stillExists ? prev : mapped[0]?.clientId ?? prev;
      });
      setSavedSnapshot(serializeDetails(mapped));
      return response.data;
    },
    [selectedAppointment, t],
  );

  const runDraftSave = useCallback(async () => {
    if (!selectedAppointment || saveInFlightRef.current) {
      if (saveInFlightRef.current) saveQueuedRef.current = true;
      return;
    }

    if (
      !isDetailsDirty(detailsRef.current, savedSnapshotRef.current)
    ) {
      return;
    }

    saveInFlightRef.current = true;
    setSaveStatus('saving');
    try {
      await persistDraft();
      setSaveStatus('saved');
    } catch (error: unknown) {
      setSaveStatus('error');
      showError(formatApiErrorMessage(error, t('errorSaveDraft')));
      throw error;
    } finally {
      saveInFlightRef.current = false;
      if (saveQueuedRef.current) {
        saveQueuedRef.current = false;
        if (isDetailsDirty(detailsRef.current, savedSnapshotRef.current)) {
          void runDraftSave();
        }
      }
    }
  }, [selectedAppointment, persistDraft, showError, t]);

  const refreshHistory = useCallback(async (patientId: string) => {
    try {
      const response = await treatmentsApi.listPatientHistory(patientId);
      setHistory(response.data);
    } catch (error: unknown) {
      showError(formatApiErrorMessage(error, t('errorLoadHistory')));
    }
  }, [showError, t]);

  const flushDraftSave = useCallback(async (): Promise<boolean> => {
    if (autosaveTimerRef.current) {
      clearTimeout(autosaveTimerRef.current);
      autosaveTimerRef.current = null;
    }

    if (workspaceModeRef.current !== 'live' || !selectedAppointment || !canEditTreatmentForDay) {
      return true;
    }

    while (saveInFlightRef.current) {
      await new Promise((resolve) => setTimeout(resolve, 50));
    }

    if (!isDetailsDirty(detailsRef.current, savedSnapshotRef.current)) {
      return true;
    }

    try {
      await runDraftSave();
      if (historyPatientId) {
        await refreshHistory(historyPatientId);
      }
      return true;
    } catch {
      return window.confirm(t('confirmDiscard'));
    }
  }, [selectedAppointment, canEditTreatmentForDay, runDraftSave, historyPatientId, refreshHistory, t]);

  useEffect(() => {
    if (draftHydratingRef.current || !canEditTreatmentForDay || !selectedAppointment?.id) {
      return;
    }

    if (!isDirty) {
      return;
    }

    setSaveStatus('dirty');

    if (autosaveTimerRef.current) clearTimeout(autosaveTimerRef.current);
    autosaveTimerRef.current = setTimeout(() => {
      autosaveTimerRef.current = null;
      void runDraftSave();
    }, AUTOSAVE_DEBOUNCE_MS);

    return () => {
      if (autosaveTimerRef.current) {
        clearTimeout(autosaveTimerRef.current);
        autosaveTimerRef.current = null;
      }
    };
  }, [details, isDirty, canEditTreatmentForDay, selectedAppointment?.id, runDraftSave]);

  const resetToLiveContext = useCallback(() => {
    setWorkspaceMode('live');
    setSelectedPreviewId(null);
  }, []);

  const onPickAppointment = useCallback(
    (id: string) => {
      void (async () => {
        const ok = await flushDraftSave();
        if (!ok) return;
        resetToLiveContext();
        setSelectionLocked(true);
        setSelectedAppointmentId(id);
      })();
    },
    [flushDraftSave, resetToLiveContext],
  );

  const onSelectDay = useCallback(
    (day: Date) => {
      void (async () => {
        const ok = await flushDraftSave();
        if (!ok) return;
        const patientIdToRefresh = historyPatientId;
        resetToLiveContext();
        setSelectedDay(day);
        if (patientIdToRefresh) {
          await refreshHistory(patientIdToRefresh);
        }
      })();
    },
    [flushDraftSave, resetToLiveContext, historyPatientId, refreshHistory],
  );

  const handleSelectPreviewTreatment = useCallback((treatment: PastTreatment) => {
    setSelectedPreviewId(treatment.id);
  }, []);

  const handleOpenTreatment = useCallback(() => {
    void (async () => {
      const treatment = previewTreatment;
      if (!treatment?.appointmentId) {
        showError(t('errorNoAppointmentForTreatment'));
        return;
      }

      if (isPreviewAlreadyOpen) return;

      const ok = workspaceModeRef.current === 'live' ? await flushDraftSave() : true;
      if (!ok) return;

      const isHistorical = isTreatmentDayHistorical(treatment.treatmentAt, todayStart);
      setWorkspaceMode(isHistorical ? 'historical' : 'live');
      setSelectedPreviewId(treatment.id);
      setSelectedDay(startOfLocalDay(new Date(treatment.treatmentAt)));
      setSelectionLocked(true);
      setSelectedAppointmentId(treatment.appointmentId);

      skipNextGetDraftRef.current = true;
      draftHydratingRef.current = true;
      hydrateFromTreatment(treatment);
      draftHydratingRef.current = false;
    })();
  }, [
    previewTreatment,
    isPreviewAlreadyOpen,
    flushDraftSave,
    hydrateFromTreatment,
    showError,
    t,
    todayStart,
  ]);

  const uploadForDetail = useCallback(
    async (detailClientId: string, files: FileList | File[]) => {
      if (!canEditTreatmentForDay || !selectedAppointment) return;
      const list = files instanceof FileList ? Array.from(files) : files;
      if (!list.length) return;

      setUploadBusyDetailId(detailClientId);
      try {
        const uploaded = await treatmentsApi.uploadCaseAttachments(
          selectedAppointment.id,
          detailClientId,
          list,
        );
        setDetails((prev) =>
          prev.map((d) =>
            d.clientId === detailClientId
              ? { ...d, attachmentMetas: [...d.attachmentMetas, ...uploaded.data] }
              : d,
          ),
        );
        showSuccess(t('successFilesUploaded', { count: uploaded.data.length }));
      } catch (error: unknown) {
        showError(formatApiErrorMessage(error, t('errorUpload')));
      } finally {
        setUploadBusyDetailId(null);
      }
    },
    [canEditTreatmentForDay, selectedAppointment, showSuccess, showError, t],
  );

  const persistLabCases = useCallback(
    async (savedTreatment: PastTreatment) => {
      if (!selectedAppointment) throw new Error('No appointment selected');

      const detailIdByClientId = new Map(
        savedTreatment.details.map((d) => [d.clientId, d.id]),
      );

      const payload = labCaseDrafts.map((lc) => ({
        clientId: lc.clientId,
        id: lc.id,
        destinationOrganizationId: lc.destinationOrganizationId ?? undefined,
        labComment: lc.labComment.trim() || undefined,
        treatmentDetailIds: lc.detailClientIds
          .map((clientId) => detailIdByClientId.get(clientId))
          .filter((id): id is string => Boolean(id)),
        toothProsthesis: lc.toothProsthesis
          .map((tp) => {
            const detailId = detailIdByClientId.get(tp.detailClientId);
            if (!detailId) return null;
            return {
              treatmentDetailId: detailId,
              tooth: tp.tooth,
              prosthesisTypeCode: tp.prosthesisTypeCode,
            };
          })
          .filter((row): row is { treatmentDetailId: string; tooth: string; prosthesisTypeCode: string } => row !== null),
      }));

      if (payload.length === 0) {
        return savedTreatment;
      }

      const response = await treatmentsApi.saveLabCases(selectedAppointment.id, {
        labCases: payload,
      });
      const mapped = response.data.labCases.map(mapLabCaseDraftFromApi);
      setLabCaseDrafts(mapped);
      setActiveLabCaseId((prev) => {
        if (prev && mapped.some((lc) => lc.clientId === prev)) return prev;
        return mapped[0]?.clientId ?? null;
      });
      return response.data;
    },
    [labCaseDrafts, selectedAppointment],
  );

  const handleSendLabCase = useCallback(
    async (labCase: LabCaseDraft) => {
      if (!canEditTreatmentForDay || !selectedAppointment) return;
      if (!labCase.destinationOrganizationId) {
        showError(t('errorChooseOrg'));
        return;
      }
      if (labCase.detailClientIds.length === 0) {
        showError(t('errorLabCaseNeedsDetails'));
        return;
      }

      setSendBusyId(labCase.clientId);
      try {
        if (autosaveTimerRef.current) {
          clearTimeout(autosaveTimerRef.current);
          autosaveTimerRef.current = null;
        }
        while (saveInFlightRef.current) {
          await new Promise((resolve) => setTimeout(resolve, 50));
        }

        const saved = await persistDraft({ force: true });
        const afterLabCases = await persistLabCases(saved);

        const refreshedLabCase = afterLabCases.labCases.find(
          (lc) => lc.clientId === labCase.clientId || lc.id === labCase.id,
        );
        if (!refreshedLabCase?.id) throw new Error(t('errorSendCase'));

        const response = await treatmentsApi.sendLabCase(refreshedLabCase.id);

        const sentDetailClientIds = new Set(labCase.detailClientIds);
        setDetails((prev) =>
          prev.map((detail) => {
            if (!sentDetailClientIds.has(detail.clientId)) return detail;
            return {
              ...detail,
              labCaseId: response.data.id,
              sentAt: response.data.sentAt,
              sends: response.data.sends,
              sendToOrganizationIds: response.data.destinationOrganizationId
                ? [response.data.destinationOrganizationId]
                : detail.sendToOrganizationIds,
            };
          }),
        );

        setLabCaseDrafts((prev) =>
          prev.map((lc) =>
            lc.clientId === labCase.clientId
              ? {
                  ...lc,
                  id: response.data.id,
                  sentAt: response.data.sentAt,
                  destinationOrganizationId: response.data.destinationOrganizationId,
                  sends: response.data.sends,
                }
              : lc,
          ),
        );

        setRecentOrganizationIds((prev) => {
          const orgId = labCase.destinationOrganizationId!;
          return [orgId, ...prev.filter((id) => id !== orgId)].slice(0, 10);
        });
        showSuccess(t('successCaseSent'));
      } catch (error: unknown) {
        showError(formatApiErrorMessage(error, t('errorSendCase')));
      } finally {
        setSendBusyId(null);
      }
    },
    [
      canEditTreatmentForDay,
      selectedAppointment,
      persistDraft,
      persistLabCases,
      showSuccess,
      showError,
      t,
    ],
  );

  if (!canView) {
    return (
      <div className="surface-card p-6 max-w-xl">
        <h2 className="text-lg font-semibold text-text-primary">{t('noPermissionTitle')}</h2>
        <p className="text-sm text-text-secondary mt-2">{t('noPermissionBody')}</p>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <header className="space-y-1">
        <h1 className="text-2xl font-semibold text-text-primary">{t('title')}</h1>
        <p className="text-sm text-text-secondary">
          {canEdit ? t('subtitleEditPhase4') : t('subtitleReadOnly')}
        </p>
      </header>

      <ToastStack {...toastMessages} />

      <AppointmentsStrip
        stripHidden={stripHidden}
        onToggleStripHidden={() => setStripHidden((s) => !s)}
        selectedDay={selectedDay}
        onSelectDay={onSelectDay}
        appointments={appointments}
        selectedAppointmentId={selectedAppointmentId}
        onSelectAppointment={onPickAppointment}
        treatmentCatalog={treatmentCatalog}
        loading={apptsLoading}
      />

      {workspaceMode === 'historical' && (
        <p className="text-sm text-emerald-700 dark:text-emerald-400 rounded-[var(--radius-md)] border border-emerald-500/40 bg-emerald-500/10 px-3 py-2">
          {t('historicalReadonlyNotice')}
        </p>
      )}

      {isViewingPastDay && workspaceMode === 'live' && (
        <p className="text-sm text-text-secondary rounded-[var(--radius-md)] border border-border/60 bg-background-secondary/50 px-3 py-2">
          {t('pastDayNotice')}
        </p>
      )}

      <div className="grid grid-cols-1 xl:grid-cols-[minmax(300px,380px)_minmax(0,1fr)] gap-4 items-start">
        <div className="space-y-3 min-w-0 xl:max-w-[380px]">
          {selectedAppointment ? (
            <div className="surface-card p-3 space-y-0.5">
              <p className="text-[10px] uppercase tracking-wide text-text-muted">{t('selectedPatient')}</p>
              <p className="text-base font-semibold text-text-primary">
                {selectedAppointment.patientFirstName} {selectedAppointment.patientLastName}
              </p>
              <p className="text-[11px] text-text-secondary">
                {t('purposeLabel')}{' '}
                <span className="text-text-primary">
                  {treatmentTypeLabelFromCatalog(selectedAppointment.purpose, treatmentCatalog)}
                </span>
              </p>
            </div>
          ) : (
            <div className="surface-card p-3 text-sm text-text-muted">
              {apptsLoading ? t('loadingAppointments') : t('selectDayWithAppointment')}
            </div>
          )}

          <TreatmentPreviewCard
            treatment={previewTreatment}
            labDependentCodes={labDependentCodes}
            treatmentCatalog={treatmentCatalog}
            orgs={orgs}
            openDisabled={isPreviewAlreadyOpen}
            onOpen={handleOpenTreatment}
          />

          <PastTreatmentsPanel
            items={historyPanelItems}
            treatmentCatalog={treatmentCatalog}
            loading={historyLoading}
            selectedPreviewId={selectedPreviewId}
            onSelectTreatment={handleSelectPreviewTreatment}
          />
        </div>

        <div className="space-y-3 min-w-0 w-full">
          <FdiToothChart
            selected={selectedTeethSet}
            onToggle={(fdi) => {
              if (!canEditTreatmentForDay || isDetailLocked(activeDetail)) return;
              setDetails((prev) =>
                prev.map((d) => {
                  if (d.clientId !== activeDetailId) return d;
                  const set = new Set(d.teeth);
                  if (set.has(fdi)) set.delete(fdi);
                  else set.add(fdi);
                  return { ...d, teeth: [...set].sort() as FdiToothId[] };
                }),
              );
            }}
            disabled={!canEditTreatmentForDay || isDetailLocked(activeDetail)}
          />

          <TreatmentDetailsEditor
            details={details}
            activeDetailId={activeDetailId}
            onActiveDetailChange={setActiveDetailId}
            onDetailsChange={setDetails}
            isDetailLocked={isDetailLocked}
            labDependentCodes={labDependentCodes}
            treatmentCatalog={treatmentDropdownCatalog}
            disabled={!canEditTreatmentForDay}
            canEdit={canEdit}
            saveStatus={saveStatus}
            uploadBusy={uploadBusyDetailId === activeDetailId}
            onAddDetail={() => {
              const next = newDetail();
              setDetails((prev) => [...prev, next]);
              setActiveDetailId(next.clientId);
            }}
            onUploadFiles={(files) => void uploadForDetail(activeDetailId, files ?? [])}
          />

          <LabCasesDispatchPanel
            details={details}
            labCases={labCaseDrafts}
            labDependentCodes={labDependentCodes}
            treatmentCatalog={treatmentCatalog}
            activeLabCaseId={activeLabCaseId}
            onActiveLabCaseChange={setActiveLabCaseId}
            onLabCasesChange={setLabCaseDrafts}
            disabled={!canEditTreatmentForDay}
            canEdit={canEdit}
            orgs={orgs}
            organizationSearch={organizationSearch}
            onOrganizationSearchChange={setOrganizationSearch}
            recentOrganizationIds={recentOrganizationIds}
            onRecentOrganizationPick={(orgId) => {
              if (!activeLabCaseId) return;
              setLabCaseDrafts((prev) =>
                prev.map((lc) =>
                  lc.clientId === activeLabCaseId && !lc.sentAt
                    ? { ...lc, destinationOrganizationId: orgId }
                    : lc,
                ),
              );
            }}
            sendBusyId={sendBusyId}
            onAddLabCase={() => {
              const next = newLabCaseDraft();
              setLabCaseDrafts((prev) => [...prev, next]);
              setActiveLabCaseId(next.clientId);
            }}
            onSendLabCase={(lc) => void handleSendLabCase(lc)}
          />
        </div>
      </div>
    </div>
  );
}
