export const TENANT_PERMISSIONS = [
  "projects:view",
  "projects:create",
  "projects:edit",
  "projects:delete",
  "projects:publish",
  "media:manage",
  "services:manage",
  "journal:manage",
  "inquiries:manage",
  "seo:manage",
  "team:manage",
  "settings:manage",
  "domains:manage",
  "analytics:view",
  "billing:manage",
] as const;

export type TenantPermission = (typeof TENANT_PERMISSIONS)[number];

export type TenantRole = "owner" | "manager" | "editor" | "contributor";

export type PlatformRole =
  | "super_admin"
  | "platform_admin"
  | "support"
  | "none";

const ROLE_PERMISSIONS: Record<TenantRole, readonly TenantPermission[]> = {
  owner: TENANT_PERMISSIONS,
  manager: [
    "projects:view",
    "projects:create",
    "projects:edit",
    "projects:delete",
    "projects:publish",
    "media:manage",
    "services:manage",
    "journal:manage",
    "inquiries:manage",
    "seo:manage",
    "team:manage",
    "settings:manage",
    "domains:manage",
    "analytics:view",
  ],
  editor: [
    "projects:view",
    "projects:create",
    "projects:edit",
    "projects:publish",
    "media:manage",
    "services:manage",
    "journal:manage",
    "seo:manage",
  ],
  contributor: [
    "projects:view",
    "projects:create",
    "projects:edit",
    "media:manage",
  ],
};

export type AuthPrincipal = {
  userId: string;
  platformRole: PlatformRole;
  tenantMemberships: Array<{
    tenantId: string;
    role: TenantRole;
    permissions: string[];
    status: string;
  }>;
};

export type AuthorizationResult =
  | { allowed: true }
  | { allowed: false; reason: string };

export function permissionsForRole(role: TenantRole): TenantPermission[] {
  return [...ROLE_PERMISSIONS[role]];
}

export function hasPlatformAdminAccess(principal: AuthPrincipal): boolean {
  return (
    principal.platformRole === "super_admin" ||
    principal.platformRole === "platform_admin"
  );
}

/**
 * Central authorization check.
 * UI hiding is NEVER sufficient — always call this server-side.
 */
export function authorize(
  principal: AuthPrincipal,
  action: TenantPermission,
  resource: { tenantId: string },
): AuthorizationResult {
  if (hasPlatformAdminAccess(principal) && principal.platformRole === "super_admin") {
    return { allowed: true };
  }

  const membership = principal.tenantMemberships.find(
    (m) => m.tenantId === resource.tenantId && m.status === "active",
  );

  if (!membership) {
    return { allowed: false, reason: "Not a member of this tenant" };
  }

  const rolePerms = permissionsForRole(membership.role);
  const extra = membership.permissions ?? [];
  const effective = new Set<string>([...rolePerms, ...extra]);

  if (!effective.has(action)) {
    return { allowed: false, reason: `Missing permission: ${action}` };
  }

  return { allowed: true };
}

/**
 * Defense-in-depth ownership check for tenant-scoped resources.
 */
export function assertSameTenant(
  resourceTenantId: string,
  trustedTenantId: string,
): AuthorizationResult {
  if (resourceTenantId !== trustedTenantId) {
    return { allowed: false, reason: "Cross-tenant access denied" };
  }
  return { allowed: true };
}

export function requireAuthorization(
  result: AuthorizationResult,
): asserts result is { allowed: true } {
  if (!result.allowed) {
    const error = new Error(result.reason);
    error.name = "AuthorizationError";
    throw error;
  }
}
