import { prisma } from '../../lib/prisma'
import { hashPassword, comparePassword } from '../../lib/password'
import { signAccessToken, signRefreshToken } from '../../lib/jwt'
import { ApiError } from '../../utils/apiError'

// Build the JWT payload + safe user object returned to clients.
const buildAuthResult = async (user: any) => {
  const fullUser = await prisma.user.findUnique({
    where: { id: user.id },
    include: { profile: true },
  })
  const payload = { userId: fullUser!.id, role: fullUser!.role, email: fullUser!.email }
  return {
    user: {
      id: fullUser!.id,
      email: fullUser!.email,
      role: fullUser!.role,
      isActive: fullUser!.isActive,
      createdAt: fullUser!.createdAt,
      updatedAt: fullUser!.updatedAt,
      profile: fullUser!.profile,
    },
    accessToken: signAccessToken(payload),
    refreshToken: signRefreshToken(payload),
  }
}

export const authService = {
  async register(input: { email: string; password: string; fullName: string; phoneNumber?: string }) {
    const existing = await prisma.user.findUnique({ where: { email: input.email } })
    if (existing) throw new ApiError(409, 'Email sudah terdaftar')

    const password = await hashPassword(input.password)
    const user = await prisma.user.create({
      data: {
        email: input.email,
        password,
        role: 'student',
        profile: {
          create: { fullName: input.fullName, phoneNumber: input.phoneNumber },
        },
        registration: { create: { status: 'draft', lastStepCompleted: 0 } },
      },
      include: { profile: true },
    })

    await prisma.activity.create({
      data: { userId: user.id, description: `Pendaftar baru: ${input.fullName}`, status: 'info' },
    })
    await prisma.notification.create({
      data: {
        userId: user.id,
        title: 'Selamat datang!',
        message: 'Akun Anda berhasil dibuat. Silakan lengkapi biodata dan unggah berkas.',
        type: 'success',
      },
    })

    return buildAuthResult(user)
  },

  async login(email: string, password: string) {
    const user = await prisma.user.findUnique({ where: { email } })
    if (!user) throw new ApiError(401, 'Email atau password salah')
    if (!user.isActive) throw new ApiError(403, 'Akun tidak aktif. Hubungi admin.')
    const valid = await comparePassword(password, user.password)
    if (!valid) throw new ApiError(401, 'Email atau password salah')
    return buildAuthResult(user)
  },

  async forgotPassword(email: string) {
    const user = await prisma.user.findUnique({ where: { email } })
    // Always return success to avoid user enumeration.
    if (!user) return { message: 'Jika email terdaftar, instruksi telah dikirim.' }
    const token = require('crypto').randomBytes(32).toString('hex')
    const expiresAt = new Date(Date.now() + 1000 * 60 * 30) // 30 minutes
    await prisma.passwordReset.create({ data: { email, token, expiresAt } })
    return { message: 'Instruksi reset password telah dikirim ke email Anda.', token }
  },

  async resetPassword(token: string, password: string) {
    const record = await prisma.passwordReset.findFirst({ where: { token, used: false } })
    if (!record) throw new ApiError(400, 'Token tidak valid')
    if (record.expiresAt < new Date()) throw new ApiError(400, 'Token sudah kedaluwarsa')
    const hashed = await hashPassword(password)
    await prisma.$transaction([
      prisma.user.update({ where: { email: record.email }, data: { password: hashed } }),
      prisma.passwordReset.update({ where: { id: record.id }, data: { used: true } }),
    ])
    return { message: 'Password berhasil direset. Silakan login.' }
  },

  async me(userId: number) {
    const user = await prisma.user.findUnique({
      where: { id: userId },
      include: { profile: true },
    })
    if (!user) throw new ApiError(404, 'User tidak ditemukan')
    return user
  },
}
