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

export const TIPOS_ARCHIVO = ['DELIMITADO', 'POSICIONAL'] as const;
export const ACRED_ESTADOS = ['GENERADO', 'ENVIADO', 'CONFIRMADO', 'ANULADO'] as const;

// ── Formatos ─────────────────────────────────────────────────
export class CreateFormatoAcreditacionDto {
  @ApiProperty()
  @IsUUID()
  banco_id!: string;

  @ApiProperty()
  @IsString()
  @Length(1, 100)
  nombre!: string;

  @ApiPropertyOptional({ default: 'UTF-8' })
  @IsOptional()
  @IsString()
  @Length(1, 20)
  encoding?: string;

  @ApiPropertyOptional({ default: '\\n' })
  @IsOptional()
  @IsString()
  @Length(1, 5)
  separador_lineas?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @Length(1, 5)
  separador_campos?: string;

  @ApiPropertyOptional({ enum: TIPOS_ARCHIVO, default: 'DELIMITADO' })
  @IsOptional()
  @IsString()
  @IsIn(TIPOS_ARCHIVO as unknown as string[])
  tipo_archivo?: (typeof TIPOS_ARCHIVO)[number];

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

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

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

  @ApiProperty()
  @IsString()
  template_detalle!: string;

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

  @ApiPropertyOptional({ default: 'txt' })
  @IsOptional()
  @IsString()
  @Length(1, 10)
  extension_archivo?: string;

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

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

export class UpdateFormatoAcreditacionDto extends PartialType(CreateFormatoAcreditacionDto) {}

export class QueryFormatosDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  banco_id?: string;
}

// ── Acreditaciones (archivos generados) ──────────────────────
export class GenerarAcreditacionDto {
  @ApiProperty()
  @IsUUID()
  liquidacion_id!: string;

  @ApiProperty()
  @IsUUID()
  banco_id!: string;

  @ApiPropertyOptional({ description: 'Si se omite, se usa el formato activo del banco' })
  @IsOptional()
  @IsUUID()
  formato_id?: string;

  @ApiPropertyOptional({ description: 'Cuenta de tesorería desde la que se paga (para registrar el egreso al confirmar)' })
  @IsOptional()
  @IsUUID()
  cuenta_tesoreria_id?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsDateString()
  fecha_pago_programada?: string;

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

export class MarcarEnviadoDto {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  observaciones?: string;
}

export class MarcarConfirmadoDto {
  @ApiPropertyOptional({ description: 'Cuenta de tesorería desde la que se paga. Requerida si la empresa usa Tesorería y no se definió al generar.' })
  @IsOptional()
  @IsUUID()
  cuenta_tesoreria_id?: string;

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

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

export class QueryAcreditacionesDto {
  @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: ACRED_ESTADOS })
  @IsOptional()
  @IsString()
  @IsIn(ACRED_ESTADOS as unknown as string[])
  estado?: string;

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

  @ApiPropertyOptional()
  @IsOptional()
  @IsUUID()
  banco_id?: string;
}
