import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

const permissionGroups = [
  ["project.view", "project.create", "project.edit", "project.archive", "project.delete"],
  ["users.view", "users.create", "users.edit", "users.disable", "users.resetPassword", "users.managePermissions"],
  ["partners.view", "partners.create", "partners.edit", "partners.archive", "partners.delete", "partners.editOwnership"],
  ["categories.view", "categories.create", "categories.edit", "categories.archive", "categories.delete"],
  ["contributions.view", "contributions.create", "contributions.edit", "contributions.archive", "contributions.delete"],
  ["purchaseCosts.view", "purchaseCosts.create", "purchaseCosts.edit", "purchaseCosts.archive", "purchaseCosts.delete"],
  ["renovationCosts.view", "renovationCosts.create", "renovationCosts.edit", "renovationCosts.archive", "renovationCosts.delete"],
  ["operatingExpenses.view", "operatingExpenses.create", "operatingExpenses.edit", "operatingExpenses.archive", "operatingExpenses.delete"],
  ["expenses.view", "expenses.create", "expenses.edit", "expenses.archive", "expenses.delete", "expenses.export"],
  ["recurringBills.view", "recurringBills.create", "recurringBills.edit", "recurringBills.archive", "recurringBills.delete", "recurringBills.markPaid"],
  ["receipts.view", "receipts.upload", "receipts.replace", "receipts.archive", "receipts.delete", "receipts.download"],
  ["documents.view", "documents.upload", "documents.edit", "documents.archive", "documents.delete", "documents.download"],
  ["tenants.view", "tenants.create", "tenants.edit", "tenants.archive", "tenants.delete"],
  ["units.view", "units.create", "units.edit", "units.archive", "units.delete"],
  ["rentPayments.view", "rentPayments.create", "rentPayments.edit", "rentPayments.archive", "rentPayments.delete"],
  ["securityDeposits.view", "securityDeposits.create", "securityDeposits.edit", "securityDeposits.archive", "securityDeposits.delete"],
  ["profitLoss.view", "profitLoss.export"],
  ["settlement.view", "settlement.export"],
  ["dashboard.view", "reports.view", "reports.export"],
  ["settings.view", "settings.edit", "settings.manageApp"],
  ["approvals.view", "approvals.approve", "approvals.reject"],
  ["audit.view"]
];

const allPermissionKeys = permissionGroups.flat();
const roles = ["OWNER", "ADMIN", "EDITOR", "CONTRIBUTOR", "VIEWER", "RECEIPT_UPLOADER", "TENANT", "CUSTOM"];

function map(keys = []) {
  return Object.fromEntries(allPermissionKeys.map((key) => [key, keys.includes(key)]));
}

const viewKeys = allPermissionKeys.filter((key) => key.endsWith(".view") || key.endsWith(".download"));
const editKeys = allPermissionKeys.filter((key) => !key.endsWith(".delete") && !key.startsWith("users.") && key !== "settings.manageApp" && key !== "audit.view");
const createUploadKeys = allPermissionKeys.filter(
  (key) => key.endsWith(".view") || key.endsWith(".create") || key.endsWith(".upload") || key.endsWith(".download") || key === "receipts.replace"
);

const defaults = {
  OWNER: map(allPermissionKeys),
  ADMIN: map(allPermissionKeys.filter((key) => key !== "project.delete")),
  EDITOR: map([...editKeys, "expenses.export", "reports.view", "documents.download", "receipts.download", "recurringBills.markPaid"]),
  CONTRIBUTOR: map([...createUploadKeys, "dashboard.view", "project.view", "expenses.view", "purchaseCosts.view", "renovationCosts.view", "operatingExpenses.view", "documents.view", "receipts.view"]),
  VIEWER: map([...viewKeys, "dashboard.view", "project.view", "reports.view", "profitLoss.view", "settlement.view"]),
  RECEIPT_UPLOADER: map(["dashboard.view", "project.view", "expenses.view", "purchaseCosts.view", "renovationCosts.view", "operatingExpenses.view", "documents.view", "documents.upload", "documents.download", "receipts.view", "receipts.upload", "receipts.replace", "receipts.download"]),
  TENANT: map(["project.view", "tenants.view", "units.view", "rentPayments.view", "documents.view", "documents.download", "receipts.view", "receipts.download"]),
  CUSTOM: map([])
};

async function main() {
  for (const role of roles) {
    for (const permissionKey of allPermissionKeys) {
      await prisma.rolePermission.upsert({
        where: { role_permissionKey: { role, permissionKey } },
        update: { allowed: defaults[role][permissionKey] },
        create: { role, permissionKey, allowed: defaults[role][permissionKey] }
      });
    }
  }

  const projects = await prisma.project.findMany({ select: { id: true, ownerId: true } });
  for (const project of projects) {
    await prisma.projectUser.upsert({
      where: { projectId_userId: { projectId: project.id, userId: project.ownerId } },
      update: { role: "OWNER", status: "ACTIVE" },
      create: { projectId: project.id, userId: project.ownerId, role: "OWNER", status: "ACTIVE" }
    });
  }

  console.log(`Backfilled ${roles.length} roles and ${projects.length} project owner assignments.`);
}

main()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
