import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import {
    IsBoolean, IsEmail, IsEnum, IsIn, IsInt, IsMongoId, IsNumber, IsOptional, IsString, Matches, Max, MaxLength, Min, MinLength
} from 'class-validator';
import { LeadStage } from '../schema/lead.schema';

const trim = ({ value }: { value: unknown }) => (typeof value === 'string' ? value.trim() : value);
const lowerTrim = ({ value }: { value: unknown }) => (typeof value === 'string' ? value.trim().toLowerCase() : value);
const toBool = ({ value }: { value: unknown }) => (value === 'true' || value === true ? true : value === 'false' || value === false ? false : value);

export class CreateLeadDto {
    @ApiProperty({ required: false, description: 'Existing customer. Otherwise send customer_name and phone_no and the customer is found or created by mobile.' })
    @IsOptional()
    @IsMongoId()
    customer_id?: string;

    @ApiProperty({ required: false, example: 'Vikramaditya Roy' })
    @IsOptional()
    @IsString()
    @MinLength(2)
    @MaxLength(80)
    @Transform(trim)
    customer_name?: string;

    @ApiProperty({ required: false, example: '9830055443' })
    @IsOptional()
    @Matches(/^\d{7,15}$/)
    @Transform(trim)
    phone_no?: string;

    @ApiProperty({ required: false, default: '+91' })
    @IsOptional()
    @Matches(/^\+\d{1,4}$/)
    @Transform(trim)
    country_code?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsEmail()
    @Transform(lowerTrim)
    email?: string;

    @ApiProperty({ description: 'Product category id' })
    @IsMongoId()
    category_id: string;

    @ApiProperty({ description: 'Approved agent (authorised for the category) or Policy Staff. Policy Staff can only assign to themselves.' })
    @IsMongoId()
    assigned_to: string;

    @ApiProperty({ required: false, example: 25000 })
    @IsOptional()
    @IsNumber()
    @Min(0)
    estimated_premium?: number;

    @ApiProperty({ required: false, example: 'Looking for a ₹15L health floater' })
    @IsOptional()
    @IsString()
    @MaxLength(1000)
    @Transform(trim)
    notes?: string;
}

export class UpdateLeadDto {
    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    category_id?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    assigned_to?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsNumber()
    @Min(0)
    estimated_premium?: number;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsString()
    @MaxLength(1000)
    @Transform(trim)
    notes?: string;
}

export class MoveLeadStageDto {
    @ApiProperty({ enum: LeadStage })
    @IsEnum(LeadStage)
    stage: LeadStage;

    @ApiProperty({ required: false, description: 'Why the lead was lost' })
    @IsOptional()
    @IsString()
    @MaxLength(300)
    @Transform(trim)
    lost_reason?: string;
}

export class AddLeadNoteDto {
    @ApiProperty({ example: 'Called, customer asked for a lower premium option' })
    @IsString()
    @MinLength(2)
    @MaxLength(1000)
    @Transform(trim)
    remark: string;

    @ApiProperty({ required: false, description: 'true records this as a call and updates "last call"' })
    @IsOptional()
    @Transform(toBool)
    @IsBoolean()
    is_call?: boolean;

    @ApiProperty({ required: false, description: 'Next follow-up as epoch milliseconds, must be in the future' })
    @IsOptional()
    @IsInt()
    next_follow_up_at?: number;
}

export class LeadListDto {
    @ApiProperty({ required: false, default: 1 })
    @IsOptional()
    @Transform(({ value }) => Number(value))
    @IsInt()
    @Min(1)
    page: number = 1;

    @ApiProperty({ required: false, default: 10 })
    @IsOptional()
    @Transform(({ value }) => Number(value))
    @IsInt()
    @Min(1)
    @Max(100)
    limit: number = 10;

    @ApiProperty({ required: false, description: 'Search by customer name, mobile or requirement notes' })
    @IsOptional()
    @IsString()
    search?: string;

    @ApiProperty({ required: false, enum: LeadStage })
    @IsOptional()
    @IsEnum(LeadStage)
    stage?: LeadStage;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    assigned_to?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    category_id?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    customer_id?: string;

    @ApiProperty({ required: false, enum: ['true', 'false'], description: 'true = follow-up due today or overdue on open leads' })
    @IsOptional()
    @IsIn(['true', 'false'])
    follow_up_due?: string;
}

export class LeadBoardDto {
    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    assigned_to?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsMongoId()
    category_id?: string;

    @ApiProperty({ required: false })
    @IsOptional()
    @IsString()
    search?: string;

    @ApiProperty({ required: false, default: 50, description: 'Max cards per column' })
    @IsOptional()
    @Transform(({ value }) => Number(value))
    @IsInt()
    @Min(1)
    @Max(200)
    limit_per_stage: number = 50;
}

export class AssigneesDto {
    @ApiProperty({ required: false, description: 'Only agents authorised for this category (Policy Staff are always included)' })
    @IsOptional()
    @IsMongoId()
    category_id?: string;
}
