import {
  IsEmail,
  IsOptional,
  MaxLength,
  Validate,
  ValidationArguments,
  ValidatorConstraint,
  ValidatorConstraintInterface,
} from 'class-validator';

import type { MasterUser } from './master-user.dto';
import { isPlanFiUuidLike } from '../planfi-uuid';

@ValidatorConstraint({ name: 'planFiUuid', async: false })
class PlanFiUuidConstraint implements ValidatorConstraintInterface {
  validate(value: unknown): boolean {
    return isPlanFiUuidLike(value);
  }

  defaultMessage(): string {
    return 'uuid must be a valid PlanFi UUID';
  }
}

@ValidatorConstraint({ name: 'uuidOrEmailExclusive', async: false })
class UuidOrEmailExclusiveConstraint implements ValidatorConstraintInterface {
  validate(_: unknown, args: ValidationArguments): boolean {
    const obj = args.object as LookupUserDto;
    const hasUuid = typeof obj.uuid === 'string' && obj.uuid.trim().length > 0;
    const hasEmail =
      typeof obj.email === 'string' && obj.email.trim().length > 0;
    return hasUuid !== hasEmail;
  }

  defaultMessage(): string {
    return 'Provide exactly one of uuid or email';
  }
}

export class LookupUserDto {
  @IsOptional()
  @Validate(PlanFiUuidConstraint)
  uuid?: string;

  @IsOptional()
  @IsEmail()
  @MaxLength(255)
  email?: string;

  @Validate(UuidOrEmailExclusiveConstraint)
  private readonly _uuidOrEmailExclusive?: never;
}

export interface LookupUserResponse {
  user: MasterUser;
}
