import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { ArrayMinSize, IsArray, IsDateString, IsIn, IsNumber, IsOptional, IsString, IsUUID, Min, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';

// ─── Promesas de Pago ────────────────────────────────────────────────────────

export class CreatePromesaPagoDto {
  @ApiProperty({ description: 'ID de la factura' })
  @IsUUID()
  factura_cab_id: string;

  @ApiProperty({ description: 'ID del cliente' })
  @IsUUID()
  cliente_id: string;

  @ApiPropertyOptional({ description: 'ID del cobrador asignado' })
  @IsOptional()
  @IsUUID()
  cobrador_id?: string;

  @ApiPropertyOptional({ description: 'ID de la cuota específica (null = promesa general sobre la factura)' })
  @IsOptional()
  @IsUUID()
  cuota_id?: string;

  @ApiProperty({ description: 'Fecha prometida de pago (YYYY-MM-DD)' })
  @IsDateString()
  fecha_prometida: string;

  @ApiPropertyOptional({ description: 'Monto prometido' })
  @IsOptional()
  @IsNumber()
  @Min(0)
  monto_prometido?: number;

  @ApiPropertyOptional({ description: 'Notas adicionales' })
  @IsOptional()
  @IsString()
  notas?: string;

  @ApiPropertyOptional({ enum: ['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'], default: 'VERBAL' })
  @IsOptional()
  @IsIn(['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'])
  tipo_evidencia?: string;

  @ApiPropertyOptional({ enum: ['CLIENTE', 'GARANTE', 'TERCERO'], default: 'CLIENTE' })
  @IsOptional()
  @IsIn(['CLIENTE', 'GARANTE', 'TERCERO'])
  pagador_tipo?: string;

  @ApiPropertyOptional({ description: 'ID del cliente garante/tercero (si pagador_tipo != CLIENTE)' })
  @IsOptional()
  @IsUUID()
  pagador_cliente_id?: string;
}

export class PromesaFacturaAsignacionDto {
  @ApiProperty()
  @IsUUID()
  factura_cab_id: string;

  @ApiPropertyOptional({ description: 'Cuota objetivo dentro de la factura; sin cuota = la factura completa' })
  @IsOptional()
  @IsUUID()
  cuota_id?: string;

  @ApiProperty()
  @IsNumber()
  @Min(0)
  monto_asignado: number;
}

export class CreatePromesaMultiFacturaDto {
  @ApiProperty({ description: 'ID del cliente' })
  @IsUUID()
  cliente_id: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  cobrador_id?: string;

  @ApiProperty({ description: 'Facturas a las que se aplica la promesa', type: [PromesaFacturaAsignacionDto] })
  @IsArray()
  @ArrayMinSize(1)
  @ValidateNested({ each: true })
  @Type(() => PromesaFacturaAsignacionDto)
  facturas: PromesaFacturaAsignacionDto[];

  @ApiProperty({ description: 'Fecha prometida (YYYY-MM-DD)' })
  @IsDateString()
  fecha_prometida: string;

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

  @ApiPropertyOptional({ enum: ['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'], default: 'VERBAL' })
  @IsOptional()
  @IsIn(['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'])
  tipo_evidencia?: string;

  @ApiPropertyOptional({ enum: ['CLIENTE', 'GARANTE', 'TERCERO'], default: 'CLIENTE' })
  @IsOptional()
  @IsIn(['CLIENTE', 'GARANTE', 'TERCERO'])
  pagador_tipo?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  pagador_cliente_id?: string;
}

export class RenegociarPromesaDto {
  @ApiProperty({ description: 'Nueva fecha prometida (YYYY-MM-DD)' })
  @IsDateString()
  fecha_prometida: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsNumber()
  @Min(0)
  monto_prometido?: number;

  @ApiProperty({ description: 'Motivo / notas de la renegociación' })
  @IsString()
  notas: string;

  @ApiPropertyOptional({ enum: ['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'] })
  @IsOptional()
  @IsIn(['VERBAL', 'WHATSAPP', 'EMAIL', 'DOCUMENTO_FIRMADO'])
  tipo_evidencia?: string;
}

export class CancelarPromesaDto {
  @ApiProperty({ description: 'Motivo de la cancelación' })
  @IsString()
  motivo: string;
}

export class UpdatePromesaEstadoDto {
  @ApiProperty({ description: 'Nuevo estado', enum: ['cumplida', 'incumplida', 'cancelada'] })
  @IsIn(['cumplida', 'incumplida', 'cancelada'])
  estado: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  notas?: string;
}

export class QueryPromesasDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  factura_cab_id?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  cobrador_id?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  cliente_id?: string;

  @ApiPropertyOptional({ enum: ['pendiente', 'cumplida', 'cumplida_parcial', 'incumplida', 'cancelada', 'renegociada', 'todas'] })
  @IsOptional()
  @IsString()
  estado?: string;

  @ApiPropertyOptional({ description: 'Fecha desde (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  fecha_desde?: string;

  @ApiPropertyOptional({ description: 'Fecha hasta (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  fecha_hasta?: string;
}

// ─── Autorizaciones de Descuento ─────────────────────────────────────────────

export type TipoAutorizacionDescuento = 'QUITA_CAPITAL' | 'EXONERACION_INTERES';

export class CreateAutorizacionDescuentoDto {
  @ApiPropertyOptional({ description: 'ID de la factura a descontar' })
  @IsOptional()
  @IsUUID()
  factura_cab_id?: string;

  @ApiPropertyOptional({
    description:
      'ID de la cuota — obligatorio cuando tipo=EXONERACION_INTERES (la exoneración se ata a una cuota específica)',
  })
  @IsOptional()
  @IsUUID()
  factura_cuota_id?: string;

  @ApiProperty({ description: 'ID del cliente' })
  @IsUUID()
  cliente_id: string;

  @ApiProperty({ description: 'ID del cobrador que solicita' })
  @IsUUID()
  cobrador_id: string;

  @ApiPropertyOptional({
    enum: ['QUITA_CAPITAL', 'EXONERACION_INTERES'],
    default: 'QUITA_CAPITAL',
  })
  @IsOptional()
  @IsIn(['QUITA_CAPITAL', 'EXONERACION_INTERES'])
  tipo?: TipoAutorizacionDescuento;

  @ApiPropertyOptional({ description: 'Monto fijo de descuento' })
  @IsOptional()
  @IsNumber()
  @Min(0)
  descuento_monto?: number;

  @ApiPropertyOptional({ description: 'Porcentaje de descuento (0-100)' })
  @IsOptional()
  @IsNumber()
  @Min(0)
  descuento_porcentaje?: number;

  @ApiPropertyOptional({ description: 'Motivo de la solicitud de descuento' })
  @IsOptional()
  @IsString()
  motivo?: string;
}

export class CrearDescuentoAdminDto {
  @ApiPropertyOptional({ description: 'ID de la factura' })
  @IsOptional()
  @IsUUID()
  factura_cab_id?: string;

  @ApiPropertyOptional({
    description:
      'ID de la cuota — obligatorio cuando tipo=EXONERACION_INTERES',
  })
  @IsOptional()
  @IsUUID()
  factura_cuota_id?: string;

  @ApiProperty({ description: 'ID del cliente' })
  @IsUUID()
  cliente_id: string;

  @ApiPropertyOptional({ description: 'ID del cobrador al que aplica el descuento (opcional: si se omite, queda asociado solo al cliente)' })
  @IsOptional()
  @IsUUID()
  cobrador_id?: string;

  @ApiPropertyOptional({
    enum: ['QUITA_CAPITAL', 'EXONERACION_INTERES'],
    default: 'QUITA_CAPITAL',
    description:
      'QUITA_CAPITAL: descuento normal sobre capital. EXONERACION_INTERES: perdona mora de una cuota concreta.',
  })
  @IsOptional()
  @IsIn(['QUITA_CAPITAL', 'EXONERACION_INTERES'])
  tipo?: TipoAutorizacionDescuento;

  @ApiPropertyOptional({ description: 'Monto fijo de descuento en Gs.' })
  @IsOptional()
  @IsNumber()
  @Min(0)
  descuento_monto?: number;

  @ApiPropertyOptional({ description: 'Porcentaje de descuento (0-100)' })
  @IsOptional()
  @IsNumber()
  @Min(0)
  descuento_porcentaje?: number;

  @ApiPropertyOptional({ description: 'Motivo o condición del descuento' })
  @IsOptional()
  @IsString()
  motivo?: string;

  @ApiPropertyOptional({ description: 'Fecha/hora de expiración (si no se indica, expira en 30 días)' })
  @IsOptional()
  @IsDateString()
  expires_at?: string;
}

export class ResolverAutorizacionDto {
  @ApiProperty({ enum: ['aprobado', 'rechazado'] })
  @IsIn(['aprobado', 'rechazado'])
  decision: string;

  @ApiPropertyOptional({ description: 'Notas del supervisor' })
  @IsOptional()
  @IsString()
  notas_supervisor?: string;
}

export class QueryAutorizacionesDto {
  @ApiPropertyOptional({ enum: ['pendiente', 'aprobado', 'rechazado', 'expirado', 'usado', 'todos'] })
  @IsOptional()
  @IsString()
  estado?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  cobrador_id?: string;
}
