/**
 * Narrow permission policy for Orb sessions.
 *
 * Denies merge, production deployment, secret access, and external
 * communications. Allows all other operations. Used as the callback for
 * ACP permission_request events with permissionPolicy: "ask".
 */

interface PermissionOption {
  readonly id: string;
  readonly title?: string;
  readonly description?: string;
}

interface PermissionRequestLike {
  readonly requestId: string;
  readonly options?: readonly PermissionOption[];
  readonly toolCall?: {
    readonly title?: string;
    readonly kind?: string;
    readonly name?: string;
  };
}

const DENY_PATTERNS = [
  /\bmerge\b/iu,
  /\bdeploy\b.*\bprod/iu,
  /\bproduction\b/iu,
  /\bsecret/iu,
  /\bcredential/iu,
  /\bpassword\b/iu,
  /\bapi[_-]?key\b/iu,
  /\bpush\s+to\s+(?<branch>main|master)\b/iu,
];

/** Evaluate whether a permission request is dangerous. */
export const isDangerousPermission = (
  request: PermissionRequestLike
): boolean => {
  const text = [
    request.toolCall?.title,
    request.toolCall?.kind,
    request.toolCall?.name,
  ]
    .filter((s): s is string => typeof s === "string")
    .join(" ");
  return DENY_PATTERNS.some((pattern) => pattern.test(text));
};

/**
 * Pick the option ID that matches the desired decision. Falls back to the
 * last option (typically deny) for safety when no explicit deny option exists,
 * or the first option (typically allow) when no explicit allow option exists.
 */
const pickOption = (
  options: readonly PermissionOption[],
  allow: boolean
): string | undefined => {
  if (options.length === 0) {
    return undefined;
  }
  if (allow) {
    const match = options.find(
      (o) =>
        /allow|accept|yes|permit/iu.test(o.title ?? "") ||
        /allow|accept|yes|permit/iu.test(o.description ?? "")
    );
    return match?.id ?? options[0]?.id;
  }
  const match = options.find(
    (o) =>
      /deny|reject|no|cancel/iu.test(o.title ?? "") ||
      /deny|reject|no|cancel/iu.test(o.description ?? "")
  );
  return match?.id ?? options.at(-1)?.id;
};

export interface PermissionDecision {
  readonly allow: boolean;
  readonly optionId: string | undefined;
}

/** Evaluate a permission request and return the decision. */
export const evaluatePermission = (
  request: PermissionRequestLike
): PermissionDecision => {
  const dangerous = isDangerousPermission(request);
  const optionId = pickOption(request.options ?? [], !dangerous);
  return { allow: !dangerous, optionId };
};
