import type { QueryClient } from '@tanstack/react-query';
import {
  WORK_ORDER_STATUS_LABELS,
  WORK_ORDER_TRANSITIONS,
  type ChecklistState,
  type ReportUpsert,
  type WorkOrderDetail,
  type WorkOrderStatus,
} from '@siop/shared';
import { enfiler, lireFile } from './store';
import { rejouer } from './synchro';

/** Chaque geste terrain = une saisie en file + un patch OPTIMISTE du cache
 *  (le technicien voit son travail tout de suite, même en mode avion — le
 *  cache persisté garde ce patch après redémarrage). En ligne, la file se
 *  vide dans la foulée : le comportement R4.2 est conservé. */

function patchDetail(
  queryClient: QueryClient,
  otId: string,
  patch: (ot: WorkOrderDetail) => WorkOrderDetail,
): void {
  queryClient.setQueryData<WorkOrderDetail>(['work-orders', otId], (courant) =>
    courant ? patch(courant) : courant,
  );
}

export function enfilerTransition(
  queryClient: QueryClient,
  ot: WorkOrderDetail,
  to: WorkOrderStatus,
): void {
  enfiler({
    type: 'TRANSITION',
    otId: ot.id,
    otReference: ot.reference,
    libelle:
      to === 'DONE' ? 'Clôture de l’intervention' : `Passage à « ${WORK_ORDER_STATUS_LABELS[to]} »`,
    baseUpdatedAt: ot.updatedAt,
    payload: { to },
  });
  patchDetail(queryClient, ot.id, (c) => ({
    ...c,
    status: to,
    allowedTransitions: WORK_ORDER_TRANSITIONS[to],
  }));
  void rejouer(queryClient);
}

export function enfilerCoche(
  queryClient: QueryClient,
  ot: WorkOrderDetail,
  item: { id: string; label: string },
  state: ChecklistState,
): void {
  enfiler({
    type: 'COCHE',
    otId: ot.id,
    otReference: ot.reference,
    libelle: `Coche « ${item.label} » → ${state === 'DONE' ? 'fait' : state === 'NA' ? 'N/A' : 'à faire'}`,
    baseUpdatedAt: ot.updatedAt,
    payload: { itemId: item.id, state },
  });
  patchDetail(queryClient, ot.id, (c) => ({
    ...c,
    checklist: c.checklist.map((i) => (i.id === item.id ? { ...i, state } : i)),
  }));
  void rejouer(queryClient);
}

export function enfilerBilan(
  queryClient: QueryClient,
  ot: WorkOrderDetail,
  corps: Omit<ReportUpsert, 'baseUpdatedAt'>,
  labels: Partial<Record<keyof ReportUpsert, { id: string; label: string } | null>>,
): void {
  enfiler({
    type: 'BILAN',
    otId: ot.id,
    otReference: ot.reference,
    libelle: 'Bilan d’intervention codé',
    baseUpdatedAt: ot.updatedAt,
    payload: corps,
  });
  patchDetail(queryClient, ot.id, (c) => ({
    ...c,
    report: {
      note: corps.note !== undefined ? corps.note : (c.report?.note ?? null),
      doorState: labels.doorStateId !== undefined ? (labels.doorStateId ?? null) : (c.report?.doorState ?? null),
      cabinPosition:
        labels.cabinPositionId !== undefined ? (labels.cabinPositionId ?? null) : (c.report?.cabinPosition ?? null),
      anomaly: labels.anomalyId !== undefined ? (labels.anomalyId ?? null) : (c.report?.anomaly ?? null),
      externalCause:
        labels.externalCauseId !== undefined ? (labels.externalCauseId ?? null) : (c.report?.externalCause ?? null),
      actionTaken:
        labels.actionTakenId !== undefined ? (labels.actionTakenId ?? null) : (c.report?.actionTaken ?? null),
      componentConcerned:
        labels.componentConcernedId !== undefined
          ? (labels.componentConcernedId ?? null)
          : (c.report?.componentConcerned ?? null),
    },
  }));
  void rejouer(queryClient);
}

export function enfilerPhoto(
  queryClient: QueryClient,
  ot: WorkOrderDetail,
  fichier: { uri: string; nom: string; mime: string },
): void {
  enfiler({
    type: 'PHOTO',
    otId: ot.id,
    otReference: ot.reference,
    libelle: `Photo — ${fichier.nom}`,
    baseUpdatedAt: ot.updatedAt,
    payload: fichier,
  });
  void rejouer(queryClient);
}

/** Ce que la file porte encore pour cet OT — chips « en file » des écrans. */
export function saisiesPour(otId: string) {
  return lireFile().filter((s) => s.otId === otId);
}
