import { ApiProperty, ApiPropertyOptional, PartialType } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import {
  IsBoolean,
  IsEnum,
  IsInt,
  IsOptional,
  IsString,
  IsUUID,
  Length,
  Matches,
  Max,
  Min,
} from 'class-validator';

export enum PermisoPresentismoTipo {
  JORNADA_COMPLETA = 'JORNADA_COMPLETA',
  TURNO = 'TURNO',
  SALIDA_ANTICIPADA = 'SALIDA_ANTICIPADA',
  LLEGADA_TARDIA = 'LLEGADA_TARDIA',
  AUSENCIA_TURNO = 'AUSENCIA_TURNO',
}

export enum PermisoPresentismoJustificacion {
  MEDICA = 'MEDICA',
  PERSONAL = 'PERSONAL',
  FUERZA_MAYOR = 'FUERZA_MAYOR',
  INSTITUCIONAL = 'INSTITUCIONAL',
  CLIMA = 'CLIMA',
  OTRO = 'OTRO',
}

export enum PermisoPresentismoEstado {
  PENDIENTE = 'PENDIENTE',
  APROBADO = 'APROBADO',
  RECHAZADO = 'RECHAZADO',
}

export enum ToleranciaAplicaA {
  TODOS = 'TODOS',
  SUCURSAL = 'SUCURSAL',
  DEPARTAMENTO = 'DEPARTAMENTO',
}

const FECHA_RE = /^\d{4}-\d{2}-\d{2}$/;
const HORA_RE = /^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/;

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

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

  @ApiPropertyOptional({ enum: PermisoPresentismoEstado })
  @IsOptional()
  @IsEnum(PermisoPresentismoEstado)
  estado?: PermisoPresentismoEstado;

  @ApiPropertyOptional({ enum: PermisoPresentismoTipo })
  @IsOptional()
  @IsEnum(PermisoPresentismoTipo)
  tipo_permiso?: PermisoPresentismoTipo;

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

  @ApiPropertyOptional({ example: '2026-05-01' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha_desde debe ser YYYY-MM-DD' })
  fecha_desde?: string;

  @ApiPropertyOptional({ example: '2026-05-31' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha_hasta debe ser YYYY-MM-DD' })
  fecha_hasta?: string;
}

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

  @ApiProperty({ example: '2026-05-20' })
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha debe ser YYYY-MM-DD' })
  fecha!: string;

  @ApiProperty({ enum: PermisoPresentismoTipo })
  @IsEnum(PermisoPresentismoTipo)
  tipo_permiso!: PermisoPresentismoTipo;

  @ApiPropertyOptional({ minimum: 1 })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(10)
  turno_bloque_orden?: number;

  @ApiPropertyOptional({ example: '08:00' })
  @IsOptional()
  @IsString()
  @Matches(HORA_RE, { message: 'hora_desde debe ser HH:MM' })
  hora_desde?: string;

  @ApiPropertyOptional({ example: '08:30' })
  @IsOptional()
  @IsString()
  @Matches(HORA_RE, { message: 'hora_hasta debe ser HH:MM' })
  hora_hasta?: string;

  @ApiPropertyOptional({ description: 'Especialmente para LLEGADA_TARDIA', minimum: 1 })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(720)
  minutos_tolerados?: number;

  @ApiPropertyOptional({
    description:
      'Documento del legajo asociado al permiso (por ejemplo certificado médico). Debe pertenecer al mismo empleado y empresa.',
  })
  @IsOptional()
  @IsUUID()
  legajo_documento_id?: string;

  @ApiProperty({ example: 'Consulta médica de urgencia' })
  @IsString()
  @Length(3, 500)
  motivo!: string;

  @ApiProperty({ enum: PermisoPresentismoJustificacion })
  @IsEnum(PermisoPresentismoJustificacion)
  tipo_justificacion!: PermisoPresentismoJustificacion;

  @ApiPropertyOptional({ default: true })
  @IsOptional()
  @IsBoolean()
  afecta_descuento?: boolean = true;
}

export class UpdatePermisoPresentismoDto extends PartialType(CreatePermisoPresentismoDto) {}

export class CambiarEstadoPermisoPresentismoDto {
  @ApiPropertyOptional({ example: 'Aprobado por documentación adjunta completa.' })
  @IsOptional()
  @IsString()
  @Length(3, 500)
  motivo?: string;
}

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

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

  @ApiPropertyOptional({ enum: ToleranciaAplicaA })
  @IsOptional()
  @IsEnum(ToleranciaAplicaA)
  aplica_a?: ToleranciaAplicaA;

  @ApiPropertyOptional({ example: '2026-05-20' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha debe ser YYYY-MM-DD' })
  fecha?: string;
}

export class CreateToleranciaEspecialDto {
  @ApiProperty({ example: '2026-05-20' })
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha debe ser YYYY-MM-DD' })
  fecha!: string;

  @ApiProperty({ minimum: 0, maximum: 720 })
  @Type(() => Number)
  @IsInt()
  @Min(0)
  @Max(720)
  tolerancia_entrada_min!: number;

  @ApiProperty({ minimum: 0, maximum: 720 })
  @Type(() => Number)
  @IsInt()
  @Min(0)
  @Max(720)
  tolerancia_salida_min!: number;

  @ApiProperty({ example: 'Lluvia intensa' })
  @IsString()
  @Length(3, 500)
  motivo!: string;

  @ApiPropertyOptional({ enum: ToleranciaAplicaA, default: ToleranciaAplicaA.TODOS })
  @IsOptional()
  @IsEnum(ToleranciaAplicaA)
  aplica_a?: ToleranciaAplicaA = ToleranciaAplicaA.TODOS;

  @ApiPropertyOptional({ description: 'Obligatorio para SUCURSAL o DEPARTAMENTO' })
  @IsOptional()
  @IsUUID()
  aplica_a_id?: string;
}

export class UpdateToleranciaEspecialDto extends PartialType(CreateToleranciaEspecialDto) {}
