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

// ──────────────────────────────────────────────────────────────────────────
// Enums (espejo de los enums Prisma — mantener sincronizados)
// ──────────────────────────────────────────────────────────────────────────

export enum LegajoDocumentoEstado {
  ACTIVO = 'ACTIVO',
  REEMPLAZADO = 'REEMPLAZADO',
  ANULADO = 'ANULADO',
}

export enum LegajoVencimientoEstado {
  SIN_VENCIMIENTO = 'SIN_VENCIMIENTO',
  VIGENTE = 'VIGENTE',
  POR_VENCER = 'POR_VENCER',
  VENCIDO = 'VENCIDO',
}

const FECHA_RE = /^\d{4}-\d{2}-\d{2}$/;
const CODIGO_RE = /^[A-Z0-9_]+$/;

// ──────────────────────────────────────────────────────────────────────────
// M23 — Catálogo de tipos de documento
// ──────────────────────────────────────────────────────────────────────────

export class QueryTiposDocumentoDto {
  @ApiPropertyOptional({ description: 'Incluir tipos inactivos (default: false)' })
  @IsOptional()
  @Transform(({ value }) => String(value).toLowerCase() === 'true')
  @IsBoolean()
  incluir_inactivos?: boolean = false;

  @ApiPropertyOptional({ description: 'Filtrar sólo tipos personalizados de la empresa' })
  @IsOptional()
  @Transform(({ value }) => String(value).toLowerCase() === 'true')
  @IsBoolean()
  solo_personalizados?: boolean = false;

  @ApiPropertyOptional({ description: 'Búsqueda parcial por nombre o código' })
  @IsOptional()
  @IsString()
  @Length(1, 100)
  q?: string;
}

export class CreateTipoDocumentoDto {
  @ApiProperty({ example: 'NDA', description: 'Código único en mayúsculas, sin espacios' })
  @IsString()
  @Length(2, 30)
  @Matches(CODIGO_RE, { message: 'El código debe contener sólo mayúsculas, números y guión bajo' })
  codigo!: string;

  @ApiProperty({ example: 'Acuerdo de confidencialidad' })
  @IsString()
  @Length(2, 150)
  nombre!: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(0, 1000)
  descripcion?: string;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  @IsBoolean()
  admite_vencimiento?: boolean = false;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  @IsBoolean()
  vencimiento_obligatorio?: boolean = false;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  @IsBoolean()
  es_obligatorio?: boolean = false;

  @ApiPropertyOptional({ description: 'Días de anticipación de alerta (null = usa parámetro global)' })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(365)
  dias_alerta_vencimiento?: number;

  @ApiPropertyOptional({ default: false })
  @IsOptional()
  @IsBoolean()
  permite_multiples?: boolean = false;
}

export class UpdateTipoDocumentoDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(2, 150)
  nombre?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(0, 1000)
  descripcion?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  admite_vencimiento?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  vencimiento_obligatorio?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  es_obligatorio?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  @Max(365)
  dias_alerta_vencimiento?: number | null;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  permite_multiples?: boolean;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  activo?: boolean;
}

// ──────────────────────────────────────────────────────────────────────────
// M24 — Documentos del legajo
// ──────────────────────────────────────────────────────────────────────────

export class SubirDocumentoDto {
  @ApiProperty({ description: 'ID del tipo de documento (catálogo M23)' })
  @IsUUID()
  tipo_documento_id!: string;

  @ApiPropertyOptional({ example: '2026-05-01', description: 'Fecha de emisión del documento' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha_documento debe ser YYYY-MM-DD' })
  fecha_documento?: string;

  @ApiPropertyOptional({ example: '2027-05-01', description: 'Fecha de vencimiento (si aplica)' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'fecha_vencimiento debe ser YYYY-MM-DD' })
  fecha_vencimiento?: string;

  @ApiPropertyOptional({ description: 'Observaciones adicionales' })
  @IsOptional()
  @IsString()
  @Length(0, 2000)
  descripcion?: string;
}

export class ReemplazarDocumentoDto {
  @ApiPropertyOptional({ example: '2026-05-01' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE)
  fecha_documento?: string;

  @ApiPropertyOptional({ example: '2027-05-01' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE)
  fecha_vencimiento?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(0, 2000)
  descripcion?: string;
}

export class AnularDocumentoDto {
  @ApiProperty({ description: 'Motivo de anulación (obligatorio para auditoría)' })
  @IsString()
  @Length(5, 1000)
  motivo!: string;
}

// ──────────────────────────────────────────────────────────────────────────
// Query del legajo por funcionario
// ──────────────────────────────────────────────────────────────────────────

export class QueryLegajoEmpleadoDto {
  @ApiPropertyOptional({ description: 'Filtrar por estado de vencimiento' })
  @IsOptional()
  @IsEnum(LegajoVencimientoEstado)
  estado_vencimiento?: LegajoVencimientoEstado;

  @ApiPropertyOptional({ description: 'Filtrar por tipo de documento' })
  @IsOptional()
  @IsUUID()
  tipo_documento_id?: string;
}

// ──────────────────────────────────────────────────────────────────────────
// M26 — Consulta avanzada y exportación
// ──────────────────────────────────────────────────────────────────────────

export class QueryLegajosConsultaDto {
  @ApiPropertyOptional({ default: 50, minimum: 1, maximum: 100 })
  @IsOptional()
  @Transform(({ value }) => parseInt(String(value), 10) || 50)
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number = 50;

  @ApiPropertyOptional({
    description: 'Cursor opaco para keyset pagination (base64)',
  })
  @IsOptional()
  @IsString()
  cursor?: string;

  @ApiPropertyOptional({ description: 'Filtrar por empleado específico' })
  @IsOptional()
  @IsUUID()
  empleado_id?: string;

  @ApiPropertyOptional({ description: 'Filtrar por tipo de documento' })
  @IsOptional()
  @IsUUID()
  tipo_documento_id?: string;

  @ApiPropertyOptional({ description: 'Filtrar por sucursal del empleado' })
  @IsOptional()
  @IsUUID()
  sucursal_id?: string;

  @ApiPropertyOptional({ description: 'Filtrar por departamento del empleado' })
  @IsOptional()
  @IsUUID()
  departamento_id?: string;

  @ApiPropertyOptional({ enum: LegajoVencimientoEstado })
  @IsOptional()
  @IsEnum(LegajoVencimientoEstado)
  estado_vencimiento?: LegajoVencimientoEstado;

  @ApiPropertyOptional({
    enum: LegajoDocumentoEstado,
    default: LegajoDocumentoEstado.ACTIVO,
  })
  @IsOptional()
  @IsEnum(LegajoDocumentoEstado)
  estado_documento?: LegajoDocumentoEstado = LegajoDocumentoEstado.ACTIVO;

  @ApiPropertyOptional({ example: '2026-05-01', description: 'Fecha de carga desde (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'subido_desde debe ser YYYY-MM-DD' })
  subido_desde?: string;

  @ApiPropertyOptional({ example: '2026-05-31', description: 'Fecha de carga hasta (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'subido_hasta debe ser YYYY-MM-DD' })
  subido_hasta?: string;

  @ApiPropertyOptional({ example: '2026-06-01', description: 'Fecha de vencimiento desde (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'vence_desde debe ser YYYY-MM-DD' })
  vence_desde?: string;

  @ApiPropertyOptional({ example: '2026-12-31', description: 'Fecha de vencimiento hasta (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  @Matches(FECHA_RE, { message: 'vence_hasta debe ser YYYY-MM-DD' })
  vence_hasta?: string;

  @ApiPropertyOptional({
    description: 'Búsqueda libre por empleado (nombre/apellido/número), tipo (código/nombre) o nombre de archivo',
  })
  @IsOptional()
  @IsString()
  @Length(1, 120)
  q?: string;
}

export class ExportarLegajosConsultaDto extends QueryLegajosConsultaDto {
  @ApiProperty({ enum: ['excel'], default: 'excel' })
  @IsString()
  @Matches(/^excel$/i, { message: 'Sólo se admite formato=excel en backend.' })
  formato!: string;
}
