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

export class RequisicionAprobacionConfigItemDto {
  @ApiProperty({ enum: ['compra', 'gasto'] })
  @IsString()
  @IsIn(['compra', 'gasto'])
  origen_tipo: 'compra' | 'gasto';

  @ApiProperty({ description: 'Nivel secuencial de aprobación (1..N)' })
  @IsInt()
  @Min(1)
  nivel: number;

  @ApiProperty({ description: 'Perfil requerido para aprobar el nivel' })
  @IsUUID()
  @IsNotEmpty()
  perfil_id: string;

  @ApiPropertyOptional({ description: 'Monto mínimo aplicable', default: 0 })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  monto_desde?: number;

  @ApiPropertyOptional({ description: 'Monto máximo aplicable (null = sin tope)' })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  monto_hasta?: number | null;

  @ApiPropertyOptional({ default: true })
  @IsOptional()
  activo?: boolean;
}

export class UpsertRequisicionAprobacionConfigDto {
  @ApiProperty({ type: [RequisicionAprobacionConfigItemDto] })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => RequisicionAprobacionConfigItemDto)
  items: RequisicionAprobacionConfigItemDto[];
}

export class RequisicionPresupuestoItemDto {
  @ApiProperty()
  @IsUUID()
  periodo_id: string;

  @ApiProperty()
  @IsUUID()
  centro_costo_id: string;

  @ApiProperty({ enum: ['compra', 'gasto'] })
  @IsString()
  @IsIn(['compra', 'gasto'])
  origen_tipo: 'compra' | 'gasto';

  @ApiProperty({ description: 'Monto asignado al período y centro de costo' })
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  monto_asignado: number;
}

export class UpsertRequisicionPresupuestoDto {
  @ApiProperty({ type: [RequisicionPresupuestoItemDto] })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => RequisicionPresupuestoItemDto)
  items: RequisicionPresupuestoItemDto[];
}

export class AprobarRequisicionDto {
  @ApiPropertyOptional({ description: 'Comentario de aprobación' })
  @IsOptional()
  @IsString()
  comentario?: string;
}

export class RechazarRequisicionDto {
  @ApiPropertyOptional({ description: 'Motivo de rechazo' })
  @IsOptional()
  @IsString()
  motivo?: string;
}

export class CancelarRequisicionDto {
  @ApiPropertyOptional({ description: 'Motivo de cancelación' })
  @IsOptional()
  @IsString()
  motivo?: string;
}

export class GenerarDesdeRequisicionOrdenCompraDto {
  @ApiProperty()
  @IsUUID()
  proveedor_id: string;

  @ApiProperty()
  @IsUUID()
  sucursal_id: string;

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

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

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

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

export class GenerarOcDistribuidaItemDto {
  @ApiProperty({ description: 'ID de la línea de la requisición' })
  @IsUUID()
  requisicion_det_id: string;

  @ApiPropertyOptional({
    description: 'Centro de costo de la línea (obligatorio si CONTABILIDAD está habilitado)',
  })
  @IsOptional()
  @IsUUID()
  centro_costo_id?: string;

  @ApiProperty({ description: 'Proveedor asignado a esta línea' })
  @IsUUID()
  proveedor_id: string;

  @ApiPropertyOptional({ description: 'Cantidad a generar (default: pendiente de la línea)' })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 4 })
  @Min(0.0001)
  cantidad?: number;

  @ApiPropertyOptional({ description: 'Costo unitario para esta línea en la OC', default: 0 })
  @IsOptional()
  @IsNumber({ maxDecimalPlaces: 4 })
  @Min(0)
  precio_unitario?: number;

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

export class GenerarOrdenesCompraDistribuidasDto {
  @ApiProperty({ description: 'Sucursal de las OCs a generar' })
  @IsUUID()
  sucursal_id: string;

  @ApiProperty({
    type: [GenerarOcDistribuidaItemDto],
    description: 'Asignaciones de líneas de requisición a proveedores',
  })
  @IsArray()
  @ArrayMinSize(1)
  @ValidateNested({ each: true })
  @Type(() => GenerarOcDistribuidaItemDto)
  asignaciones: GenerarOcDistribuidaItemDto[];

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

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

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

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

export class GenerarDesdeRequisicionGastoDto {
  @ApiProperty()
  @IsUUID()
  proveedor_id: string;

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

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

  @ApiPropertyOptional({ enum: ['CONTADO', 'CREDITO', 'TRANSFERENCIA'], default: 'CONTADO' })
  @IsOptional()
  @IsString()
  @IsIn(['CONTADO', 'CREDITO', 'TRANSFERENCIA'])
  forma_pago?: 'CONTADO' | 'CREDITO' | 'TRANSFERENCIA';

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

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