import type { Project, User, UserRole } from "@prisma/client";
import { requireUser } from "./auth";
import { projectDetailInclude, type ProjectDetail } from "./metrics";
import {
  ensureUserOwnedProjectAccess,
  getResolvedProjectPermissions,
  type PermissionMap,
  type PermissionKey
} from "./permissions";
import { prisma } from "./prisma";
import { redirect } from "next/navigation";

export type ProjectListItem = Omit<Project, "purchasePrice"> & {
  purchasePrice: number;
};

export async function getProjectsForUser(userId: string) {
  await ensureUserOwnedProjectAccess(userId);
  const projects = await prisma.project.findMany({
    where: {
      projectUsers: {
        some: {
          userId,
          status: "ACTIVE"
        }
      },
      status: { not: "ARCHIVED" }
    },
    orderBy: { createdAt: "asc" }
  });
  return projects.map((project) => ({
    ...project,
    purchasePrice: Number(project.purchasePrice)
  }));
}

type SelectedProjectContext = {
  user: User;
  projects: ProjectListItem[];
  project: ProjectDetail | null;
  permissions: PermissionMap | null;
  projectRole: UserRole | null;
};

export async function getSelectedProject(
  projectId?: string | null,
  requiredPermission: PermissionKey = "project.view"
): Promise<SelectedProjectContext> {
  const user = await requireUser();
  const projects = await getProjectsForUser(user.id);
  if (projectId && !projects.some((project) => project.id === projectId)) {
    redirect("/unauthorized");
  }
  const selectedId = projectId ?? projects[0]?.id;

  const project = selectedId
    ? await prisma.project.findUnique({
        where: { id: selectedId },
        include: projectDetailInclude
      })
    : null;

  if (!project) return { user, projects, project, permissions: null, projectRole: null };

  const { membership, permissions } = await getResolvedProjectPermissions(user.id, project.id);
  if (!membership || !permissions[requiredPermission]) {
    redirect(`/unauthorized?projectId=${project.id}`);
  }

  return { user, projects, project, permissions, projectRole: membership.role };
}

export async function ensureProject(projectId?: string | null) {
  const context = await getSelectedProject(projectId);
  if (!context.project) return context;
  return context;
}
