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

export class GastoCabeceraDto {
  @ApiPropertyOptional({ description: 'ID del proveedor (opcional)' })
  @IsOptional()
  @IsUUID()
  proveedor_id?: string;

  @ApiPropertyOptional({ description: 'ID de sucursal' })
  @IsOptional()
  @IsUUID()
  sucursal_id?: string;

  @ApiPropertyOptional({ description: 'ID de moneda' })
  @IsOptional()
  @IsUUID()
  moneda_id?: string;

  @ApiPropertyOptional({ description: 'ID de requisición vinculada' })
  @IsOptional()
  @IsUUID()
  requisicion_id?: string;

  @ApiPropertyOptional({ description: 'RUC del proveedor' })
  @IsOptional()
  @IsString()
  ruc?: string;

  @ApiPropertyOptional({ description: 'Timbrado del proveedor' })
  @IsOptional()
  @IsString()
  timbrado?: string;

  @ApiPropertyOptional({ description: 'Establecimiento (001)' })
  @IsOptional()
  @IsString()
  establecimiento?: string;

  @ApiPropertyOptional({ description: 'Punto de expedición (001)' })
  @IsOptional()
  @IsString()
  punto_expedicion?: string;

  @ApiPropertyOptional({ description: 'Número de factura (0000001)' })
  @IsOptional()
  @IsString()
  numero_factura?: string;

  @ApiPropertyOptional({ description: 'Fecha de emisión (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  fecha_emision?: string;

  @ApiPropertyOptional({ description: 'Fecha vencimiento timbrado' })
  @IsOptional()
  @IsDateString()
  fecha_vencimiento_timbrado?: string;

  @ApiPropertyOptional({
    description: 'Forma de pago. ANTICIPO se usa para gastos rendidos con anticipo previo.',
    enum: ['CONTADO', 'CREDITO', 'TRANSFERENCIA', 'ANTICIPO'],
  })
  @IsOptional()
  @IsIn(['CONTADO', 'CREDITO', 'TRANSFERENCIA', 'ANTICIPO'])
  forma_pago?: 'CONTADO' | 'CREDITO' | 'TRANSFERENCIA' | 'ANTICIPO';

  @ApiPropertyOptional({
    description:
      'Comprobante preimpreso (talonario físico). Si es false, el documento es electrónico y ' +
      'ya está declarado en SIFEN/Marangatu, por lo que no se incluye en el Libro IVA Compras.',
    default: true,
  })
  @IsOptional()
  @IsBoolean()
  es_preimpreso?: boolean;

  @ApiPropertyOptional({
    description: 'ID de rendición de viáticos a la que pertenece este gasto (docs/plan-rendicion-viaticos.md)',
  })
  @IsOptional()
  @IsUUID()
  rendicion_viatico_id?: string;

  @ApiPropertyOptional({
    description:
      'ID del embarque de importación al que se imputa este gasto. Genera su componente de costo y entra al prorrateo del embarque.',
  })
  @IsOptional()
  @IsUUID()
  embarque_id?: string;

  @ApiPropertyOptional({
    description:
      'Concepto de costo de importación para el componente. Requerido si se envía embarque_id.',
  })
  @IsOptional()
  @IsUUID()
  concepto_costo_id?: string;

  @ApiPropertyOptional({
    description:
      'ID de un componente de costo ya cargado en la importación. Si se envía, el gasto toma ese componente en vez de crear uno nuevo (regularización de costos cargados a mano).',
  })
  @IsOptional()
  @IsUUID()
  convertir_componente_id?: string;

  @ApiPropertyOptional({ description: 'Cotización (si moneda no es PYG)' })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 6 })
  @Min(0)
  cotizacion?: number;

  @ApiPropertyOptional({ description: 'Descripción/observaciones del gasto' })
  @IsOptional()
  @IsString()
  descripcion?: string;

  @ApiPropertyOptional({
    description:
      'Medio de pago (Tesorería). Requerido cuando el gasto paga de contado/transferencia y no se difiere a Orden de Pago.',
  })
  @IsOptional()
  @IsUUID()
  medio_pago_id?: string;

  @ApiPropertyOptional({
    description: 'Cuenta de Tesorería específica (opcional). Si no se informa, se resuelve por regla PAGO_GASTO.',
  })
  @IsOptional()
  @IsUUID()
  cuenta_tesoreria_id?: string;
}

export class GastoItemDto {
  @ApiPropertyOptional({ description: 'ID del producto (opcional)' })
  @IsOptional()
  @IsUUID()
  producto_id?: string;

  @ApiPropertyOptional({ description: 'ID del tipo de gasto (clasificación)' })
  @IsOptional()
  @IsUUID()
  tipo_gasto_id?: string;

  @ApiPropertyOptional({ description: 'ID del detalle de requisición vinculado' })
  @IsOptional()
  @IsUUID()
  requisicion_det_id?: string;

  @ApiPropertyOptional({
    description: 'Descripción del ítem (requerida si no hay producto_id)',
  })
  @IsOptional()
  @IsString()
  descripcion?: string;

  @ApiProperty({ description: 'Cantidad' })
  @IsNumber({ maxDecimalPlaces: 4 })
  @Min(0.0001)
  cantidad: number;

  @ApiProperty({ description: 'Precio unitario (IVA incluido)' })
  @IsNumber({ maxDecimalPlaces: 4 })
  @Min(0)
  precio_unitario: number;

  @ApiPropertyOptional({
    description: 'Porcentaje de IVA: 0 (exento), 5 o 10',
    default: 10,
  })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  porcentaje_iva?: number;
}

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

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