import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
  IsArray,
  IsIn,
  IsNotEmpty,
  IsNumber,
  IsOptional,
  IsString,
  IsUUID,
  Length,
  Max,
  Min,
  ValidateNested,
} from 'class-validator';
import { DocumentosAsociadosDto } from 'src/common/dto/documento-asociado.dto';

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

  @ApiProperty({ example: '41a49136-e1ac-4bbf-88c8-3d12674ee4e8' })
  @IsUUID()
  @IsNotEmpty({ message: 'Tipo impuesto es obligatorio' })
  tipo_impuesto_id: string;

  @ApiProperty({ example: '9c131c09-bc75-4cf0-b79b-1c28e498564c' })
  @IsUUID()
  @IsNotEmpty({ message: 'Moneda es obligatoria' })
  moneda_id: string;

  @ApiProperty({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsNotEmpty({ message: 'Motivo de emisión es obligatorio' })
  motivo_emision_id: string;

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

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

  @ApiProperty({ example: 'cd88ac6a-2b0e-41bc-afd9-24b594cb8daf' })
  @IsUUID()
  @IsNotEmpty({ message: 'Numeración es obligatoria' })
  numeracion_id: string;

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

  @ApiPropertyOptional({ example: 'electronico', description: 'Tipo de documento: electronico o impreso' })
  @IsOptional()
  @IsIn(['electronico', 'impreso'], { message: 'tipo_documento debe ser electronico o impreso' })
  tipo_documento?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 3000, { message: 'Dinfoemi debe tener entre 1 y 3000 caracteres' })
  dinfoemi?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Length(1, 3000, { message: 'Dinfofisc debe tener entre 1 y 3000 caracteres' })
  dinfofisc?: string;

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

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID('all', { message: 'cliente_direccion_id debe ser un UUID válido' })
  cliente_direccion_id?: string;

  @ApiProperty({ example: '2025-11-12 00:00:00' })
  @IsNotEmpty({ message: 'Fecha de emisión es obligatoria' })
  @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()
  dticam?: number;

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

  @ApiPropertyOptional({ type: DocumentosAsociadosDto })
  @ValidateNested()
  @Type(() => DocumentosAsociadosDto)
  documentos_asociados: DocumentosAsociadosDto;

  @ApiPropertyOptional({
    description: 'Modo de aplicación de la NC en recibos multi-factura. ESTRICTO: solo aplicable a su factura origen. FLEXIBLE: aplicable a cualquier factura del cliente. Si se omite, usa el default de la empresa.',
    enum: ['ESTRICTO', 'FLEXIBLE'],
    example: 'ESTRICTO',
  })
  @IsOptional()
  @IsIn(['ESTRICTO', 'FLEXIBLE'], { message: 'rec_modo_aplicacion debe ser ESTRICTO o FLEXIBLE' })
  rec_modo_aplicacion?: 'ESTRICTO' | 'FLEXIBLE';
}

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

  @ApiProperty({ example: 'UNI' })
  @IsNotEmpty({ message: 'Unidad de medida es obligatoria' })
  @IsString()
  @Length(1, 5, { message: 'Unidad de medida debe tener entre 1 y 5 caracteres' })
  unidad_medida: string;

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

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

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

  @ApiProperty({ example: 10000 })
  @IsNotEmpty({ message: 'Total bruto es obligatorio' })
  @IsNumber()
  total_bruto: number;

  @ApiProperty({ example: 10000 })
  @IsNotEmpty({ message: 'Total operación es obligatorio' })
  @IsNumber()
  total_operacion: number;

  @ApiPropertyOptional({ example: 10000 })
  @IsOptional()
  @IsNumber()
  total_gs?: number;

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

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

  @ApiProperty({ example: 100 })
  @IsNotEmpty({ message: 'Proporción de IVA es obligatorio' })
  @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: 909 })
  @IsNotEmpty({ message: 'Base gravada es obligatorio' })
  @IsNumber()
  base_gravada: number;

  @ApiProperty({ example: 91 })
  @IsNotEmpty({ message: 'Liquidación IVA es obligatorio' })
  @IsNumber()
  liquidacion_iva: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  descuento?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  porcentaje_descuento?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  base_gravada_exenta?: number;

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

  @ApiPropertyOptional()
  @IsOptional()
  @Length(3, 3, { message: 'País de origen debe tener 3 caracteres' })
  pais_origen?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsNumber()
  tipo_cambio_item?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @IsNumber()
  item?: number;
}

export class NotaCreditoSubtotalDto {
  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  subtotal_exento?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  subtotal_exonerado?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  subtotal_5?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  subtotal_10?: number;

  @ApiProperty({ example: 10000 })
  @IsNotEmpty({ message: 'Total operación es obligatorio' })
  @IsNumber()
  total_operacion: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total descuento es obligatorio' })
  @IsNumber()
  total_descuento: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total descuento global item es obligatorio' })
  @IsNumber()
  total_descuento_global_item: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total anticipo item es obligatorio' })
  @IsNumber()
  total_anticipo_item: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total anticipo global es obligatorio' })
  @IsNumber()
  total_anticipo_global: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Porcentaje descuento total es obligatorio' })
  @IsNumber()
  porcentaje_descuento_total: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total anticipo es obligatorio' })
  @IsNumber()
  total_anticipo: number;

  @ApiProperty({ example: 0 })
  @IsNotEmpty({ message: 'Total redondeo es obligatorio' })
  @IsNumber()
  total_redondeo: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  total_comision?: number;

  @ApiProperty({ example: 10000 })
  @IsNotEmpty({ message: 'Total general operación es obligatorio' })
  @IsNumber()
  total_general_operacion: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  liquidacion_iva_5?: number;

  @ApiPropertyOptional({ example: 909 })
  @IsOptional()
  @IsNumber()
  liquidacion_iva_10?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  liquidacion_redondeo_5?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  liquidacion_redondeo_10?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  liquidacion_iva_comision?: number;

  @ApiPropertyOptional({ example: 909 })
  @IsOptional()
  @IsNumber()
  total_iva?: number;

  @ApiPropertyOptional({ example: 0 })
  @IsOptional()
  @IsNumber()
  total_base_gravada_5?: number;

  @ApiPropertyOptional({ example: 9091 })
  @IsOptional()
  @IsNumber()
  total_base_gravada_10?: number;

  @ApiPropertyOptional({ example: 9091 })
  @IsOptional()
  @IsNumber()
  total_base_gravada?: number;

  @ApiPropertyOptional({ example: 10000 })
  @IsOptional()
  @IsNumber()
  total_gs?: number;
}

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

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

  @ApiProperty({ type: NotaCreditoSubtotalDto })
  @ValidateNested()
  @Type(() => NotaCreditoSubtotalDto)
  subtotal: NotaCreditoSubtotalDto;
}
