import { IsString, IsNotEmpty, IsNumber, IsInt, Min, Max, MaxLength, IsOptional, IsBoolean, IsIn, IsArray, ArrayMinSize, ArrayMaxSize, ValidateNested, Validate, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, IsMongoId, IsDateString } 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 SubFeeDto {
    @IsString() @IsNotEmpty() @MaxLength(200) name: string;
    @IsNumber() @Min(0) @Max(10000000) amount: number;
}

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() @ValidateNested({ each: true }) @Type(() => LateFineSlabDto) slabs?: LateFineSlabDto[];
}

@ValidatorConstraint({ name: 'endAfterStart', async: false })
class EndAfterStartValidator implements ValidatorConstraintInterface {
    validate(_: any, args: ValidationArguments) {
        const obj = args.object as any;
        if (!obj.startDate || !obj.endDate) return true;
        return new Date(obj.endDate).getTime() > new Date(obj.startDate).getTime();
    }
    defaultMessage() {
        return 'endDate must be after startDate';
    }
}

export class CreateFeeStructureDto {
    @IsString() @IsNotEmpty() @MaxLength(200) name: string;
    @IsString() @IsIn(['one-time', 'monthly', 'quarterly', 'yearly']) feeType: 'one-time' | 'monthly' | 'quarterly' | 'yearly';
    @IsMongoId() academicYearId: string;
    @IsNumber() @Min(1) @Max(10000000) amount: number;
    @IsArray() @ArrayMinSize(1) @IsString({ each: true }) classIds: string[];
    @IsOptional() @IsNumber() @Min(1) @Max(12) dueMonth?: number;
    @IsNumber() @Min(1) @Max(31) dueDay: number;

    @IsOptional() @IsDateString() startDate?: string;
    @IsOptional() @IsDateString() @Validate(EndAfterStartValidator) endDate?: string;

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

    @IsOptional() @IsArray() @ArrayMaxSize(50) @ValidateNested({ each: true }) @Type(() => SubFeeDto)
    subFees?: SubFeeDto[];

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

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