import {
  IsString,
  IsEnum,
  IsOptional,
  IsIn,
  IsBoolean,
  IsInt,
} from "class-validator";
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { PaymentIntentStatus } from "@prisma/client";

export enum PaymentRegionEnum {
  ETHIOPIA = "ETHIOPIA",
  DJIBOUTI = "DJIBOUTI",
  INTERNATIONAL = "INTERNATIONAL",
  GLOBAL = "GLOBAL",
}

export enum PaymentMethodTypeEnum {
  TELEBIRR = "TELEBIRR", // Ethiopia
  CBE_BIRR = "CBE_BIRR", // Ethiopia
  EBIRR = "EBIRR", // Ethiopia
  WAAFI = "WAAFI",
  DMONEY= "DMONEY",// Djibouti
  CARD = "CARD", // International
  WALLET = "WALLET", // Internal
}

export type PaymentPlatformDto = "web" | "mobile";

export class InitiatePaymentDto {
  @ApiProperty({ example: "booking-uuid" }) @IsString() bookingId: string;
  @ApiProperty({
    enum: PaymentMethodTypeEnum,
    description:
      "Payment method: TELEBIRR/CBE_BIRR/EBIRR (Ethiopia), WAAFI (Djibouti), CARD (International), WALLET (Internal)",
    example: "TELEBIRR",
  })
  @IsEnum(PaymentMethodTypeEnum)
  method: PaymentMethodTypeEnum;
  @ApiPropertyOptional({ description: "Saved payment method ID (optional)" })
  @IsOptional()
  @IsString()
  paymentMethodId?: string;
  @ApiPropertyOptional({
    enum: ["web", "mobile"],
    default: "web",
    description: "Payment platform (web or mobile)",
  })
  @IsOptional()
  @IsIn(["web", "mobile"])
  platform?: PaymentPlatformDto;
}

export class RefundDto {
  @ApiProperty() @IsString() bookingId: string;
  @ApiPropertyOptional() @IsOptional() @IsString() reason?: string;
}

export class AddPaymentMethodDto {
  @ApiProperty({ enum: PaymentMethodTypeEnum })
  @IsEnum(PaymentMethodTypeEnum)
  type: PaymentMethodTypeEnum;
  @ApiProperty() @IsString() displayName: string;
  @ApiProperty({ enum: PaymentRegionEnum })
  @IsEnum(PaymentRegionEnum)
  region: PaymentRegionEnum;
  @ApiPropertyOptional({ example: "ETB" })
  @IsOptional()
  @IsString()
  currency?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() providerId?: string;
  @ApiPropertyOptional({ default: true })
  @IsOptional()
  @IsBoolean()
  enabled?: boolean;
  @ApiPropertyOptional({ default: 0 })
  @IsOptional()
  @IsInt()
  sortOrder?: number;
}

export class SupportedPaymentMethodDto {
  @ApiProperty({ enum: PaymentMethodTypeEnum }) type: PaymentMethodTypeEnum;
  @ApiProperty({ example: "Telebirr" }) displayName: string;
  @ApiProperty({ enum: PaymentRegionEnum }) region: PaymentRegionEnum;
  @ApiProperty({
    example: "ETB",
    description: "Settlement currency for this method",
  })
  currency: string;
  @ApiProperty({
    description: "Whether the platform currently accepts this method",
  })
  enabled: boolean;
}

export class ClientActionDto {
  @ApiProperty({ enum: ["REDIRECT", "LAUNCH_APP", "COLLECT_OTP"] })
  type: "REDIRECT" | "LAUNCH_APP" | "COLLECT_OTP";
  @ApiPropertyOptional({ description: "Set when type=REDIRECT (web flow)" })
  url?: string;
  @ApiPropertyOptional({
    description: "Set when type=LAUNCH_APP (mobile flow)",
  })
  prepayId?: string;
  @ApiPropertyOptional({
    description: "Set when type=LAUNCH_APP (mobile flow)",
  })
  receiveCode?: string;
  @ApiPropertyOptional({
    description: "Set when type=LAUNCH_APP (mobile flow)",
  })
  shortCode?: string;
  @ApiPropertyOptional({ description: "Set when type=COLLECT_OTP (e.g. CAC Bank)" })
  providerOrderId?: string;
  @ApiPropertyOptional({ description: "Set when type=COLLECT_OTP" })
  message?: string;
}

export class InitiateResponseDto {
  @ApiProperty() intentId: string;
  @ApiProperty({ enum: PaymentIntentStatus }) status: PaymentIntentStatus;
  @ApiPropertyOptional({ type: ClientActionDto })
  clientAction?: ClientActionDto;
  @ApiPropertyOptional() merchantOrderId?: string;
}

export class IntentStatusDto {
  @ApiProperty() intentId: string;
  @ApiProperty({ enum: PaymentIntentStatus }) status: PaymentIntentStatus;
  @ApiPropertyOptional({ type: ClientActionDto })
  clientAction?: ClientActionDto;
  @ApiPropertyOptional() merchantOrderId?: string;
  @ApiPropertyOptional() paidAt?: string;
  @ApiPropertyOptional() failureCode?: string;
  @ApiPropertyOptional() failureMessage?: string;
}
