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

export class FacturaCabAutoDto {
  @ApiProperty({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsNotEmpty({ message: 'Cliente es obligatorio' })
  cliente_id: string;

  @ApiProperty({ example: '0ba68a57-7e52-487a-8437-6d55f801b935' })
  @IsUUID()
  @IsOptional()
  tipo_transaccion_id?: string;

  @ApiProperty({ example: '41a49136-e1ac-4bbf-88c8-3d12674ee4e8' })
  @IsUUID()
  @IsOptional()
  tipo_impuesto_id?: string;

  @ApiProperty({ example: '9c131c09-bc75-4cf0-b79b-1c28e498564c' })
  @IsUUID()
  @IsOptional()
  moneda_id?: string;

  @ApiProperty({ example: 'eeec7470-e500-499b-ae44-704b929a1d37' })
  @IsUUID()
  @IsOptional()
  indicador_presencia_id?: string;

  @ApiProperty({ example: '6b6b4e89-85a4-4b01-9b90-2da0ff11b955' })
  @IsUUID()
  @IsOptional()
  condicion_operacion_id?: string;

  @ApiProperty({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsOptional()
  tipo_operacion_id?: string;

  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsOptional()
  sucripcion_id?: string;

  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsOptional()
  @Length(1, 3000, { message: 'Dinfoemi debe tener entre 1 y 3000 caracteres' })
  dinfoemi?: string;

  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsOptional()
  @Length(1, 3000, { message: 'Dinfofisc debe tener entre 1 y 3000 caracteres' })
  dinfofisc?: string;

  @ApiProperty({ example: '001' })
  @IsOptional()
  @Length(1, 3, { message: 'Establecimiento debe tener entre 1 y 3 caracteres' })
  dest?: string;

  @ApiProperty({ example: '001' })
  @IsOptional()
  @Length(1, 3, { message: 'Punto de expedición debe tener entre 1 y 3 caracteres' })
  dpunexp?: string;

  @ApiProperty({ example: '0000001' })
  @IsOptional()
  @Length(1, 7, { message: 'Número de documento debe tener entre 1 y 7 caracteres' })
  dnumdoc: string;

  @ApiPropertyOptional({ example: 'AA' })
  @IsOptional()
  @Length(1, 2, { message: 'Serie debe tener entre 1 y 3 caracteres' })
  dserienum?: string;

  @ApiProperty({ example: '2025-11-12 00:00:00' })
  @IsOptional()
  @Length(1, 19, { message: 'Fecha de emisión debe tener entre 1 y 19 caracteres' })
  dfeemide?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsIn(['1', '2'], { message: 'dCondTiCam debe ser 1 o 2' })
  dcondticam?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsNotEmpty({ message: 'dticam es obligatorio' })
  dticam?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @IsIn(['1', '2'], { message: 'icondant debe ser 1 o 2' })
  icondant: string;

  @ApiPropertyOptional({ example: 'AAAA-MM-DD' })
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'dfecemnr debe tener el formato AAAA-MM-DD' })
  @Length(1, 10, { message: 'dfecemnr debe tener entre 1 y 10 caracteres' })
  dfecemnr: string;

  @ApiPropertyOptional({ example: 'email@example.com' })
  @IsOptional()
  @Length(1, 80, { message: 'Email debe tener entre 1 y 80 caracteres' })
  demailadmin?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(2, 2, { message: 'Modalidad debe tener entre 2 y 2 caracteres' })
  dmodcont?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(5, 5, { message: 'Entidad debe tener entre 5 y 5 caracteres' })
  dentcont?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(2, 2, { message: 'Año debe tener entre 2 y 2 caracteres' })
  danocont?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(7, 7, { message: 'Secuencia debe tener entre 7 y 7 caracteres' })
  dseccont?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'dfecodcont debe tener el formato AAAA-MM-DD' })
  @Length(1, 10, { message: 'Fecha de emisión del codigo de contratación debe tener entre 1 y 10 caracteres' })
  dfecodcont?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 15, { message: 'dciclo debe tener entre 2 y 2 caracteres' })
  dciclo?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Fecha inicio del ciclo debe tener el formato AAAA-MM-DD' })
  @Length(1, 10, { message: 'Fecha inicio del ciclo debe tener entre 1 y 10 caracteres' })
  dfecinic?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Fecha fin del ciclo debe tener el formato AAAA-MM-DD' })
  @Length(1, 10, { message: 'Fecha fin del ciclo debe tener entre 1 y 10 caracteres' })
  dfecfinc?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, { message: 'Fecha vencimiento del pago debe tener el formato AAAA-MM-DD' })
  @Length(1, 10, { message: 'Fecha vencimiento del pago debe tener entre 1 y 10 caracteres' })
  dvencpag?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 30, { message: 'Numero de contrato debe tener entre 1 y 30 caracteres' })
  dcontrato?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 15, { message: 'Saldo anterior debe tener entre 1 y 15 caracteres' })
  dsalant?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 5000, { message: 'Información adicional debe tener entre 1 y 5000 caracteres' })
  dinfadic?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsIn(['1', '2'], { message: 'Condición de la operación a crédito debe ser 1 o 2' })
  icondcred?: string;

  @ApiPropertyOptional({ example: '30 dias' })
  @IsOptional()
  @IsNotEmpty({ message: 'Plazo de crédito debe estar vacío' })
  @Length(2, 15, { message: 'dplazocre debe tener entre 2 y 2 caracteres' })
  dplazocre: string;

  @ApiPropertyOptional({ example: '12' })
  @IsOptional()
  @Length(1, 3, { message: 'Cantidad de cuotas debe tener entre 1 y 3 caracteres' })
  dcuotas?: number;

  @ApiPropertyOptional()
  @IsOptional()
  dmonent?: number;
}

export class DetalleFacturaAutoDto {
  @ApiProperty({ example: '9ce06294-3e21-450c-96bc-70b3a2523a9e' })
  @IsUUID()
  @IsNotEmpty({ message: 'Producto es obligatorio' })
  producto_id: string;

  @ApiProperty({ example: 'UNI' })
  @IsOptional()
  unidad_medida?: string;

  @ApiProperty({ example: 'Producto' })
  @IsNotEmpty({ message: 'Descripción es obligatoria' })
  @Length(1, 2000, { message: 'Descripción debe tener entre 1 y 2000 caracteres' })
  descripcion: string;

  @ApiProperty({ example: '1' })
  @IsNotEmpty({ message: 'Cantidad es obligatoria' })
  cantidad: number;

  @ApiProperty({ example: '0' })
  @IsNotEmpty({ message: 'Precio unitario es obligatorio' })
  precio_unitario: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  total_bruto?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  descuento?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  porcentaje_descuento?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  descuento_global?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  total_operacion?: number;
  @ApiProperty({ example: '0' })
  @IsOptional()
  total_gs?: number;

  @ApiProperty({ example: '1' })
  @IsOptional()
  @IsIn([1, 2, 3, 4], { message: 'Afectación IVA debe ser 1, 2, 3, 4' })
  afectacion_iva?: number;

  @ApiProperty({ example: '10' })
  @IsOptional()
  @IsIn([10, 5, 0], { message: 'Porcentaje de IVA debe ser 10, 5 o 0' })
  porcentaje_iva?: number;

  @ApiProperty({ example: '100' })
  @IsOptional()
  @Min(0, { message: 'Proporción de IVA debe ser un número entre 0 y 100' })
  @Max(100, { message: 'Proporción de IVA debe ser un número entre 0 y 100' })
  proporcion_iva?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  base_gravada?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  liquidacion_iva?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  base_gravada_exenta?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 5000, { message: 'Información adicional debe tener entre 1 y 5000 caracteres' })
  info_adicional_item?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(3, 3, { message: 'Pais de origen debe tener entre 3 y 3 caracteres' })
  pais_origen?: string;
  @ApiPropertyOptional()
  @IsOptional()
  tipo_cambio_item?: number;

  @ApiPropertyOptional()
  @IsOptional()
  cdc_anticipo_item?: string;

  @ApiPropertyOptional()
  @IsOptional()
  anticipo_precio_unitario?: number;
}

export class FormaPagoAutoDto {
  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsOptional()
  @IsUUID()
  sesion_caja_id?: string;

  @ApiProperty({ example: '9044b1a1-ba0e-4803-8ff8-c3870466b46c' })
  @IsUUID()
  @IsOptional()
  medio_pago_id?: string;

  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsOptional()
  @IsUUID()
  tarjeta_id?: string;

  @ApiPropertyOptional({ example: 'Otra tarjeta' })
  @IsOptional()
  @Length(4, 20, { message: 'La descripcion de la tarjeta debe tener entre 4 y 20 caracteres' })
  tarjeta_descripcion_otro?: string;

  @ApiProperty({ example: '1cfdf379-8225-4c7e-b572-c5fa6983c846' })
  @IsUUID()
  @IsOptional()
  forma_procesamiento_pago_id?: string;

  @ApiProperty({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsOptional()
  moneda_id?: string;

  @ApiPropertyOptional({ example: '0' })
  @IsOptional()
  monto_pago?: number;

  @ApiPropertyOptional({
    example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf',
    description: 'ID de la moneda en que se realiza el pago',
  })
  @IsOptional()
  @IsUUID()
  moneda_pago_id?: string;

  @ApiPropertyOptional({ example: 100, description: 'Monto en la moneda original del pago (antes de conversión)' })
  @IsOptional()
  monto_moneda_original?: number;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(4, 60, { message: 'Razón social de la procesadora de tarjeta debe tener entre 4 y 60 caracteres' })
  razon_social_procesadora?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(3, 8, { message: 'Ruc de la procesadora de tarjeta debe tener entre 3 y 8 caracteres' })
  ruc_procesadora?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(1, 1, { message: 'Dígito verificador de la procesadora de tarjeta debe tener entre 1 y 1 caracteres' })
  dv_procesadora?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(6, 10, { message: 'Nro de autorización de la procesadora de tarjeta debe tener entre 6 y 10 caracteres' })
  nro_autorizacion_procesadora?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(4, 30, { message: 'Nombre titular de la tarjeta debe tener entre 4 y 30 caracteres' })
  nombre_titular_tarjeta?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(4, 4, { message: 'La tarjeta debe tener 4 digitos (Ultimos 4 digitos)' })
  numero_tarjeta?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(8, 8, { message: 'El cheque debe tener 8 digitos' })
  numero_cheque?: string;

  @ApiPropertyOptional({ example: '' })
  @IsOptional()
  @Length(4, 20, { message: 'Banco emisor del cheque debe tener entre 4 y 20 caracteres' })
  banco_emisor?: string;
}

export class SubtotalAutoDto {
  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Subtotal exento debe ser numérico' })
  subtotal_exento?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Subtotal exonerado debe ser numérico' })
  subtotal_exonerado?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Subtotal IVA 5% debe ser numérico' })
  subtotal_5?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total IVA 10% debe ser numérico' })
  subtotal_10?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Liquidación IVA 5% debe ser numérico' })
  liquidacion_iva_5?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Liquidación IVA 10% debe ser numérico' })
  liquidacion_iva_10?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Liquidación redondeo debe ser numérico' })
  liquidacion_redondeo_5?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Liquidación redondeo debe ser numérico' })
  liquidacion_redondeo_10?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Liquidación IVA comisión debe ser numérico' })
  liquidacion_iva_comision?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total IVA debe ser numérico' })
  total_iva?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total operación debe ser numérico' })
  total_operacion?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total descuento debe ser numérico' })
  total_descuento?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total descuento global debe ser numérico' })
  total_descuento_global_item?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total descuento particular item debe ser numérico' })
  total_descuento_particular_item?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total bruto operación debe ser numérico' })
  total_bruto_operacion?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total anticipo item debe ser numérico' })
  total_anticipo_item?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total anticipo global debe ser numérico' })
  total_anticipo_global_item?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Porcentaje de descuento total debe ser numérico' })
  porcentaje_descuento_total?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total anticipo debe ser numérico' })
  total_anticipo_operacion?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total redondeo debe ser numérico' })
  total_redondeo?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total comisión debe ser numérico' })
  total_comision?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total general operación debe ser numérico' })
  total_general_operacion?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total general operación debe ser numérico' })
  total_base_gravada_5?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total general operación debe ser numérico' })
  total_base_gravada_10?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total base gravada debe ser numérico' })
  total_base_gravada?: number;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Total gs debe ser numérico' })
  total_gs?: number;
}

export class CuotasAutoDto {
  @ApiPropertyOptional({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsOptional()
  @IsNotEmpty({ message: 'Cuenta es obligatoria' })
  cuenta_id?: string;

  @ApiProperty({ example: 'PYG' })
  @IsOptional()
  @IsString({ message: 'Moneda debe ser una cadena' })
  @Length(3, 3, { message: 'Moneda debe tener entre 3 y 3 caracteres' })
  moneda_iso?: string;

  @ApiProperty({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Monto de cuota debe ser numérico' })
  monto_cuota?: number;

  @ApiProperty({ example: '1' })
  @IsOptional()
  @IsNumber({}, { message: 'Cantidad de cuotas debe ser numérico' })
  nro_cuota?: number;

  @ApiProperty({ example: '2025-12-12' })
  @IsOptional()
  @Matches(/^\d{4}-\d{2}-\d{2}$/, {
    message: 'Fecha de vencimiento debe ser una fecha con el formato AAAA-MM-DD',
  })
  vencimiento?: string;

  @ApiPropertyOptional({ example: '0' })
  @IsOptional()
  @IsNumber({}, { message: 'Saldo pendiente debe ser numérico' })
  saldo_pendiente?: number;
}

export class CreateFacturaAutoDto {
  @ApiProperty({ type: FacturaCabAutoDto })
  @ValidateNested()
  @Type(() => FacturaCabAutoDto)
  cabecera: FacturaCabAutoDto;

  @ApiProperty({ type: [DetalleFacturaAutoDto] })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => DetalleFacturaAutoDto)
  items: DetalleFacturaAutoDto[];

  @ApiPropertyOptional({ type: [FormaPagoAutoDto] })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => FormaPagoAutoDto)
  pagos?: FormaPagoAutoDto[];

  @ApiPropertyOptional({ type: SubtotalAutoDto })
  @ValidateNested()
  @Type(() => SubtotalAutoDto)
  subtotal?: SubtotalAutoDto;

  @ApiPropertyOptional({ type: [CuotasAutoDto] })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => CuotasAutoDto)
  cuotas?: CuotasAutoDto[];
}
