import type { AccessPath } from "#src/access-intent/access-path";
import type { ScopedPermissionResolver } from "#src/permission-resolver";
import type { PermissionCheckResult } from "#src/types";
import { pickMostRestrictive } from "./candidate-check";

/** An external path whose resolved `external_directory` state is not "allow". */
export interface UncoveredExternalPath {
  path: AccessPath;
  check: PermissionCheckResult;
}

/** The uncovered external paths plus the most restrictive check among them. */
export interface UncoveredExternalPaths {
  uncovered: UncoveredExternalPath[];
  /** Worst check among uncovered paths; `undefined` only when none are uncovered. */
  worstCheck: PermissionCheckResult | undefined;
}

/**
 * Resolve one external path's policy on the `external_directory` surface.
 *
 * Emits an `access-path` {@link AccessIntent}; the resolver unwraps it via
 * {@link AccessPath.matchValues} so a config pattern on either the typed or
 * symlink-resolved alias applies (#418). This is the single source for the
 * external-directory resolve that the two external-directory gates previously
 * duplicated.
 */
export function resolveExternalDirectoryPolicy(
  path: AccessPath,
  resolver: ScopedPermissionResolver,
  agentName: string | undefined,
): PermissionCheckResult {
  return resolver.resolve({
    kind: "access-path",
    surface: "external_directory",
    path,
    agentName,
  });
}

/**
 * Resolve a set of external paths and select those not already allowed.
 *
 * Each path is resolved via {@link resolveExternalDirectoryPolicy}; entries
 * whose state is not "allow" are collected (filtering on state, not source, so
 * config-level allow rules suppress the prompt just as session-level allow
 * rules do), and the most restrictive uncovered check is returned so a config
 * "deny" is not downgraded to the catch-all "ask".
 */
export function selectUncoveredExternalPaths(
  paths: readonly AccessPath[],
  resolver: ScopedPermissionResolver,
  agentName: string | undefined,
): UncoveredExternalPaths {
  const uncovered: UncoveredExternalPath[] = [];
  for (const path of paths) {
    const check = resolveExternalDirectoryPolicy(path, resolver, agentName);
    if (check.state !== "allow") {
      uncovered.push({ path, check });
    }
  }
  return {
    uncovered,
    worstCheck: pickMostRestrictive(uncovered.map(({ check }) => check)),
  };
}
