import { z } from 'zod';

/** Vocabulaires & schémas de la gestion (R3). */

export const PARTNER_KINDS = ['SUPPLIER', 'CLIENT'] as const;
export type PartnerKind = (typeof PARTNER_KINDS)[number];
export const PARTNER_KIND_LABELS: Record<PartnerKind, string> = {
  SUPPLIER: 'Fournisseur',
  CLIENT: 'Client / syndic',
};

export const PURCHASE_ORDER_STATUSES = ['DRAFT', 'SENT', 'RECEIVED', 'CANCELLED'] as const;
export type PurchaseOrderStatus = (typeof PURCHASE_ORDER_STATUSES)[number];
export const PURCHASE_ORDER_STATUS_LABELS: Record<PurchaseOrderStatus, string> = {
  DRAFT: 'Brouillon',
  SENT: 'Envoyé',
  RECEIVED: 'Reçu',
  CANCELLED: 'Annulé',
};

export const STOCK_MOVEMENT_KINDS = ['RECEIPT', 'ENTRY', 'CONSUMPTION', 'ADJUSTMENT'] as const;
export type StockMovementKind = (typeof STOCK_MOVEMENT_KINDS)[number];
export const STOCK_MOVEMENT_KIND_LABELS: Record<StockMovementKind, string> = {
  RECEIPT: 'Réception',
  ENTRY: 'Entrée',
  CONSUMPTION: 'Sortie (OT)',
  ADJUSTMENT: 'Ajustement',
};

// ————— Tiers —————

export const PartnerSchema = z.object({
  id: z.uuid(),
  name: z.string(),
  kind: z.enum(PARTNER_KINDS),
  contactName: z.string().nullable(),
  phone: z.string().nullable(),
  email: z.string().nullable(),
  city: z.string().nullable(),
  isActive: z.boolean(),
  openOrders: z.number().int(), // BC non reçus/annulés (fournisseur)
  siteNames: z.array(z.string()), // sites gérés (client/syndic) — maquette « Rattachements »
});
export type PartnerDto = z.infer<typeof PartnerSchema>;

export const PartnersResponseSchema = z.object({ partners: z.array(PartnerSchema) });
export type PartnersResponse = z.infer<typeof PartnersResponseSchema>;

export const PartnerCreateSchema = z.object({
  name: z.string().min(1).max(120),
  kind: z.enum(PARTNER_KINDS),
  contactName: z.string().max(120).optional(),
  phone: z.string().max(40).optional(),
  email: z.email().optional(),
  city: z.string().max(80).optional(),
});
export type PartnerCreate = z.infer<typeof PartnerCreateSchema>;

export const PartnerUpdateSchema = PartnerCreateSchema.partial().extend({
  isActive: z.boolean().optional(),
});
export type PartnerUpdate = z.infer<typeof PartnerUpdateSchema>;

// ————— Pièces & stock (dérivé des mouvements) —————

export const PartSchema = z.object({
  id: z.uuid(),
  reference: z.string(),
  designation: z.string(),
  threshold: z.number().int(),
  lastUnitPrice: z.number().nullable(),
  compatible: z.string().nullable(),
  supplierId: z.uuid().nullable(),
  supplierName: z.string().nullable(),
  isActive: z.boolean(),
  stock: z.number().int(), // Σ mouvements — calculé, jamais stocké
  belowThreshold: z.boolean(),
});
export type PartDto = z.infer<typeof PartSchema>;

export const PartsResponseSchema = z.object({ parts: z.array(PartSchema) });
export type PartsResponse = z.infer<typeof PartsResponseSchema>;

export const PartCreateSchema = z.object({
  designation: z.string().min(1).max(200),
  threshold: z.number().int().min(0).optional(),
  supplierId: z.uuid().optional(),
  compatible: z.string().max(200).optional(),
  initialPrice: z.number().positive().optional(), // premier PU connu
});
export type PartCreate = z.infer<typeof PartCreateSchema>;

export const PartUpdateSchema = z.object({
  designation: z.string().min(1).max(200).optional(),
  threshold: z.number().int().min(0).optional(),
  supplierId: z.uuid().nullable().optional(),
  compatible: z.string().max(200).nullable().optional(),
  isActive: z.boolean().optional(),
});
export type PartUpdate = z.infer<typeof PartUpdateSchema>;

export const StockMovementSchema = z.object({
  id: z.uuid(),
  kind: z.enum(STOCK_MOVEMENT_KINDS),
  quantity: z.number().int(),
  unitPrice: z.number().nullable(),
  reason: z.string().nullable(),
  workOrderReference: z.string().nullable(),
  purchaseOrderReference: z.string().nullable(),
  byName: z.string().nullable(),
  createdAt: z.iso.datetime(),
});
export type StockMovementDto = z.infer<typeof StockMovementSchema>;

export const PartDetailSchema = PartSchema.extend({
  movements: z.array(StockMovementSchema), // récents d'abord — le stock EST cette liste
});
export type PartDetail = z.infer<typeof PartDetailSchema>;

/** Entrée manuelle (+) ou ajustement (±, motif requis). */
export const StockMovementCreateSchema = z.object({
  kind: z.enum(['ENTRY', 'ADJUSTMENT']),
  quantity: z.number().int().refine((q) => q !== 0, 'Quantité non nulle requise'),
  reason: z.string().max(300).optional(),
});
export type StockMovementCreate = z.infer<typeof StockMovementCreateSchema>;

// ————— Bons de commande —————

export const PurchaseOrderLineSchema = z.object({
  id: z.uuid(),
  partId: z.uuid(),
  partReference: z.string(),
  designation: z.string(),
  quantity: z.number().int(),
  unitPrice: z.number(),
});

export const PurchaseOrderSchema = z.object({
  id: z.uuid(),
  reference: z.string(),
  status: z.enum(PURCHASE_ORDER_STATUSES),
  supplierId: z.uuid(),
  supplierName: z.string(),
  lines: z.array(PurchaseOrderLineSchema),
  total: z.number(),
  sentAt: z.iso.datetime().nullable(),
  receivedAt: z.iso.datetime().nullable(),
  createdAt: z.iso.datetime(),
});
export type PurchaseOrderDto = z.infer<typeof PurchaseOrderSchema>;

export const PurchaseOrdersResponseSchema = z.object({
  purchaseOrders: z.array(PurchaseOrderSchema),
});
export type PurchaseOrdersResponse = z.infer<typeof PurchaseOrdersResponseSchema>;

export const PurchaseOrderCreateSchema = z.object({
  supplierId: z.uuid(),
  lines: z
    .array(
      z.object({
        partId: z.uuid(),
        quantity: z.number().int().positive(),
        unitPrice: z.number().positive(),
      }),
    )
    .min(1),
});
export type PurchaseOrderCreate = z.infer<typeof PurchaseOrderCreateSchema>;

export const PurchaseOrderTransitionSchema = z.object({
  to: z.enum(['SENT', 'RECEIVED', 'CANCELLED']),
});
export type PurchaseOrderTransition = z.infer<typeof PurchaseOrderTransitionSchema>;

// ————— Coûts sur OT —————

export const ConsumePartSchema = z.object({
  partId: z.uuid(),
  quantity: z.number().int().positive(),
});
export type ConsumePart = z.infer<typeof ConsumePartSchema>;

export const LaborTimeCreateSchema = z.object({
  minutes: z.number().int().positive().max(24 * 60),
  userId: z.uuid().optional(), // défaut : la personne connectée
  note: z.string().max(200).optional(),
});
export type LaborTimeCreate = z.infer<typeof LaborTimeCreateSchema>;

export const WorkOrderCostsSchema = z.object({
  parts: z.array(
    z.object({
      id: z.uuid(),
      designation: z.string(),
      quantity: z.number().int(),
      unitPrice: z.number(),
      total: z.number(),
    }),
  ),
  labor: z.array(
    z.object({
      id: z.uuid(),
      displayName: z.string(),
      minutes: z.number().int(),
      hourlyRate: z.number(),
      total: z.number(),
      note: z.string().nullable(),
    }),
  ),
  total: z.number(),
});
export type WorkOrderCosts = z.infer<typeof WorkOrderCostsSchema>;
