import type { UserRole } from "@/lib/auth";

export type ActionPermission =
  | "admin:read"
  | "admin:manage"
  | "agent:read"
  | "agent:manage"
  | "inbox:read"
  | "inbox:assign"
  | "inbox:status"
  | "inbox:reply"
  | "inbox:notes"
  | "inbox:tags"
  | "tenant:read"
  | "profile:manage_self";

type AllPermission = ActionPermission | "*";

const rolePermissions: Record<UserRole, readonly AllPermission[]> = {
  super_admin: ["*", "admin:read", "admin:manage", "agent:read", "agent:manage", "inbox:read", "inbox:assign", "inbox:status", "inbox:reply", "inbox:notes", "inbox:tags", "tenant:read"],
  admin_client: [
    "admin:read",
    "admin:manage",
    "inbox:read",
    "inbox:assign",
    "inbox:status",
    "inbox:reply",
    "inbox:notes",
    "inbox:tags",
    "agent:read",
    "tenant:read",
    "profile:manage_self"
  ],
  agent: [
    "agent:read",
    "inbox:read",
    "inbox:assign",
    "inbox:status",
    "inbox:reply",
    "inbox:notes",
    "inbox:tags",
    "profile:manage_self"
  ]
};

function toPermissionSet(role: UserRole) {
  return new Set<AllPermission | string>(rolePermissions[role]);
}

export function hasPermission(role: UserRole, permission: ActionPermission) {
  const permissionSet = toPermissionSet(role);
  return permissionSet.has("*") || permissionSet.has(permission);
}

export function hasPermissionWithGrants(role: UserRole, permission: ActionPermission, extraPermissions?: Iterable<string>) {
  const permissionSet = toPermissionSet(role);
  if (extraPermissions) {
    for (const value of extraPermissions) {
      permissionSet.add(value);
    }
  }
  return permissionSet.has("*") || permissionSet.has(permission);
}

export function assertPermission(role: UserRole, permission: ActionPermission, extraPermissions?: Iterable<string>) {
  if (!hasPermissionWithGrants(role, permission, extraPermissions)) {
    return false;
  }

  return true;
}
