import {
  IsString,
  IsUUID,
  IsOptional,
  IsDateString,
  IsEnum,
  IsNumber,
  IsBoolean,
  IsPositive,
  MaxLength,
  MinLength,
} from 'class-validator';
import { LeaveStatus, HalfDayType } from '../entities/leave.entity';

/**
 * DTO for creating a new leave request
 */
export class CreateLeaveDto {
  @IsUUID()
  companyId: string;

  @IsUUID()
  employeeId: string;

  @IsUUID()
  leaveTypeId: string;

  @IsOptional()
  @IsUUID()
  allocationId?: string;

  @IsDateString()
  dateFrom: string;

  @IsDateString()
  dateTo: string;

  @IsNumber()
  @IsPositive()
  daysRequested: number;

  @IsOptional()
  @IsBoolean()
  isHalfDay?: boolean;

  @IsOptional()
  @IsEnum(['morning', 'afternoon'])
  halfDayType?: HalfDayType;

  @IsOptional()
  @IsEnum(['draft', 'submitted', 'approved', 'rejected', 'cancelled'])
  status?: LeaveStatus;

  @IsOptional()
  @IsString()
  requestReason?: string;

  @IsOptional()
  @IsString()
  documentUrl?: string;

  @IsOptional()
  @IsString()
  notes?: string;
}

/**
 * DTO for updating an existing leave request
 */
export class UpdateLeaveDto {
  @IsOptional()
  @IsUUID()
  leaveTypeId?: string;

  @IsOptional()
  @IsUUID()
  allocationId?: string | null;

  @IsOptional()
  @IsDateString()
  dateFrom?: string;

  @IsOptional()
  @IsDateString()
  dateTo?: string;

  @IsOptional()
  @IsNumber()
  @IsPositive()
  daysRequested?: number;

  @IsOptional()
  @IsBoolean()
  isHalfDay?: boolean;

  @IsOptional()
  @IsEnum(['morning', 'afternoon'])
  halfDayType?: HalfDayType | null;

  @IsOptional()
  @IsEnum(['draft', 'submitted', 'approved', 'rejected', 'cancelled'])
  status?: LeaveStatus;

  @IsOptional()
  @IsString()
  requestReason?: string | null;

  @IsOptional()
  @IsString()
  documentUrl?: string | null;

  @IsOptional()
  @IsString()
  notes?: string | null;
}

/**
 * DTO for submitting a leave request for approval
 */
export class SubmitLeaveDto {
  @IsOptional()
  @IsString()
  requestReason?: string;
}

/**
 * DTO for approving a leave request
 */
export class ApproveLeaveDto {
  @IsOptional()
  @IsString()
  notes?: string;
}

/**
 * DTO for rejecting a leave request
 */
export class RejectLeaveDto {
  @IsString()
  @MinLength(1)
  @MaxLength(1000)
  rejectionReason: string;
}

/**
 * DTO for cancelling a leave request
 */
export class CancelLeaveDto {
  @IsOptional()
  @IsString()
  @MaxLength(1000)
  reason?: string;
}

/**
 * DTO for creating a leave type
 */
export class CreateLeaveTypeDto {
  @IsUUID()
  companyId: string;

  @IsString()
  @MinLength(1)
  @MaxLength(255)
  name: string;

  @IsString()
  @MinLength(1)
  @MaxLength(50)
  code: string;

  @IsOptional()
  @IsString()
  description?: string;

  @IsOptional()
  @IsString()
  @MaxLength(7)
  color?: string;

  @IsOptional()
  @IsEnum(['vacation', 'sick', 'personal', 'maternity', 'paternity', 'bereavement', 'unpaid', 'other'])
  leaveCategory?: string;

  @IsOptional()
  @IsEnum(['fixed', 'accrual', 'unlimited'])
  allocationType?: string;

  @IsOptional()
  @IsBoolean()
  requiresApproval?: boolean;

  @IsOptional()
  @IsBoolean()
  requiresDocument?: boolean;

  @IsOptional()
  @IsNumber()
  maxDaysPerRequest?: number;

  @IsOptional()
  @IsNumber()
  maxDaysPerYear?: number;

  @IsOptional()
  @IsNumber()
  minDaysNotice?: number;

  @IsOptional()
  @IsBoolean()
  isPaid?: boolean;

  @IsOptional()
  @IsNumber()
  payPercentage?: number;

  @IsOptional()
  @IsBoolean()
  isActive?: boolean;
}

/**
 * DTO for creating a leave allocation
 */
export class CreateLeaveAllocationDto {
  @IsUUID()
  employeeId: string;

  @IsUUID()
  leaveTypeId: string;

  @IsNumber()
  @IsPositive()
  daysAllocated: number;

  @IsDateString()
  dateFrom: string;

  @IsDateString()
  dateTo: string;

  @IsOptional()
  @IsString()
  notes?: string;
}

/**
 * DTO for updating a leave allocation
 */
export class UpdateLeaveAllocationDto {
  @IsOptional()
  @IsNumber()
  @IsPositive()
  daysAllocated?: number;

  @IsOptional()
  @IsDateString()
  dateFrom?: string;

  @IsOptional()
  @IsDateString()
  dateTo?: string;

  @IsOptional()
  @IsString()
  notes?: string | null;
}
