import { describe, expect, it } from "vitest";

import {
  applyShellDecisionFloor,
  SHELL_TOOL_DECISION_FLOOR_PATTERN,
} from "#src/handlers/gates/shell-decision-floor";
import type { PermissionCheckResult, PermissionState } from "#src/types";

function check(state: PermissionState, source: PermissionCheckResult["source"] = "bash") {
  return {
    state,
    toolName: "bash",
    source,
    origin: source === "session" ? ("session" as const) : ("global" as const),
    command: "pwd",
    matchedPattern: source === "session" ? "pwd" : "*",
  } satisfies PermissionCheckResult;
}

describe("applyShellDecisionFloor", () => {
  it("raises allow to ask", () => {
    expect(applyShellDecisionFloor(check("allow"), "ask")).toEqual({
      ...check("allow"),
      state: "ask",
      source: "bash",
      matchedPattern: SHELL_TOOL_DECISION_FLOOR_PATTERN,
      reason: undefined,
    });
  });

  it("raises a session allow to ask without retaining the session fast path", () => {
    const result = applyShellDecisionFloor(check("allow", "session"), "ask");
    expect(result.state).toBe("ask");
    expect(result.source).toBe("bash");
    expect(result.matchedPattern).toBe(SHELL_TOOL_DECISION_FLOOR_PATTERN);
  });

  it.each(["ask", "deny"] as const)("preserves an existing %s", (state) => {
    const original = check(state);
    expect(applyShellDecisionFloor(original, "ask")).toBe(original);
  });

  it("does nothing when no floor is configured", () => {
    const original = check("allow");
    expect(applyShellDecisionFloor(original, undefined)).toBe(original);
  });
});
