import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
  ArrayMinSize,
  IsArray,
  IsDate,
  IsIn,
  IsNumber,
  IsObject,
  IsOptional,
  IsString,
  Max,
  MaxLength,
  Min,
  MinLength,
  ValidateNested,
} from 'class-validator';

// ─── API Keys (admin) ──────────────────────────────────────────────────────

const SCOPES = ['sync', 'cobros', 'gestiones'] as const;

export class CrearApiKeyDto {
  @ApiProperty()
  @IsString()
  @MinLength(3)
  @MaxLength(120)
  nombre!: string;

  @ApiProperty({ enum: SCOPES, isArray: true, required: false })
  @IsOptional()
  @IsArray()
  @IsIn(SCOPES as unknown as string[], { each: true })
  scopes?: string[];

  @ApiProperty({ required: false, description: 'Días hasta expiración' })
  @IsOptional()
  @Type(() => Number)
  @IsNumber()
  @Min(1)
  @Max(3650)
  expira_en_dias?: number;
}

// ─── /sync — Snapshot de cartera ───────────────────────────────────────────

export class SyncDocumentoDto {
  @ApiProperty()
  @IsString()
  @MaxLength(80)
  cliente_externo_id!: string;

  @ApiProperty()
  @IsString()
  @MaxLength(255)
  cliente_nombre!: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(40)
  cliente_documento?: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(40)
  cliente_telefono?: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(120)
  cliente_email?: string;

  @ApiProperty()
  @IsString()
  @MaxLength(80)
  documento_numero!: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(40)
  documento_tipo?: string;

  @ApiProperty({ required: false, default: 'PYG' })
  @IsOptional()
  @IsString()
  @MaxLength(3)
  moneda_codigo?: string;

  @ApiProperty()
  @Type(() => Number)
  @IsNumber()
  @Min(0)
  monto_total!: number;

  @ApiProperty()
  @Type(() => Number)
  @IsNumber()
  @Min(0)
  saldo_pendiente!: number;

  @ApiProperty({ type: String, format: 'date' })
  @Type(() => Date)
  @IsDate()
  fecha_emision!: Date;

  @ApiProperty({ type: String, format: 'date', required: false })
  @IsOptional()
  @Type(() => Date)
  @IsDate()
  fecha_vencimiento?: Date;
}

export class SyncCarteraDto {
  @ApiProperty({
    enum: ['snapshot', 'delta'],
    description: 'snapshot = reemplaza todo; delta = upserts incrementales',
    default: 'delta',
  })
  @IsOptional()
  @IsIn(['snapshot', 'delta'])
  modo?: 'snapshot' | 'delta';

  @ApiProperty({ type: SyncDocumentoDto, isArray: true })
  @IsArray()
  @ArrayMinSize(1)
  @ValidateNested({ each: true })
  @Type(() => SyncDocumentoDto)
  documentos!: SyncDocumentoDto[];
}

// ─── /cobros — Notificar cobro externo ─────────────────────────────────────

export class NotificarCobroDto {
  @ApiProperty()
  @IsString()
  @MaxLength(80)
  cliente_externo_id!: string;

  @ApiProperty()
  @IsString()
  @MaxLength(80)
  documento_numero!: string;

  @ApiProperty()
  @Type(() => Number)
  @IsNumber()
  @Min(0)
  monto!: number;

  @ApiProperty({ required: false, default: 'PYG' })
  @IsOptional()
  @IsString()
  @MaxLength(3)
  moneda_codigo?: string;

  @ApiProperty({ type: String, format: 'date-time' })
  @Type(() => Date)
  @IsDate()
  fecha!: Date;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(40)
  medio_pago?: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(80)
  referencia_externa?: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsObject()
  metadata?: Record<string, unknown>;
}

// ─── /gestiones — Registrar gestión externa ────────────────────────────────

export class RegistrarGestionExternaDto {
  @ApiProperty()
  @IsString()
  @MaxLength(80)
  cliente_externo_id!: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(80)
  documento_numero?: string;

  @ApiProperty()
  @IsIn(['VISITA', 'LLAMADA', 'WHATSAPP', 'EMAIL', 'SMS', 'OTRO'])
  tipo_gestion!: string;

  @ApiProperty()
  @IsIn([
    'COBRADO_TOTAL',
    'COBRADO_PARCIAL',
    'PROMESA_PAGO',
    'NO_ATIENDE',
    'CLIENTE_AUSENTE',
    'DIRECCION_INCORRECTA',
    'CLIENTE_DISPUTA',
    'RECHAZO_PAGAR',
    'COMPROMISO_LLAMADA_POSTERIOR',
    'CLIENTE_FALLECIDO',
    'OTRO',
  ])
  resultado!: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(2000)
  observacion?: string;

  @ApiProperty({ required: false })
  @IsOptional()
  @IsString()
  @MaxLength(500)
  proxima_accion?: string;

  @ApiProperty({ required: false, type: String, format: 'date-time' })
  @IsOptional()
  @Type(() => Date)
  @IsDate()
  proxima_fecha?: Date;
}
