import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import {
  IsBoolean,
  IsDateString,
  IsIn,
  IsInt,
  IsNumber,
  IsOptional,
  IsString,
  IsUUID,
  Length,
  Max,
  Min,
} from 'class-validator';

export const LIQUIDACION_ESTADOS = ['BORRADOR', 'PRE_LIQUIDACION', 'CERRADA', 'ANULADA'] as const;
// MENSUAL, QUINCENAL ya están operativos.
// AGUINALDO: 1 por año (mes = 12), 1/12 de las remuneraciones brutas anuales (Art. 243 CT).
// VACACIONES: 1 por mes; agrupa solicitudes aprobadas con afecta_salario=true (Art. 219 CT).
export const LIQUIDACION_TIPOS = ['MENSUAL', 'QUINCENAL', 'AGUINALDO', 'VACACIONES'] as const;
export const PLANILLA_FORMATS = ['json', 'xlsx'] as const;

export class CreateLiquidacionDto {
  @ApiPropertyOptional({ enum: LIQUIDACION_TIPOS, default: 'MENSUAL' })
  @IsOptional()
  @IsString()
  @IsIn(LIQUIDACION_TIPOS as unknown as string[])
  tipo?: (typeof LIQUIDACION_TIPOS)[number];

  @ApiPropertyOptional({ description: 'Requerido si tipo = QUINCENAL: 1 (días 1-15) o 2 (días 16-fin)' })
  @IsOptional()
  @Transform(({ value }) => (value === undefined || value === null || value === '' ? undefined : parseInt(String(value), 10)))
  @IsInt()
  @Min(1)
  @Max(2)
  quincena?: number;

  @ApiProperty()
  @Transform(({ value }) => parseInt(String(value), 10))
  @IsInt()
  @Min(2000)
  @Max(2100)
  periodo_anio!: number;

  @ApiProperty({ description: 'Para AGUINALDO se fija automáticamente en 12 si se omite.' })
  @IsOptional()
  @Transform(({ value }) => (value === undefined || value === null || value === '' ? undefined : parseInt(String(value), 10)))
  @IsInt()
  @Min(1)
  @Max(12)
  periodo_mes?: number;

  @ApiPropertyOptional({ description: 'Sucursal específica; vacío = todas las sucursales' })
  @IsOptional()
  @IsUUID()
  sucursal_id?: string;

  @ApiPropertyOptional({ description: 'Tipo de empleado específico (ej. Asalariados, Prestadores); vacío = todos los tipos' })
  @IsOptional()
  @IsUUID()
  tipo_empleado_id?: string;

  @ApiProperty({ description: 'Fecha programada de pago de la liquidación' })
  @IsDateString()
  fecha_pago_programada!: string;

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

export class AgregarLineaManualDto {
  @ApiProperty()
  @IsUUID()
  empleado_id!: string;

  @ApiProperty({ description: 'ID del concepto de liquidación (de Configuración › Conceptos)' })
  @IsUUID()
  concepto_id!: string;

  @ApiProperty({ enum: ['INGRESO', 'EGRESO'] })
  @IsString()
  @IsIn(['INGRESO', 'EGRESO'])
  tipo!: 'INGRESO' | 'EGRESO';

  @ApiProperty()
  @IsNumber()
  @Min(0.01)
  monto!: number;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(0, 250)
  observacion?: string;
}

export class AccionLiquidacionDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  comentario?: string;

  @ApiPropertyOptional({
    description:
      'Confirmación explícita para permitir cierre con neto negativo cuando el parámetro vigente lo habilita.',
    default: false,
  })
  @IsOptional()
  @Transform(({ value }) => {
    if (value === undefined || value === null || value === '') return undefined;
    if (typeof value === 'boolean') return value;
    const raw = String(value).trim().toLowerCase();
    if (['true', '1', 'si', 'sí', 'yes'].includes(raw)) return true;
    if (['false', '0', 'no'].includes(raw)) return false;
    return value;
  })
  @IsBoolean()
  confirmar_excepcion_neto_negativo?: boolean;

  @ApiPropertyOptional({
    description:
      'Motivo formal de la excepción para neto negativo. Obligatorio cuando se confirma la excepción.',
  })
  @IsOptional()
  @IsString()
  @Length(10, 500)
  motivo_excepcion_neto_negativo?: string;
}

export class QueryLiquidacionesDto {
  @ApiPropertyOptional({ default: 1 })
  @IsOptional()
  @Transform(({ value }) => parseInt(String(value), 10) || 1)
  @IsInt()
  @Min(1)
  page?: number = 1;

  @ApiPropertyOptional({ default: 20 })
  @IsOptional()
  @Transform(({ value }) => parseInt(String(value), 10) || 20)
  @IsInt()
  @Min(1)
  @Max(200)
  limit?: number = 20;

  @ApiPropertyOptional({ enum: LIQUIDACION_ESTADOS })
  @IsOptional()
  @IsString()
  @IsIn(LIQUIDACION_ESTADOS as unknown as string[])
  estado?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @Transform(({ value }) => (value ? parseInt(String(value), 10) : undefined))
  @IsInt()
  periodo_anio?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @Transform(({ value }) => (value ? parseInt(String(value), 10) : undefined))
  @IsInt()
  periodo_mes?: number;
}

export class QueryPlanillaLiquidacionDto {
  @ApiPropertyOptional({ enum: PLANILLA_FORMATS, default: 'json' })
  @IsOptional()
  @IsString()
  @IsIn(PLANILLA_FORMATS as unknown as string[])
  format?: (typeof PLANILLA_FORMATS)[number] = 'json';
}
