import {
    IsString, IsNotEmpty, IsNumber, IsInt, Min, Max, MaxLength,
    IsOptional, IsBoolean, IsIn, IsArray, ArrayMaxSize, ValidateNested, Validate,
    ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments,
    IsMongoId,
} from 'class-validator';
import { Type } from 'class-transformer';

@ValidatorConstraint({ name: 'slabRange', async: false })
class SlabRangeValidator implements ValidatorConstraintInterface {
    validate(_: any, args: ValidationArguments) {
        const obj = args.object as any;
        return obj.endDay >= obj.startDay;
    }
    defaultMessage() {
        return 'endDay must be >= startDay';
    }
}

class LateFineSlabDto {
    @IsInt() @Min(1) startDay: number;
    @IsInt() @Min(1) @Validate(SlabRangeValidator) endDay: number;
    @IsNumber() @Min(0) amount: number;
}

class LateFineRuleDto {
    @IsBoolean() enabled: boolean;
    @IsOptional() @IsString() @IsIn(['percentage', 'per_day', 'day_wise_slab']) type?: 'percentage' | 'per_day' | 'day_wise_slab';
    @IsOptional() @IsNumber() @Min(0) amountPerDay?: number;
    @IsOptional() @IsNumber() @Min(0) @Max(100) percentage?: number;
    @IsOptional() @IsArray() @ArrayMaxSize(50) @ValidateNested({ each: true }) @Type(() => LateFineSlabDto) slabs?: LateFineSlabDto[];
}

export class CreateRouteDto {
    @IsString() @IsNotEmpty() @MaxLength(200) name: string;
    @IsMongoId() academicYearId: string;
    @IsNumber() @Min(0) @Max(10000000) monthlyFee: number;
    @IsInt() @Min(1) @Max(31) dueDay: number;

    @IsOptional() @IsString() @MaxLength(500) description?: string;
    @IsOptional() @IsArray() @ArrayMaxSize(100) @IsString({ each: true }) @MaxLength(200, { each: true }) stops?: string[];
    @IsOptional() @IsString() @MaxLength(50) vehicleNumber?: string;
    @IsOptional() @IsString() @MaxLength(200) driverName?: string;
    @IsOptional() @IsString() @MaxLength(20) driverPhone?: string;

    @IsOptional() @ValidateNested() @Type(() => LateFineRuleDto)
    lateFine?: LateFineRuleDto;

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