/** Claude Agent SDK PreToolUse hook that checks HANRIA before execution. */

import { query, type HookCallback, type HookCallbackMatcher, type Options } from "@anthropic-ai/claude-agent-sdk";
import { pathToFileURL } from "node:url";

const CHECK_URL = "https://check.hanria.ai/v1/check";
const MANDATE = {
  schema_version: "0.2-draft",
  mandate_id: "review-tool-calls",
  purpose: "Permit file reads under the example directory.",
  default: "deny",
  clauses: [{
    id: "permit-example-read",
    effect: "permit",
    match: { kind: ["file"], verb: ["read"], target_prefix: ["/tmp/example/"] },
  }],
};

type FetchLike = typeof globalThis.fetch;

export async function checkAction(
  action: Record<string, unknown>,
  checkUrl = CHECK_URL,
  fetchImpl: FetchLike = globalThis.fetch,
): Promise<Record<string, unknown>> {
  try {
    const response = await fetchImpl(checkUrl, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ mandate: MANDATE, action }),
      signal: AbortSignal.timeout(10000),
    });
    if (!response.ok) return { outcome: "error", reason: `HANRIA returned HTTP ${response.status}` };
    const decision = await response.json() as Record<string, unknown>;
    if (!["permit", "deny", "escalate", "error"].includes(String(decision.outcome))) {
      return { outcome: "error", reason: "HANRIA returned an invalid decision" };
    }
    return decision;
  } catch (error) {
    return { outcome: "error", reason: `HANRIA check failed: ${String(error)}` };
  }
}

export function createHanriaHook({
  checkUrl = CHECK_URL,
  fetchImpl = globalThis.fetch,
}: { checkUrl?: string; fetchImpl?: FetchLike } = {}): HookCallback {
  return async (input) => {
    if (input.hook_event_name !== "PreToolUse") {
      return { continue: false, stopReason: "Expected a PreToolUse event" };
    }
    const toolInput = input.tool_input as Record<string, unknown>;
    const action = {
      schema_version: "0.1-draft",
      requested_by: { agent: "claude-agent-sdk-example" },
      operation: {
        kind: input.tool_name === "Read" ? "file" : "tool",
        verb: input.tool_name === "Read" ? "read" : input.tool_name,
        target: String(toolInput.file_path ?? toolInput.path ?? input.tool_name),
      },
      justification: `Run ${input.tool_name} through the Claude Agent SDK.`,
    };
    const decision = await checkAction(action, checkUrl, fetchImpl);
    if (decision.outcome === "permit") return {};
    return {
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "deny",
        permissionDecisionReason: `HANRIA returned ${String(decision.outcome ?? "error")}: ${String(decision.reason ?? "no reason returned")}`,
      },
    };
  };
}

export function createHookOptions(settings: { checkUrl?: string; fetchImpl?: FetchLike } = {}): Options {
  const matcher: HookCallbackMatcher = { hooks: [createHanriaHook(settings)] };
  return { hooks: { PreToolUse: [matcher] } };
}

export function constructQuery(prompt: string, options = createHookOptions()) {
  return query({ prompt, options });
}

if (process.argv[1] && pathToFileURL(process.argv[1]).href === import.meta.url) {
  const options = createHookOptions();
  console.log(`Constructed ${options.hooks?.PreToolUse?.length ?? 0} HANRIA PreToolUse hook matcher.`);
}
