import {
  IsString,
  IsNotEmpty,
  IsArray,
  ValidateNested,
  IsOptional,
  ArrayMinSize,
  ValidateIf,
} from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';

class CommissionInstanceDto {
  @ApiPropertyOptional({ example: '1', description: 'Selected ID' })
  @IsString()
  @IsOptional()
  id?: string;

  @ApiPropertyOptional({ example: '1', description: 'Selected ID' })
  @IsString()
  @IsOptional()
  instance?: string;

  @ApiProperty({ example: 'percentage', description: 'Type of commission' })
  @IsString()
  @IsNotEmpty({ message: 'Commission type is required' })
  commission_type: string;

  @ApiProperty({
    example: '10',
    description: 'Commission amount or percentage',
  })
  @IsString()
  @IsNotEmpty({ message: 'Commission amount is required' })
  commission_amount: string;
}

class SetDto {
  @ApiPropertyOptional({ example: '1', description: 'Selected ID' })
  @IsString()
  @IsOptional()
  id?: string;

  @ApiProperty({ example: 'Set A', description: 'Name of the commission set' })
  @IsString()
  @IsNotEmpty({ message: 'Set name is required' })
  set_name: string;

  /**
   * Conditionally required only when student_condition === '2'.
   * The condition is evaluated using the parent DTO value via ValidateIf.
   */
  @ApiPropertyOptional({
    example: '5',
    description: 'Minimum students required (only if student_condition = 2)',
  })
  @ValidateIf((o, value) => o?.__parentDto?.student_condition === '2')
  @IsString()
  @IsNotEmpty({
    message: 'Minimum students is required when student condition is 2',
  })
  min_students?: string;

  @ApiPropertyOptional({
    example: '10',
    description: 'Maximum students allowed (only if student_condition = 2)',
  })
  @ValidateIf((o, value) => o?.__parentDto?.student_condition === '2')
  @IsString()
  @IsNotEmpty({
    message: 'Maximum students is required when student condition is 2',
  })
  max_students?: string;

  @ApiProperty({
    example: '1',
    description: 'Indicates if bonus applies (1 = yes, 0 = no)',
  })
  @IsString()
  @IsNotEmpty({ message: 'Bonus selection is required' })
  has_bonus: string;

  @ApiPropertyOptional({
    example: 'flat',
    description: 'Bonus type (required if has_bonus = 1)',
  })
  @ValidateIf((o) => o.has_bonus === '1')
  @IsString()
  @IsNotEmpty({ message: 'Bonus type is required when bonus is selected' })
  bonus_type?: string;

  @ApiPropertyOptional({
    example: '500',
    description: 'Bonus amount (required if has_bonus = 1)',
  })
  @ValidateIf((o) => o.has_bonus === '1')
  @IsString()
  @IsNotEmpty({ message: 'Bonus amount is required when bonus is selected' })
  bonus_amount?: string;

  @ApiPropertyOptional({
    type: [Object],
    description: 'Optional specific contract file(s)',
  })
  @IsOptional()
  @IsArray()
  specific_contract?: any[];

  @ApiPropertyOptional({
    type: [Object],
    description: 'Optional specific contract file(s)',
  })
  @IsOptional()
  @IsArray()
  attachment_file?: any[];

  @ApiProperty({
    type: [CommissionInstanceDto],
    description: 'Commission structure instances',
  })
  @IsArray()
  @ArrayMinSize(1, { message: 'At least one commission instance is required' })
  @ValidateNested({ each: true })
  @Type(() => CommissionInstanceDto)
  instances: CommissionInstanceDto[];
}

class ApplicableSetDto {
  @ApiPropertyOptional({ example: '1', description: 'Selected ID' })
  @IsString()
  @IsOptional()
  id?: string;

  @ApiPropertyOptional({
    type: [String],
    description: 'Applicable campuses (required if campus_condition = 2)',
    example: ['campus_1', 'campus_2'],
  })
  @IsOptional()
  @IsArray()
  applicable_campuses?: string[];

  @ApiPropertyOptional({
    type: [String],
    description:
      'Applicable study levels (required if study_level_condition = 2)',
    example: ['bachelor', 'master'],
  })
  @IsOptional()
  @IsArray()
  applicable_study_levels?: string[];

  @ApiPropertyOptional({
    type: [String],
    description: 'Applicable courses (required if course_condition = 2)',
    example: ['course_1', 'course_2'],
  })
  @IsOptional()
  @IsArray()
  applicable_courses?: string[];

  @ApiProperty({ example: '2', description: 'Number of instances' })
  @IsString()
  @IsNotEmpty({ message: 'Number of instances is required' })
  no_of_instances: string;

  @ApiProperty({ example: '5', description: 'Number of students per instance' })
  @IsString()
  @IsNotEmpty({ message: 'Students per is required' })
  students_per: string;

  @ApiProperty({
    type: [SetDto],
    description: 'List of sets under this applicable condition',
  })
  @IsArray()
  @ArrayMinSize(1, { message: 'At least one set is required' })
  @ValidateNested({ each: true })
  @Type(() => SetDto)
  sets: SetDto[];
}

export class CreateCommissionContractDto {
  @ApiPropertyOptional({ example: '1', description: 'Selected ID' })
  @IsString()
  @IsOptional()
  id?: string;

  @ApiProperty({ example: 'prod_101', description: 'Selected product ID' })
  @IsString()
  @IsNotEmpty({ message: 'Product is required' })
  product_id: string;

  @ApiProperty({ example: 'associate_type', description: 'Association type' })
  @IsString()
  @IsNotEmpty({ message: 'Associate is required' })
  association_type: string;

  @ApiProperty({
    example: 'country_visa_01',
    description: 'Visa service country ID',
  })
  @IsString()
  @IsNotEmpty({ message: 'Visa Service is required' })
  visa_service_country_id: string;

  @ApiPropertyOptional({ example: 'assoc_123', description: 'Associate ID' })
  @IsString()
  @IsOptional({ message: 'Associate is required' })
  associate_id?: string;

  @ApiProperty({ example: '123', description: 'Institute ID' })
  @IsString()
  @IsNotEmpty({ message: 'Institute is required' })
  institute_id: string;

  @ApiProperty({
    type: [String],
    example: ['IN', 'AU'],
    description: 'Client originating countries',
  })
  @IsArray()
  @ArrayMinSize(1, { message: 'At least one country required' })
  client_from_countries: string[];

  @ApiPropertyOptional({
    type: [Object],
    description: 'Optional general contract file(s)',
  })
  @IsOptional()
  @IsArray()
  attachment_file?: any[];

  @ApiProperty({
    example: '1',
    description: 'Student condition flag (e.g., 1 or 2)',
  })
  @IsString()
  @IsNotEmpty({ message: 'Student Condition is required' })
  student_condition: string;

  @ApiProperty({
    example: '2',
    description: 'Campus condition flag (if 2, applicable_campuses required)',
  })
  @IsString()
  @IsNotEmpty({ message: 'Campus Condition is required' })
  campus_condition: string;

  @ApiProperty({
    example: '2',
    description:
      'Study level condition flag (if 2, applicable_study_levels required)',
  })
  @IsString()
  @IsNotEmpty({ message: 'Study Level Condition is required' })
  study_level_condition: string;

  @ApiProperty({
    example: '1',
    description: 'Course condition flag (if 2, applicable_courses required)',
  })
  @IsString()
  @IsNotEmpty({ message: 'Course Condition is required' })
  course_condition: string;

  @ApiProperty({
    example: 'Students must maintain 70% attendance',
    description: 'Important notes or conditions',
  })
  @IsString()
  @IsNotEmpty({ message: 'Important Conditions / Notes is required' })
  notes: string;

  @ApiProperty({ example: 'USD', description: 'Currency code' })
  @IsString()
  @IsNotEmpty({ message: 'Currency is required' })
  currency: string;

  @ApiProperty({
    type: [ApplicableSetDto],
    description: 'List of applicable sets with conditions',
  })
  @IsArray()
  @ArrayMinSize(1, { message: 'At least one applicable set is required' })
  @ValidateNested({ each: true })
  @Type(() => ApplicableSetDto)
  applicable_sets: ApplicableSetDto[];
}
