import { db } from "@/lib/db"

export type LeaveApprovalStatus = "pending" | "approved" | "rejected"

export type LeaveApprover = {
  userId: string
  roleName: string
}

/** Roles that include the leave "process" action. */
export async function getLeaveProcessorRoleIds(): Promise<string[]> {
  const perms = await db.permission.findMany({
    where: { module: "leave" },
    select: { roleId: true, actions: true },
  })
  return perms.filter((p) => p.actions.includes("process")).map((p) => p.roleId)
}

/** Active users who can process leave (one entry per user; role = first matching process role). */
export async function getLeaveApprovers(excludeUserId?: string): Promise<LeaveApprover[]> {
  const roleIds = await getLeaveProcessorRoleIds()
  if (roleIds.length === 0) return []

  const userRoles = await db.userRole.findMany({
    where: {
      roleId: { in: roleIds },
      user: { isActive: true },
    },
    include: {
      role: { select: { name: true } },
    },
    orderBy: { role: { name: "asc" } },
  })

  const byUser = new Map<string, LeaveApprover>()
  for (const ur of userRoles) {
    if (excludeUserId && ur.userId === excludeUserId) continue
    if (!byUser.has(ur.userId)) {
      byUser.set(ur.userId, { userId: ur.userId, roleName: ur.role.name })
    }
  }
  return [...byUser.values()]
}

export async function userCanProcessLeave(userId: string): Promise<boolean> {
  const approvers = await getLeaveApprovers()
  return approvers.some((a) => a.userId === userId)
}

/** Create pending LeaveApproval rows for every leave processor (idempotent per user). */
export async function createLeaveApprovals(
  leaveRequestId: string,
  excludeUserId?: string,
): Promise<void> {
  const approvers = await getLeaveApprovers(excludeUserId)
  if (approvers.length === 0) return

  const existing = await db.leaveApproval.findMany({
    where: { leaveRequestId },
    select: { approverId: true },
  })
  const existingIds = new Set(existing.map((a) => a.approverId))

  const toCreate = approvers.filter((a) => !existingIds.has(a.userId))
  if (toCreate.length === 0) return

  await db.leaveApproval.createMany({
    data: toCreate.map((a) => ({
      leaveRequestId,
      approverId: a.userId,
      role: a.roleName,
      status: "pending",
    })),
  })
}

/** Backfill approvals for legacy pending requests that have none yet. */
export async function ensureLeaveApprovals(
  leaveRequestId: string,
  employeeUserId?: string | null,
): Promise<void> {
  const count = await db.leaveApproval.count({ where: { leaveRequestId } })
  if (count > 0) return
  await createLeaveApprovals(leaveRequestId, employeeUserId ?? undefined)
}

export function resolveLeaveRequestStatus(
  approvals: { status: string }[],
): LeaveApprovalStatus {
  if (approvals.length === 0) return "pending"
  if (approvals.some((a) => a.status === "rejected")) return "rejected"
  if (approvals.every((a) => a.status === "approved")) return "approved"
  return "pending"
}
