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
  CAC_BANK = "CAC_BANK", // Djibouti (OTP debit)
  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;
  @ApiPropertyOptional({
    description:
      "Payer account / mobile number. Required for OTP-debit methods (CAC_BANK) — " +
      "the bank sends the OTP to this number.",
    example: "77112233",
  })
  @IsOptional()
  @IsString()
  payerAccount?: string;
}

export class ConfirmOtpDto {
  @ApiProperty({
    description: "One-time password the payer received by SMS (e.g. CAC Bank).",
    example: "4530",
  })
  @IsString()
  otp: string;
}

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;
  @ApiPropertyOptional({
    type: "object",
    additionalProperties: true,
    description:
      "Raw provider payload (initiation response merged with the latest status query) for inspection/debugging. Provider-specific shape; never trusted for state.",
  })
  providerResponse?: Record<string, unknown>;
}

export class BookingAmountResponseDto {
  @ApiProperty({ example: 'booking-uuid' }) booking_id: string;
  @ApiProperty({ example: 'DJF', description: 'Currency of the returned amount' }) currency: string;
  @ApiProperty({ example: 162.5, description: 'Booking total converted to the requested currency (major units)' }) amount: number;
}

export class ForceConfirmDto {
  @ApiPropertyOptional({ description: 'External payment reference / transaction ID from the vendor', example: 'TXN-123456' })
  @IsOptional() @IsString() paymentReference?: string;

  @ApiPropertyOptional({ enum: PaymentMethodTypeEnum, description: 'Payment method used externally', example: 'TELEBIRR' })
  @IsOptional() @IsEnum(PaymentMethodTypeEnum) paymentMethod?: PaymentMethodTypeEnum;

  @ApiPropertyOptional({ description: 'Internal notes about why this was force-confirmed', example: 'Vendor confirmed via phone' })
  @IsOptional() @IsString() notes?: string;
}
