import type { PrismaClient } from '@prisma/client'
import type { IUserRepository } from '../../domain/ports/user-repository'
import type { User, CreateUserData } from '../../domain/entities/user'
import { isUserRole } from '../../domain/entities/user'
import { AppError } from '../../domain/errors/app-error'

function mapUser(raw: {
  id: string
  fullName: string
  email: string
  passwordHash: string
  role: string
  discountLimitPct: { toNumber(): number }
  isActive: boolean
  createdAt: Date
  updatedAt: Date
}): User {
  const role = raw.role
  if (!isUserRole(role)) {
    throw new AppError('INTERNAL_ERROR', 500, `Rol desconocido en BD: ${role}`)
  }
  return {
    id: raw.id,
    fullName: raw.fullName,
    email: raw.email,
    passwordHash: raw.passwordHash,
    role,
    discountLimitPct: raw.discountLimitPct.toNumber(),
    isActive: raw.isActive,
    createdAt: raw.createdAt,
    updatedAt: raw.updatedAt,
  }
}

export class PrismaUserRepository implements IUserRepository {
  constructor(private readonly db: PrismaClient) {}

  async findByEmail(email: string): Promise<User | null> {
    const raw = await this.db.user.findUnique({ where: { email } })
    return raw ? mapUser(raw) : null
  }

  async findById(id: string): Promise<User | null> {
    const raw = await this.db.user.findUnique({ where: { id } })
    return raw ? mapUser(raw) : null
  }

  async emailExists(email: string): Promise<boolean> {
    const count = await this.db.user.count({ where: { email } })
    return count > 0
  }

  async create(data: CreateUserData): Promise<User> {
    const raw = await this.db.user.create({
      data: {
        fullName: data.fullName,
        email: data.email,
        passwordHash: data.passwordHash,
        role: data.role,
        discountLimitPct: data.discountLimitPct,
      },
    })
    return mapUser(raw)
  }
}
