/**
 * CreateBankAccountDto - DTO para crear cuentas bancarias
 *
 * @module Finance
 * @rf RF-MAE014-001
 */

import {
  IsString,
  IsNotEmpty,
  IsOptional,
  IsUUID,
  IsEnum,
  IsNumber,
  IsBoolean,
  MaxLength,
  MinLength,
  Matches,
  Min,
  IsObject,
} from 'class-validator';
import { BankAccountType, BankAccountStatus } from '../entities/bank-account.entity';

export class CreateBankAccountDto {
  /**
   * Nombre descriptivo de la cuenta
   * @example 'Cuenta Principal Banamex'
   */
  @IsString()
  @IsNotEmpty({ message: 'El nombre es requerido' })
  @MinLength(3, { message: 'El nombre debe tener al menos 3 caracteres' })
  @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' })
  name: string;

  /**
   * Numero de cuenta bancaria
   * @example '1234567890'
   */
  @IsString()
  @IsNotEmpty({ message: 'El numero de cuenta es requerido' })
  @MaxLength(50, { message: 'El numero de cuenta no puede exceder 50 caracteres' })
  accountNumber: string;

  /**
   * CLABE interbancaria (18 digitos)
   * @example '012345678901234567'
   */
  @IsOptional()
  @IsString()
  @Matches(/^\d{18}$/, { message: 'La CLABE debe tener exactamente 18 digitos' })
  clabe?: string;

  /**
   * Tipo de cuenta
   * @default 'checking'
   */
  @IsOptional()
  @IsEnum(['checking', 'savings', 'investment', 'credit_line', 'other'], {
    message: 'Tipo de cuenta invalido',
  })
  accountType?: BankAccountType;

  /**
   * Estado de la cuenta
   * @default 'active'
   */
  @IsOptional()
  @IsEnum(['active', 'inactive', 'blocked', 'closed'], {
    message: 'Estado invalido',
  })
  status?: BankAccountStatus;

  /**
   * Nombre del banco
   * @example 'Banamex'
   */
  @IsString()
  @IsNotEmpty({ message: 'El nombre del banco es requerido' })
  @MaxLength(100, { message: 'El nombre del banco no puede exceder 100 caracteres' })
  bankName: string;

  /**
   * Codigo del banco
   * @example '002'
   */
  @IsOptional()
  @IsString()
  @MaxLength(10)
  bankCode?: string;

  /**
   * Nombre de la sucursal
   */
  @IsOptional()
  @IsString()
  @MaxLength(100)
  branchName?: string;

  /**
   * Codigo de la sucursal
   */
  @IsOptional()
  @IsString()
  @MaxLength(20)
  branchCode?: string;

  /**
   * Moneda de la cuenta (ISO 4217)
   * @default 'MXN'
   */
  @IsOptional()
  @IsString()
  @Matches(/^[A-Z]{3}$/, { message: 'La moneda debe ser un codigo ISO de 3 letras' })
  currency?: string;

  /**
   * Saldo inicial de la cuenta
   * @default 0
   */
  @IsOptional()
  @IsNumber({}, { message: 'El saldo inicial debe ser un numero' })
  initialBalance?: number;

  /**
   * Limite de credito (para lineas de credito)
   */
  @IsOptional()
  @IsNumber({}, { message: 'El limite de credito debe ser un numero' })
  @Min(0, { message: 'El limite de credito no puede ser negativo' })
  creditLimit?: number;

  /**
   * Saldo minimo requerido
   */
  @IsOptional()
  @IsNumber({}, { message: 'El saldo minimo debe ser un numero' })
  @Min(0, { message: 'El saldo minimo no puede ser negativo' })
  minimumBalance?: number;

  /**
   * ID del proyecto asociado (si es cuenta especifica)
   */
  @IsOptional()
  @IsUUID('4', { message: 'projectId debe ser un UUID valido' })
  projectId?: string;

  /**
   * ID de la cuenta contable vinculada
   */
  @IsOptional()
  @IsUUID('4', { message: 'ledgerAccountId debe ser un UUID valido' })
  ledgerAccountId?: string;

  /**
   * Nombre del contacto en el banco
   */
  @IsOptional()
  @IsString()
  @MaxLength(255)
  bankContactName?: string;

  /**
   * Telefono del contacto en el banco
   */
  @IsOptional()
  @IsString()
  @MaxLength(50)
  bankContactPhone?: string;

  /**
   * Email del contacto en el banco
   */
  @IsOptional()
  @IsString()
  @MaxLength(255)
  bankContactEmail?: string;

  /**
   * Indica si es la cuenta por defecto
   * @default false
   */
  @IsOptional()
  @IsBoolean()
  isDefault?: boolean;

  /**
   * Permite realizar pagos
   * @default true
   */
  @IsOptional()
  @IsBoolean()
  allowsPayments?: boolean;

  /**
   * Permite recibir cobros
   * @default true
   */
  @IsOptional()
  @IsBoolean()
  allowsCollections?: boolean;

  /**
   * Notas adicionales
   */
  @IsOptional()
  @IsString()
  notes?: string;

  /**
   * Metadatos adicionales (JSON)
   */
  @IsOptional()
  @IsObject()
  metadata?: Record<string, any>;
}
