import { z } from 'zod';
import {
  BILAN_FIELDS,
  CHECKLIST_STATES,
  REQUEST_STATUSES,
  WORK_ORDER_PRIORITIES,
  WORK_ORDER_STATUSES,
  WORK_ORDER_TYPES,
} from '../exploitation';
import { WorkOrderCostsSchema } from './gestion';

const PersonneSchema = z.object({
  id: z.uuid(),
  displayName: z.string(),
  initials: z.string(),
});

// ————— Ordres de travail —————

export const WorkOrderSummarySchema = z.object({
  id: z.uuid(),
  reference: z.string(),
  title: z.string(),
  type: z.enum(WORK_ORDER_TYPES),
  status: z.enum(WORK_ORDER_STATUSES),
  priority: z.enum(WORK_ORDER_PRIORITIES),
  assetId: z.uuid(),
  assetReference: z.string(),
  siteName: z.string(),
  dueDate: z.iso.datetime().nullable(),
  assignees: z.array(PersonneSchema),
  createdAt: z.iso.datetime(),
});
export type WorkOrderSummary = z.infer<typeof WorkOrderSummarySchema>;

export const WorkOrdersResponseSchema = z.object({
  workOrders: z.array(WorkOrderSummarySchema),
});
export type WorkOrdersResponse = z.infer<typeof WorkOrdersResponseSchema>;

export const WorkOrderEventSchema = z.object({
  id: z.uuid(),
  kind: z.string(),
  message: z.string().nullable(),
  by: PersonneSchema.nullable(),
  createdAt: z.iso.datetime(),
});

export const ChecklistItemSchema = z.object({
  id: z.uuid(),
  label: z.string(),
  state: z.enum(CHECKLIST_STATES),
  doneBy: PersonneSchema.nullable(),
  doneAt: z.iso.datetime().nullable(),
});
export type ChecklistItemDto = z.infer<typeof ChecklistItemSchema>;

const BilanValueSchema = z.object({ id: z.uuid(), label: z.string() }).nullable();

export const InterventionReportSchema = z.object({
  note: z.string().nullable(),
  doorState: BilanValueSchema,
  cabinPosition: BilanValueSchema,
  anomaly: BilanValueSchema,
  externalCause: BilanValueSchema,
  actionTaken: BilanValueSchema,
  componentConcerned: BilanValueSchema,
});
export type InterventionReportDto = z.infer<typeof InterventionReportSchema>;

export const WorkOrderDetailSchema = WorkOrderSummarySchema.extend({
  description: z.string().nullable(),
  locationName: z.string(),
  startedAt: z.iso.datetime().nullable(),
  completedAt: z.iso.datetime().nullable(),
  cancelledAt: z.iso.datetime().nullable(),
  createdBy: PersonneSchema.nullable(),
  request: z
    .object({ id: z.uuid(), reference: z.string(), requesterLabel: z.string() })
    .nullable(),
  events: z.array(WorkOrderEventSchema),
  checklist: z.array(ChecklistItemSchema),
  report: InterventionReportSchema.nullable(),
  /** Coûts figés (R3) : consommations + main-d'œuvre. */
  costs: WorkOrderCostsSchema,
  /** Ce que la machine à états autorise depuis l'état courant. */
  allowedTransitions: z.array(z.enum(WORK_ORDER_STATUSES)),
  /** Ce qui bloque la clôture (vide = clôturable) — messages métier. */
  closureBlockers: z.array(z.string()),
  /** Version pour le verrou optimiste (D2 mobile) : la file d'écriture la
   *  capture à la lecture et la renvoie avec chaque saisie. */
  updatedAt: z.iso.datetime(),
});
export type WorkOrderDetail = z.infer<typeof WorkOrderDetailSchema>;

export const WorkOrderCreateSchema = z.object({
  title: z.string().min(1).max(200),
  description: z.string().max(2000).optional(),
  type: z.enum(WORK_ORDER_TYPES),
  priority: z.enum(WORK_ORDER_PRIORITIES).optional(),
  assetId: z.uuid(),
  dueDate: z.iso.datetime().optional(),
  assigneeIds: z.array(z.uuid()).optional(),
});
export type WorkOrderCreate = z.infer<typeof WorkOrderCreateSchema>;

export const TransitionRequestSchema = z.object({
  to: z.enum(WORK_ORDER_STATUSES),
  comment: z.string().max(500).optional(),
  /** Verrou optimiste (D2) : updatedAt lu — 409 si l'OT a changé depuis. */
  baseUpdatedAt: z.iso.datetime().optional(),
});
export type TransitionRequest = z.infer<typeof TransitionRequestSchema>;

export const CommentCreateSchema = z.object({
  message: z.string().min(1).max(1000),
});
export type CommentCreate = z.infer<typeof CommentCreateSchema>;

export const AssigneesUpdateSchema = z.object({
  assigneeIds: z.array(z.uuid()).max(10),
});
export type AssigneesUpdate = z.infer<typeof AssigneesUpdateSchema>;

/** Upsert du bilan — null efface un champ. */
export const ReportUpsertSchema = z.object({
  note: z.string().max(2000).nullable().optional(),
  doorStateId: z.uuid().nullable().optional(),
  cabinPositionId: z.uuid().nullable().optional(),
  anomalyId: z.uuid().nullable().optional(),
  externalCauseId: z.uuid().nullable().optional(),
  actionTakenId: z.uuid().nullable().optional(),
  componentConcernedId: z.uuid().nullable().optional(),
  baseUpdatedAt: z.iso.datetime().optional(), // verrou optimiste (D2)
});
export type ReportUpsert = z.infer<typeof ReportUpsertSchema>;

export const ChecklistPatchSchema = z.object({
  state: z.enum(CHECKLIST_STATES),
  baseUpdatedAt: z.iso.datetime().optional(), // verrou optimiste (D2)
});
export type ChecklistPatch = z.infer<typeof ChecklistPatchSchema>;

// ————— Demandes —————

export const RequestSummarySchema = z.object({
  id: z.uuid(),
  reference: z.string(),
  description: z.string(),
  isPersonTrapped: z.boolean(),
  status: z.enum(REQUEST_STATUSES),
  rejectionReason: z.string().nullable(),
  assetId: z.uuid(),
  assetReference: z.string(),
  siteName: z.string(),
  requesterLabel: z.string(),
  workOrder: z
    .object({
      id: z.uuid(),
      reference: z.string(),
      status: z.enum(WORK_ORDER_STATUSES),
    })
    .nullable(),
  createdAt: z.iso.datetime(),
});
export type RequestSummary = z.infer<typeof RequestSummarySchema>;

export const RequestsResponseSchema = z.object({
  requests: z.array(RequestSummarySchema),
});
export type RequestsResponse = z.infer<typeof RequestsResponseSchema>;

export const RequestCreateSchema = z.object({
  assetId: z.uuid(),
  description: z.string().min(1).max(2000),
  isPersonTrapped: z.boolean().optional(),
});
export type RequestCreate = z.infer<typeof RequestCreateSchema>;

export const RequestApproveSchema = z.object({
  title: z.string().min(1).max(200).optional(), // défaut : description tronquée
  priority: z.enum(WORK_ORDER_PRIORITIES).optional(),
  assigneeIds: z.array(z.uuid()).optional(),
  dueDate: z.iso.datetime().optional(),
});
export type RequestApprove = z.infer<typeof RequestApproveSchema>;

export const RequestRejectSchema = z.object({
  reason: z.string().min(3, 'Le motif est requis').max(500),
});
export type RequestReject = z.infer<typeof RequestRejectSchema>;

// ————— Référentiels du bilan codé —————

export const ReferenceValueSchema = z.object({
  id: z.uuid(),
  field: z.enum(BILAN_FIELDS),
  label: z.string(),
  isActive: z.boolean(),
  usageCount: z.number().int(),
});
export type ReferenceValueDto = z.infer<typeof ReferenceValueSchema>;

export const ReferenceValuesResponseSchema = z.object({
  referenceValues: z.array(ReferenceValueSchema),
});
export type ReferenceValuesResponse = z.infer<typeof ReferenceValuesResponseSchema>;

export const ReferenceValueCreateSchema = z.object({
  field: z.enum(BILAN_FIELDS),
  label: z.string().min(1).max(120),
});
export type ReferenceValueCreate = z.infer<typeof ReferenceValueCreateSchema>;

export const ReferenceValueUpdateSchema = z.object({
  label: z.string().min(1).max(120).optional(),
  isActive: z.boolean().optional(),
});
export type ReferenceValueUpdate = z.infer<typeof ReferenceValueUpdateSchema>;
