import { ConvexError } from "convex/values"

import type { Id } from "./_generated/dataModel"
import type { MutationCtx, QueryCtx } from "./_generated/server"

const STAFF_ROLES = new Set(["ADMIN", "MANAGER", "AGENT", "COLLABORATOR"])
const MANAGER_ROLE = "MANAGER"

type Ctx = QueryCtx | MutationCtx

function normalizeRole(role?: string | null) {
  return role?.toUpperCase() ?? null
}

async function getUser(ctx: Ctx, userId: Id<"users">) {
  const user = await ctx.db.get(userId)
  if (!user) {
    throw new ConvexError("Usuário não encontrado")
  }
  return user
}

export async function requireUser(ctx: Ctx, userId: Id<"users">, tenantId?: string) {
  const user = await getUser(ctx, userId)
  if (tenantId && user.tenantId !== tenantId) {
    throw new ConvexError("Usuário não pertence a este tenant")
  }
  return { user, role: normalizeRole(user.role) }
}

export async function requireStaff(ctx: Ctx, userId: Id<"users">, tenantId?: string) {
  const result = await requireUser(ctx, userId, tenantId)
  if (!result.role || !STAFF_ROLES.has(result.role)) {
    throw new ConvexError("Acesso restrito à equipe interna")
  }
  return result
}

export async function requireAdmin(ctx: Ctx, userId: Id<"users">, tenantId?: string) {
  const result = await requireStaff(ctx, userId, tenantId)
  if (result.role !== "ADMIN") {
    throw new ConvexError("Apenas administradores podem executar esta ação")
  }
  return result
}

// removed customer role; use requireCompanyManager or requireStaff as appropriate

export async function requireCompanyManager(ctx: Ctx, userId: Id<"users">, tenantId?: string) {
  const result = await requireUser(ctx, userId, tenantId)
  if (result.role !== MANAGER_ROLE) {
    throw new ConvexError("Apenas gestores da empresa podem executar esta ação")
  }
  if (!result.user.companyId) {
    throw new ConvexError("Gestor não possui empresa vinculada")
  }
  return result
}

export async function requireCompanyAssociation(
  ctx: Ctx,
  userId: Id<"users">,
  companyId: Id<"companies">,
  tenantId?: string,
) {
  const result = await requireUser(ctx, userId, tenantId)
  if (!result.user.companyId) {
    throw new ConvexError("Usuário não possui empresa vinculada")
  }
  if (result.user.companyId !== companyId) {
    throw new ConvexError("Usuário não pertence a esta empresa")
  }
  return result
}
