import { PaymentProvider } from '@prisma/client';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsEmail, IsEnum, IsInt, IsObject, IsOptional, IsPhoneNumber, IsString, IsUrl, Min, MinLength } from 'class-validator';
import { ESTATE_ID_EXAMPLE } from '../../common/swagger-docs';

export class EstateAdminLeadSignupDto {
  @ApiProperty({ example: 'GreenPark Estate', description: 'Estate name submitted by the prospective estate admin.' })
  @IsString()
  @MinLength(2)
  estateName!: string;

  @ApiProperty({ example: 'Lagos, Nigeria', description: 'Estate location for super-admin review.' })
  @IsString()
  location!: string;

  @ApiProperty({ example: 120, description: 'Number of units/houses/residents expected in the estate.' })
  @IsInt()
  @Min(1)
  unitCount!: number;

  @ApiProperty({ example: 'Residential gated community', description: 'Estate type or category.' })
  @IsString()
  estateType!: string;

  @ApiProperty({ example: 'Ade Okafor', description: 'Prospective estate admin full name.' })
  @IsString()
  @MinLength(2)
  adminName!: string;

  @ApiProperty({ example: '+2348000000990', description: 'Prospective estate admin login phone number.' })
  @IsPhoneNumber()
  adminPhone!: string;

  @ApiPropertyOptional({ example: 'estate.admin@example.com', description: 'Prospective estate admin email for payment checkout receipts.' })
  @IsOptional()
  @IsEmail()
  adminEmail?: string;

  @ApiPropertyOptional({ example: { source: 'website' }, description: 'Optional lead metadata.' })
  @IsOptional()
  @IsObject()
  metadata?: Record<string, unknown>;

  @ApiPropertyOptional({ example: 'Lekki Phase 1', description: 'Estate/community location details for demo qualification.' })
  @IsOptional()
  @IsString()
  estateLocation?: string;

  @ApiPropertyOptional({ example: 3, description: 'Number of gates the estate operates.' })
  @IsOptional()
  @IsInt()
  @Min(1)
  gateCount?: number;

  @ApiPropertyOptional({ example: 12, description: 'Number of security personnel.' })
  @IsOptional()
  @IsInt()
  @Min(0)
  securityPersonnelCount?: number;

  @ApiPropertyOptional({ example: 'Phone calls to gate guards', description: 'Current visitor entry process.' })
  @IsOptional()
  @IsString()
  currentVisitorEntryProcess?: string;

  @ApiPropertyOptional({ example: 'External Security Ltd', description: 'External gate management company if applicable.' })
  @IsOptional()
  @IsString()
  externalSecurityCompany?: string;

  @ApiPropertyOptional({ example: 'Traffic logs, visitor analytics, payment workflow', description: 'Management challenges to test in demo.' })
  @IsOptional()
  @IsString()
  managementChallenges?: string;

  @ApiPropertyOptional({ example: 'NGN 500,000 monthly', description: 'Estate budget for GateWise solution.' })
  @IsOptional()
  @IsString()
  gateWiseBudget?: string;

  @ApiPropertyOptional({ example: 'otp-email-token', description: 'Email verification token/code from the demo registration flow.' })
  @IsOptional()
  @IsString()
  emailVerificationToken?: string;

  @ApiPropertyOptional({ example: 'otp-phone-token', description: 'Phone verification token/code from the demo registration flow.' })
  @IsOptional()
  @IsString()
  phoneVerificationToken?: string;
}

export class SelectSubscriptionPlanDto {
  @ApiProperty({ example: '+2348000000990', description: 'Phone number used during estate admin signup.' })
  @IsPhoneNumber()
  adminPhone!: string;

  @ApiProperty({ example: 'SECURE', description: 'Subscription plan code: STARTER, SECURE, LUXURY, BUSINESS, or future ENTERPRISE.' })
  @IsString()
  planCode!: string;

  @ApiProperty({ enum: PaymentProvider, example: PaymentProvider.FLUTTERWAVE, description: 'Payment provider selected for checkout.' })
  @IsEnum(PaymentProvider)
  paymentProvider!: PaymentProvider;
}

export class RecordEstatePaymentDto {
  @ApiProperty({ example: '+2348000000990', description: 'Phone number used during estate admin signup.' })
  @IsPhoneNumber()
  adminPhone!: string;

  @ApiPropertyOptional({ example: 'SECURE', description: 'Plan code if not already selected.' })
  @IsOptional()
  @IsString()
  planCode?: string;

  @ApiPropertyOptional({ enum: PaymentProvider, example: PaymentProvider.FLUTTERWAVE, description: 'Provider if not already selected.' })
  @IsOptional()
  @IsEnum(PaymentProvider)
  paymentProvider?: PaymentProvider;

  @ApiProperty({ example: 'MANUAL-TRANSFER-001', description: 'Manual transfer or non-hosted checkout reference.' })
  @IsString()
  reference!: string;

  @ApiPropertyOptional({ example: 50000000, description: 'Amount in kobo. Optional for custom pricing.' })
  @IsOptional()
  @IsInt()
  @Min(0)
  amountKobo?: number;

  @ApiPropertyOptional({ example: { channel: 'card' }, description: 'Gateway response or manual payment metadata.' })
  @IsOptional()
  @IsObject()
  metadata?: Record<string, unknown>;
}

export class InitializeEstatePaymentDto {
  @ApiProperty({ example: '+2348000000990', description: 'Phone number used during estate admin signup.' })
  @IsPhoneNumber()
  adminPhone!: string;

  @ApiProperty({ example: 'estate.admin@example.com', description: 'Customer email required by hosted payment checkouts.' })
  @IsEmail()
  customerEmail!: string;

  @ApiPropertyOptional({ example: 'Ade Okafor', description: 'Customer name for checkout. Defaults to estate admin name when omitted.' })
  @IsOptional()
  @IsString()
  customerName?: string;

  @ApiPropertyOptional({ example: 'SECURE', description: 'Plan code if not already selected.' })
  @IsOptional()
  @IsString()
  planCode?: string;

  @ApiPropertyOptional({ enum: PaymentProvider, example: PaymentProvider.FLUTTERWAVE, description: 'Provider if not already selected.' })
  @IsOptional()
  @IsEnum(PaymentProvider)
  paymentProvider?: PaymentProvider;

  @ApiPropertyOptional({ example: 50000000, description: 'Amount in kobo. Required for custom-priced plans.' })
  @IsOptional()
  @IsInt()
  @Min(0)
  amountKobo?: number;

  @ApiPropertyOptional({ example: 'https://app.example.com/billing/return', description: 'Optional client return URL to store with payment metadata.' })
  @IsOptional()
  @IsUrl({ require_tld: false })
  returnUrl?: string;

  @ApiPropertyOptional({ example: { channel: 'card' }, description: 'Additional metadata sent to the gateway and stored locally.' })
  @IsOptional()
  @IsObject()
  metadata?: Record<string, unknown>;
}

export class EstateIdParamDto {
  @ApiProperty({ example: ESTATE_ID_EXAMPLE })
  estateId!: string;
}
