/**
 * Permission compatibility exports.
 *
 * ADR-0019 moves production authorization behind PrincipalResolver +
 * PermissionAuthorizer. The wrappers below preserve the old helper names for
 * tests and incremental callers while routing project trigger checks through
 * the new authorizer.
 */
import type { PrismaClient } from "@prisma/client";
import { createPermissionAuthorizer } from "./permissions/authorizer.js";
import { inactiveOrganizationReason } from "./org/status.js";

export { createPermissionAuthorizer, PrismaPermissionAuthorizer, roleGrantsEdit } from "./permissions/authorizer.js";
export { PrismaPrincipalResolver, principalKey } from "./permissions/principals.js";
export { syncExternalPrincipalMemberships } from "./permissions/externalSync.js";
export { grantTeamProjectAccess, listProjectTeamAccess, revokeTeamProjectAccess } from "./permissions/projectTeamAccess.js";
export type {
  AuthorizationAction,
  AuthorizationDecision,
  AuthorizationRequest,
  AuthorizationResource,
  PermissionAuthorizer,
} from "./permissions/authorizer.js";
export type {
  ActorInput,
  PrincipalRef,
  PrincipalResolution,
  PrincipalResolver,
  ResolvedPrincipal,
} from "./permissions/principals.js";
export type {
  ExternalPrincipalMembershipInput,
  ExternalPrincipalType,
  SyncExternalPrincipalMembershipsInput,
  SyncExternalPrincipalMembershipsResult,
} from "./permissions/externalSync.js";
export type {
  GrantTeamProjectAccessInput,
  ProjectTeamAccessEntry,
  RevokeTeamProjectAccessInput,
} from "./permissions/projectTeamAccess.js";

export interface PermissionResult {
  readonly allowed: boolean;
  readonly reason: string;
}

export async function canTriggerAgent(
  prisma: PrismaClient,
  projectId: string,
  principal: string,
): Promise<PermissionResult> {
  try {
    const decision = await createPermissionAuthorizer(prisma).can({
      actor: { feishuOpenId: principal },
      action: "agent.trigger",
      resource: { type: "PROJECT", id: projectId },
    });
    return { allowed: decision.allowed, reason: decision.reason };
  } catch (e) {
    return { allowed: false, reason: `permission check failed: ${e instanceof Error ? e.message : String(e)}` };
  }
}

/**
 * Role-only legacy helper. New trigger code uses `role.trigger` on
 * PermissionAuthorizer so project edit+ and role grant composition happen in
 * one decision.
 */
export async function canTriggerRole(
  prisma: PrismaClient,
  projectId: string,
  roleId: string,
  principal: string,
): Promise<PermissionResult> {
  try {
    const project = await prisma.project.findUnique({
      where: { id: projectId },
      select: { organization: { select: { id: true, status: true } } },
    });
    if (project === null) return { allowed: false, reason: `project not found: ${projectId}` };
    const inactiveReason = inactiveOrganizationReason(project.organization.id, project.organization.status);
    if (inactiveReason !== undefined) return { allowed: false, reason: inactiveReason };
    const anyGrant = await prisma.roleTriggerGrant.findFirst({
      where: { projectId, roleId },
      select: { id: true },
    });
    if (anyGrant === null) {
      return { allowed: true, reason: `role ${roleId} unconfigured on project (open)` };
    }
    const grant = await prisma.roleTriggerGrant.findFirst({
      where: { projectId, roleId, principalType: "USER", principalId: principal, revokedAt: null },
      select: { id: true },
    });
    if (grant !== null) {
      return { allowed: true, reason: `granted role ${roleId}` };
    }
    return {
      allowed: false,
      reason: `no active ${roleId} grant for ${principal} on project ${projectId}`,
    };
  } catch (e) {
    return { allowed: false, reason: `role permission check failed: ${e instanceof Error ? e.message : String(e)}` };
  }
}
