import {
  ValidatorConstraint,
  ValidatorConstraintInterface,
  ValidationArguments,
} from 'class-validator';
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';

export interface UniqueInDatabaseConstraintOptions {
  except?: (currentEntity: any) => boolean;
  allowNull?: boolean;
  ignoreIdField?: string;
}

@ValidatorConstraint({ async: true })
@Injectable()
export class UniqueInDatabaseVarlidator
  implements ValidatorConstraintInterface
{
  constructor(private readonly dataSource: DataSource) {}

  async validate(value: any, args: ValidationArguments): Promise<boolean> {
    const [EntityClass, field, options = {}] = args.constraints as [
      any,
      string,
      UniqueInDatabaseConstraintOptions,
    ];

    const { except, allowNull, ignoreIdField } = options;

    if ((value === null || value === undefined) && allowNull) {
      return true;
    }

    const repo = this.dataSource.getRepository(EntityClass);
    const entity = await repo.findOne({ where: { [field]: value } });

    if (!entity) return true;

    // ⚠️ Nếu chỉ muốn bỏ qua entity có cùng ID (hoặc trường do chỉ định)
    if (ignoreIdField && args.object) {
      const currentId = (args.object as any)[ignoreIdField];
      if (entity.id === currentId || entity[ignoreIdField] === currentId) {
        return true;
      }
    }

    // Optionally apply custom except logic
    if (typeof except === 'function') {
      return except(entity);
    }

    return false;
  }

  defaultMessage(args: ValidationArguments) {
    const [_, field] = args.constraints;
    return `${field} already exists`;
  }
}
