import { z } from "zod";
import { AllocationStatus } from "../types/enums.js";

export const CreateAllocationBaseSchema = z.object({
  resourceId: z.string().optional(),
  projectId: z.string(),
  startDate: z.coerce.date(),
  endDate: z.coerce.date(),
  hoursPerDay: z.number().min(0).max(24),
  percentage: z.number().min(0).max(100),
  role: z.string().max(200).optional(),
  roleId: z.string().optional(),
  headcount: z.number().int().min(1).default(1),
  budgetCents: z.number().int().min(0).optional(),
  status: z.nativeEnum(AllocationStatus).default(AllocationStatus.PROPOSED),
  metadata: z.record(z.string(), z.unknown()).default({}),
});

export const CreateDemandRequirementBaseSchema = z.object({
  projectId: z.string(),
  startDate: z.coerce.date(),
  endDate: z.coerce.date(),
  hoursPerDay: z.number().min(0).max(24),
  percentage: z.number().min(0).max(100),
  role: z.string().max(200).optional(),
  roleId: z.string().optional(),
  headcount: z.number().int().min(1).default(1),
  budgetCents: z.number().int().min(0).optional(),
  status: z.nativeEnum(AllocationStatus).default(AllocationStatus.PROPOSED),
  metadata: z.record(z.string(), z.unknown()).default({}),
});

export const CreateAssignmentBaseSchema = z.object({
  demandRequirementId: z.string().optional(),
  resourceId: z.string(),
  projectId: z.string(),
  startDate: z.coerce.date(),
  endDate: z.coerce.date(),
  hoursPerDay: z.number().min(0).max(24),
  percentage: z.number().min(0).max(100),
  role: z.string().max(200).optional(),
  roleId: z.string().optional(),
  dailyCostCents: z.number().int().min(0).optional(),
  status: z.nativeEnum(AllocationStatus).default(AllocationStatus.PROPOSED),
  metadata: z.record(z.string(), z.unknown()).default({}),
});

export const CreateAllocationSchema = CreateAllocationBaseSchema.refine(
  (data) => data.endDate >= data.startDate,
  { message: "End date must be after start date", path: ["endDate"] },
);

export const UpdateAllocationSchema = CreateAllocationBaseSchema.partial();

export const CreateDemandRequirementSchema = CreateDemandRequirementBaseSchema.refine(
  (data) => data.endDate >= data.startDate,
  { message: "End date must be after start date", path: ["endDate"] },
);

export const UpdateDemandRequirementSchema = CreateDemandRequirementBaseSchema.partial();

export const CreateAssignmentSchema = CreateAssignmentBaseSchema.refine(
  (data) => data.endDate >= data.startDate,
  { message: "End date must be after start date", path: ["endDate"] },
);

export const UpdateAssignmentSchema = CreateAssignmentBaseSchema.partial();

export const FillDemandRequirementSchema = z.object({
  demandRequirementId: z.string(),
  resourceId: z.string(),
  hoursPerDay: z.number().min(0.5).max(24).optional(),
  status: z.nativeEnum(AllocationStatus).optional(),
});

export const FillOpenDemandByAllocationSchema = z.object({
  allocationId: z.string(),
  resourceId: z.string(),
  hoursPerDay: z.number().min(0.5).max(24).optional(),
  status: z.nativeEnum(AllocationStatus).optional(),
});

export const ShiftProjectSchema = z
  .object({
    projectId: z.string(),
    newStartDate: z.coerce.date(),
    newEndDate: z.coerce.date(),
  })
  .refine((data) => data.newEndDate >= data.newStartDate, {
    message: "New end date must be after new start date",
    path: ["newEndDate"],
  });

export const UpdateAllocationHoursSchema = z.object({
  allocationId: z.string(),
  hoursPerDay: z.number().min(0.5).max(24).optional(),
  startDate: z.coerce.date().optional(),
  endDate: z.coerce.date().optional(),
  includeSaturday: z.boolean().optional(),
  role: z.string().min(1).max(200).optional(),
});

export type CreateAllocationInput = z.infer<typeof CreateAllocationSchema>;
export type UpdateAllocationInput = z.infer<typeof UpdateAllocationSchema>;
export type CreateDemandRequirementInput = z.infer<typeof CreateDemandRequirementSchema>;
export type UpdateDemandRequirementInput = z.infer<typeof UpdateDemandRequirementSchema>;
export type CreateAssignmentInput = z.infer<typeof CreateAssignmentSchema>;
export type UpdateAssignmentInput = z.infer<typeof UpdateAssignmentSchema>;
export type FillDemandRequirementInput = z.infer<typeof FillDemandRequirementSchema>;
export type FillOpenDemandByAllocationInput = z.infer<typeof FillOpenDemandByAllocationSchema>;
export type ShiftProjectInput = z.infer<typeof ShiftProjectSchema>;
export type UpdateAllocationHoursInput = z.infer<typeof UpdateAllocationHoursSchema>;
