import { z } from "zod";

export const partTypes = ["base", "partial", "full"] as const;
export const operationTypes = [
  "receive",
  "transfer",
  "assemble",
  "disassemble",
  "adjust",
  "cycle_count"
] as const;
export const operationStatuses = ["pending", "committed", "conflict", "void"] as const;

export type PartType = (typeof partTypes)[number];
export type OperationType = (typeof operationTypes)[number];
export type OperationStatus = (typeof operationStatuses)[number];

export const idSchema = z.string().uuid();
export const positiveNumber = z.coerce.number().positive();
export const nonNegativeNumber = z.coerce.number().nonnegative();

export const emailSchema = z.string().email().trim().toLowerCase();

export const loginSchema = z.object({
  email: emailSchema,
  password: z.string().min(8)
});

export const inviteCreateSchema = z.object({
  email: emailSchema
});

export const inviteAcceptSchema = z.object({
  token: z.string().min(24),
  password: z.string().min(8)
});

export const passwordResetRequestSchema = z.object({
  email: emailSchema
});

export const passwordResetConfirmSchema = z.object({
  token: z.string().min(24),
  password: z.string().min(8)
});

export const partCreateSchema = z.object({
  name: z.string().trim().min(1),
  sku: z.string().trim().optional().nullable(),
  type: z.enum(partTypes),
  defaultUnitCost: nonNegativeNumber.default(0)
});

export const locationCreateSchema = z.object({
  name: z.string().trim().min(1),
  kind: z.enum(["warehouse", "truck", "other"]).default("other"),
  priority: z.coerce.number().int().default(100)
});

export const receiveSchema = z.object({
  idempotencyKey: z.string().min(8),
  partId: idSchema,
  locationId: idSchema,
  quantity: positiveNumber,
  unitCost: nonNegativeNumber,
  vendorName: z.string().trim().optional().nullable(),
  reference: z.string().trim().optional().nullable()
});

export const transferSchema = z.object({
  idempotencyKey: z.string().min(8),
  partId: idSchema,
  fromLocationId: idSchema,
  toLocationId: idSchema,
  quantity: positiveNumber
});

export const bomLineSchema = z.object({
  componentPartId: idSchema,
  quantityRequired: positiveNumber
});

export const bomVersionCreateSchema = z.object({
  assemblyPartId: idSchema,
  name: z.string().trim().default("Default"),
  lines: z.array(bomLineSchema).min(1)
});

export const assemblySourceSchema = z.object({
  componentPartId: idSchema,
  locationId: idSchema,
  quantity: positiveNumber
});

export const assembleSchema = z.object({
  idempotencyKey: z.string().min(8),
  assemblyPartId: idSchema,
  bomVersionId: idSchema.optional(),
  outputLocationId: idSchema,
  quantity: positiveNumber,
  sourcingMode: z.enum(["single_location", "manual", "auto_pick"]).default("single_location"),
  sourceLocationId: idSchema.optional(),
  sources: z.array(assemblySourceSchema).optional()
});

export const disassembleSchema = z.object({
  idempotencyKey: z.string().min(8),
  assemblyPartId: idSchema,
  bomVersionId: idSchema.optional(),
  inputLocationId: idSchema,
  quantity: positiveNumber,
  returnLocationId: idSchema.optional()
});

export const adjustmentSchema = z.object({
  idempotencyKey: z.string().min(8),
  partId: idSchema,
  locationId: idSchema,
  quantityDelta: z.coerce.number(),
  reason: z.string().trim().min(1)
});

export const thresholdSchema = z.object({
  partId: idSchema,
  locationId: idSchema,
  minQuantity: nonNegativeNumber,
  reorderQuantity: nonNegativeNumber.default(0)
});

export const syncOperationSchema = z.discriminatedUnion("type", [
  z.object({ type: z.literal("receive"), payload: receiveSchema }),
  z.object({ type: z.literal("transfer"), payload: transferSchema }),
  z.object({ type: z.literal("assemble"), payload: assembleSchema }),
  z.object({ type: z.literal("disassemble"), payload: disassembleSchema }),
  z.object({ type: z.literal("adjust"), payload: adjustmentSchema })
]);

export type LoginInput = z.infer<typeof loginSchema>;
export type ReceiveInput = z.infer<typeof receiveSchema>;
export type TransferInput = z.infer<typeof transferSchema>;
export type AdjustmentInput = z.infer<typeof adjustmentSchema>;
export type AssembleInput = z.infer<typeof assembleSchema>;
export type DisassembleInput = z.infer<typeof disassembleSchema>;
export type SyncOperationInput = z.infer<typeof syncOperationSchema>;
