import { SlotFormat } from "@calcom/platform-enums";
import { ApiHideProperty, ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { Transform } from "class-transformer";
import {
  IsArray,
  IsBoolean,
  IsDateString,
  IsEnum,
  IsInt,
  IsNumber,
  IsOptional,
  IsString,
  Min,
} from "class-validator";

export class GetAvailableSlotsInput_2024_04_15 {
  @IsDateString({ strict: true })
  @ApiProperty({
    description: "Start date string starting from which to fetch slots in UTC timezone.",
    example: "2022-06-14T00:00:00.000Z",
  })
  startTime!: string;

  @IsDateString({ strict: true })
  @ApiProperty({
    description: "End date string until which to fetch slots in UTC timezone.",
    example: "2022-06-14T23:59:59.999Z",
  })
  endTime!: string;

  @Transform(({ value }: { value: string }) => value && parseInt(value))
  @IsNumber()
  @IsOptional()
  @ApiPropertyOptional({ description: "Event Type ID for which slots are being fetched.", example: 100 })
  eventTypeId?: number;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional({
    description:
      "Slug of the event type for which slots are being fetched. If event slug is provided then username must be provided too as query parameter `usernameList[]=username`",
  })
  eventTypeSlug?: string;

  @IsArray()
  @IsString({ each: true })
  @IsOptional()
  @ApiPropertyOptional({
    type: [String],
    description:
      "Only if eventTypeSlug is provided or for dynamic events - list of usernames for which slots are being fetched.",
    example: "usernameList[]=bob",
  })
  usernameList?: string[];

  @IsBoolean()
  @IsOptional()
  @ApiPropertyOptional()
  debug?: boolean;

  @Transform(({ value }: { value: string }) => value && parseInt(value))
  @IsNumber()
  @IsOptional()
  @Min(1, { message: "Duration must be a positive number" })
  @ApiPropertyOptional({ description: "Only for dynamic events - length of returned slots." })
  duration?: number;

  @IsOptional()
  @IsString()
  @ApiPropertyOptional({ type: String, nullable: true })
  rescheduleUid?: string | null;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional()
  timeZone?: string;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional({ description: "Organization slug." })
  orgSlug?: string;

  @IsString()
  @IsEnum(SlotFormat, {
    message: "slotFormat must be either 'range' or 'time'",
  })
  @Transform(({ value }) => {
    if (!value) return undefined;
    return value.toLowerCase();
  })
  @IsOptional()
  @ApiPropertyOptional({
    description: "Format of slot times in response. Use 'range' to get start and end times.",
    example: "range",
    enum: SlotFormat,
  })
  slotFormat?: SlotFormat;

  @Transform(({ value }) => value && value.toLowerCase() === "true")
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  skipContactOwner?: boolean;

  @Transform(({ value }) => value && value.toLowerCase() === "true")
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  shouldServeCache?: boolean;

  @IsOptional()
  @Transform(({ value }) => {
    if (Array.isArray(value)) {
      return value.map((s: string) => parseInt(s));
    }
    return value;
  })
  @IsArray()
  @IsNumber({}, { each: true })
  @ApiHideProperty()
  routedTeamMemberIds?: number[];

  @IsString()
  @IsOptional()
  @ApiPropertyOptional()
  teamMemberEmail?: string;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional()
  @ApiHideProperty()
  embedConnectVersion?: string;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional()
  @ApiHideProperty()
  email?: string | null;

  @Transform(({ value }) => value && value.toLowerCase() === "true")
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  _isDryRun?: boolean;

  @Transform(({ value }) => value && value.toLowerCase() === "true")
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  _bypassCalendarBusyTimes?: boolean;

  @Transform(({ value }) => value && value.toLowerCase() === "true")
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  _silentCalendarFailures?: boolean;

  @Transform(({ value }) => (value ? value.toLowerCase() === "true" : false))
  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  isTeamEvent?: boolean;

  @Transform(({ value }: { value: string }) => value && parseInt(value))
  @IsNumber()
  @IsOptional()
  @ApiHideProperty()
  teamId?: number;

  @Transform(({ value }) => {
    if (typeof value === "string") {
      return value.split(",").map((id: string) => parseInt(id.trim(), 10));
    }
    if (Array.isArray(value)) {
      return value.map((id) => (typeof id === "string" ? parseInt(id, 10) : id));
    }
    return value;
  })
  @IsArray()
  @IsNumber({}, { each: true })
  @IsOptional()
  /* @ApiPropertyOptional({
    type: [Number],
    description:
      "For round robin event types, filter available slots to only consider the specified subset of host user IDs. This allows you to get availability for specific hosts within a round robin event type.",
    example: [1, 2, 3],
  }) */
  @ApiHideProperty()
  rrHostSubsetIds?: number[];
}

export class RemoveSelectedSlotInput_2024_04_15 {
  @IsString()
  @IsOptional()
  @ApiProperty({
    description: "Unique identifier for the slot to be removed.",
    example: "e2a7bcf9-cc7b-40a0-80d3-657d391775a6",
    required: true,
  })
  uid?: string;
}

export class ReserveSlotInput_2024_04_15 {
  @IsInt()
  @ApiProperty({ description: "Event Type ID for which timeslot is being reserved.", example: 100 })
  eventTypeId!: number;

  @IsDateString()
  @ApiProperty({
    description: "Start date of the slot in UTC timezone.",
    example: "2022-06-14T00:00:00.000Z",
  })
  slotUtcStartDate!: string;

  @IsDateString()
  @ApiProperty({ description: "End date of the slot in UTC timezone.", example: "2022-06-14T00:30:00.000Z" })
  slotUtcEndDate!: string;

  @IsString()
  @IsOptional()
  @ApiPropertyOptional({
    description: "Optional but only for events with seats. Used to retrieve booking of a seated event.",
  })
  bookingUid?: string;

  @IsBoolean()
  @IsOptional()
  @ApiHideProperty()
  _isDryRun?: boolean;
}
