import { Injectable, BadRequestException } from "@nestjs/common";
import type { User as PrismaUser } from "@prisma/client";
import { PrismaService } from "@bff/infra/database/prisma.service";
import { normalizeAndValidateEmail, validateUuidV4OrThrow } from "@customer-portal/domain/common";
import { getErrorMessage } from "@bff/core/utils/error.util";

type AuthUpdatableFields = Pick<
  PrismaUser,
  "passwordHash" | "failedLoginAttempts" | "lastLoginAt" | "lockedUntil"
>;

@Injectable()
export class UserAuthRepository {
  constructor(private readonly prisma: PrismaService) {}

  async findByEmail(email: string): Promise<PrismaUser | null> {
    const normalized = normalizeAndValidateEmail(email);
    try {
      return await this.prisma.user.findUnique({ where: { email: normalized } });
    } catch (error) {
      throw new BadRequestException(`Unable to retrieve user by email: ${getErrorMessage(error)}`);
    }
  }

  async findById(id: string): Promise<PrismaUser | null> {
    const validId = validateUuidV4OrThrow(id);
    try {
      return await this.prisma.user.findUnique({ where: { id: validId } });
    } catch (error) {
      throw new BadRequestException(`Unable to retrieve user by id: ${getErrorMessage(error)}`);
    }
  }

  async create(data: Partial<PrismaUser>): Promise<PrismaUser> {
    if (!data.email) {
      throw new BadRequestException("Email is required to create a user");
    }

    const normalizedEmail = normalizeAndValidateEmail(data.email);

    try {
      return await this.prisma.user.create({
        data: {
          ...data,
          email: normalizedEmail,
        },
      });
    } catch (error) {
      throw new BadRequestException(`Unable to create user: ${getErrorMessage(error)}`);
    }
  }

  async updateAuthState(id: string, data: Partial<AuthUpdatableFields>): Promise<void> {
    const validId = validateUuidV4OrThrow(id);

    try {
      await this.prisma.user.update({
        where: { id: validId },
        data,
      });
    } catch (error) {
      throw new BadRequestException(`Unable to update user auth state: ${getErrorMessage(error)}`);
    }
  }
}
