import { IsString, IsDateString, IsInt, IsOptional, IsEnum, IsArray, ValidateNested, IsObject, Min } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { TripStatus, StopStatus, PassengerCategory } from '@prisma/client';

export class PlannedStopTimeDto {
  @ApiProperty({ example: 1, description: 'Route stop sequence number this timing applies to' }) @IsInt() @Min(1) sequence: number;
  @ApiPropertyOptional({ example: '2026-06-15T09:30:00Z', description: 'Planned arrival at this stop (omit for first stop)' }) @IsOptional() @IsDateString() plannedArrivalAt?: string;
  @ApiPropertyOptional({ example: '2026-06-15T09:45:00Z', description: 'Planned departure from this stop (omit for last stop)' }) @IsOptional() @IsDateString() plannedDepartureAt?: string;
}

export class CreateScheduleDto {
  @ApiProperty({ example: 'train-uuid', description: 'Train UUID' }) @IsString() trainId: string;

  @ApiProperty({ example: 'route-uuid', description: 'Route UUID — stops are copied from the route template. Origin and destination are derived from the first and last route stop.' })
  @IsString() routeId: string;

  @ApiProperty({ example: '2026-06-15T08:00:00Z', description: 'Scheduled departure from the first stop (origin)' }) @IsDateString() departureAt: string;
  @ApiProperty({ example: '2026-06-15T20:00:00Z', description: 'Scheduled arrival at the last stop (destination)' }) @IsDateString() arrivalAt: string;

  @ApiProperty({
    type: [PlannedStopTimeDto],
    description: 'Planned arrival/departure times per stop sequence. Must cover all stops defined on the route.',
    example: [
      { sequence: 1, plannedDepartureAt: '2026-06-15T08:00:00Z' },
      { sequence: 2, plannedArrivalAt: '2026-06-15T09:30:00Z', plannedDepartureAt: '2026-06-15T09:45:00Z' },
      { sequence: 3, plannedArrivalAt: '2026-06-15T11:30:00Z', plannedDepartureAt: '2026-06-15T11:45:00Z' },
      { sequence: 4, plannedArrivalAt: '2026-06-15T15:00:00Z', plannedDepartureAt: '2026-06-15T15:20:00Z' },
      { sequence: 5, plannedArrivalAt: '2026-06-15T18:00:00Z', plannedDepartureAt: '2026-06-15T18:10:00Z' },
      { sequence: 6, plannedArrivalAt: '2026-06-15T20:00:00Z' },
    ],
  })
  @IsArray() @ValidateNested({ each: true }) @Type(() => PlannedStopTimeDto)
  plannedTimes: PlannedStopTimeDto[];
}

export class UpdateScheduleDto {
  @ApiPropertyOptional({ example: '2026-06-15T08:00:00Z', description: 'Scheduled departure from the first stop (origin)' }) @IsOptional() @IsDateString() departureAt?: string;
  @ApiPropertyOptional({ example: '2026-06-15T20:00:00Z', description: 'Scheduled arrival at the last stop (destination)' }) @IsOptional() @IsDateString() arrivalAt?: string;
  @ApiPropertyOptional({ enum: TripStatus, example: TripStatus.SCHEDULED }) @IsOptional() @IsEnum(TripStatus) status?: TripStatus;
  @ApiPropertyOptional({ type: Array, description: 'List of coaches to assign' }) @IsOptional() @IsArray() coaches?: Array<{ coachId: string; positionNumber: number }>;
}

export class UpdateStopTimeDto {
  @ApiPropertyOptional({ example: '2026-06-15T09:30:00Z' }) @IsOptional() @IsDateString() plannedArrivalAt?: string;
  @ApiPropertyOptional({ example: '2026-06-15T09:45:00Z' }) @IsOptional() @IsDateString() plannedDepartureAt?: string;
  @ApiPropertyOptional({ enum: StopStatus, example: StopStatus.UPCOMING }) @IsOptional() @IsEnum(StopStatus) status?: StopStatus;
}

export class CreateFareRuleDto {
  @ApiPropertyOptional({ example: 'schedule-uuid', description: 'Scope fare rule to a specific schedule' }) @IsOptional() @IsString() scheduleId?: string;
  @ApiPropertyOptional({ example: 'ADD-DJI', description: 'Scope fare rule to a route code (e.g. ADD-DJI for full route or ADD-ADM for segment)' }) @IsOptional() @IsString() route?: string;
  @ApiPropertyOptional({ example: 'Ethiopian', description: 'Scope fare rule to nationality: Ethiopian, Djiboutian, Other' }) @IsOptional() @IsString() nationality?: string;
  @ApiPropertyOptional({ enum: PassengerCategory, example: 'ADULT', description: 'Passenger category: ADULT (5+ yrs) or CHILD (<5 yrs)' }) @IsOptional() @IsEnum(PassengerCategory) passengerCategory?: PassengerCategory;
  @ApiProperty({ example: 'seat-class-uuid', description: 'Seat class UUID' }) @IsString() seatClassId: string;
  @ApiProperty({ example: 45000, description: 'Base fare in minor currency units (ETB cents)' }) @IsInt() baseFareMinor: number;
  @ApiProperty({ example: '2026-01-01T00:00:00Z' }) @IsDateString() validFrom: string;
  @ApiPropertyOptional({ example: '2026-12-31T23:59:59Z' }) @IsOptional() @IsDateString() validUntil?: string;
}

export class CreateSegmentFareRuleDto {
  @ApiProperty({ example: 'route-uuid', description: 'Route UUID' }) @IsString() routeId: string;
  @ApiProperty({ example: 1, description: 'Origin stop sequence number' }) @IsInt() @Min(1) originStopSequence: number;
  @ApiProperty({ example: 2, description: 'Destination stop sequence number' }) @IsInt() @Min(1) destinationStopSequence: number;
  @ApiProperty({ example: 'seat-class-uuid', description: 'Seat class UUID' }) @IsString() seatClassId: string;
  @ApiProperty({ example: 45000, description: 'Base fare in minor currency units (ETB cents)' }) @IsInt() baseFareMinor: number;
  @ApiPropertyOptional({ example: 'Ethiopian', description: 'Nationality scope (Ethiopian, Djiboutian, Other)' }) @IsOptional() @IsString() nationality?: string;
  @ApiPropertyOptional({ enum: PassengerCategory, example: 'ADULT', description: 'Passenger category: ADULT (5+ yrs) or CHILD (<5 yrs)' }) @IsOptional() @IsEnum(PassengerCategory) passengerCategory?: PassengerCategory;
  @ApiProperty({ example: '2026-01-01T00:00:00Z' }) @IsDateString() validFrom: string;
  @ApiPropertyOptional({ example: '2026-12-31T23:59:59Z' }) @IsOptional() @IsDateString() validUntil?: string;
}

export class ListSchedulesDto {
  @ApiPropertyOptional({ example: '2026-06-15', description: 'Filter by departure date (YYYY-MM-DD). Returns all schedules departing on this calendar day.' })
  @IsOptional() @IsDateString() date?: string;

  @ApiPropertyOptional({ example: 'route-uuid', description: 'Filter by route UUID' })
  @IsOptional() @IsString() routeId?: string;

  @ApiPropertyOptional({ example: 'train-uuid', description: 'Filter by train UUID' })
  @IsOptional() @IsString() trainId?: string;

  @ApiPropertyOptional({ enum: TripStatus, example: TripStatus.SCHEDULED, description: 'Filter by schedule status' })
  @IsOptional() @IsEnum(TripStatus) status?: TripStatus;
}

export class UpdateScheduleStatusDto {
  @ApiProperty({ enum: TripStatus, example: TripStatus.EN_ROUTE }) @IsEnum(TripStatus) status: TripStatus;
}

export class BulkCreateSchedulesDto {
  @ApiProperty({ example: 'train-uuid', description: 'Train UUID' }) @IsString() trainId: string;
  @ApiProperty({ example: 'route-uuid', description: 'Route UUID' }) @IsString() routeId: string;
  @ApiProperty({ example: '2026-06-15T08:00:00Z', description: 'Start date and time for first schedule' }) @IsDateString() startDateTime: string;
  @ApiProperty({ example: 12, description: 'Hours duration per schedule' }) @IsInt() @Min(1) durationHours: number;
  @ApiProperty({ example: 2, description: 'Repeat every X days' }) @IsInt() @Min(1) repeatEveryDays: number;
  @ApiProperty({ example: 30, description: 'Generate schedules for the next Y days' }) @IsInt() @Min(1) forNextDays: number;
  @ApiPropertyOptional({ type: [PlannedStopTimeDto], description: 'Optional custom planned times per stop. If not provided, will auto-generate.' })
  @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => PlannedStopTimeDto)
  plannedTimes?: PlannedStopTimeDto[];

  @ApiPropertyOptional({ type: [String], description: 'Optional coach UUIDs to assign to every generated schedule' })
  @IsOptional() @IsArray() @IsString({ each: true })
  coachIds?: string[];
}

export class BulkSchedulesResponseDto {
  @ApiProperty() schedulesCreated: number;
  @ApiProperty() errors: string[];
  @ApiProperty() scheduleIds: string[];
}
