import {
  registerDecorator,
  ValidationArguments,
  ValidationOptions,
  ValidatorConstraint,
  ValidatorConstraintInterface,
} from 'class-validator';

/** An Ethiopian TIN is exactly 10 digits. */
export const TIN_REGEX = /^\d{10}$/;

/**
 * Draft companies carry a placeholder TIN ("D" + 9 digits) minted server-side by
 * CompaniesService.generateDraftTin(), because the column is NOT NULL + unique.
 * Those never travel through a DTO, so this constraint deliberately rejects them
 * — a "D…" value arriving on a request body is client-supplied and invalid.
 */
@ValidatorConstraint({ name: 'IsTin', async: false })
export class IsTinConstraint implements ValidatorConstraintInterface {
  validate(value: unknown): boolean {
    // Empty is allowed here; pair with @IsOptional / @IsNotEmpty as needed.
    if (value === undefined || value === null || value === '') return true;
    if (typeof value !== 'string') return false;
    return TIN_REGEX.test(value);
  }

  defaultMessage(args: ValidationArguments): string {
    return `${args.property} must be exactly 10 digits`;
  }
}

/** Class-validator decorator enforcing the 10-digit TIN format. */
export function IsTin(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsTinConstraint,
    });
  };
}

/**
 * Strip everything that isn't a digit and cap at 10 characters. Tolerant —
 * never throws; returns the value unchanged when empty/nullish.
 */
export function normalizeTin(
  value: string | null | undefined,
): string | null | undefined {
  if (value === undefined || value === null || value === '') return value;
  return value.replace(/\D/g, '').slice(0, 10);
}
