// Copyright (C) 2026 Rob Colbert <rob.colbert@openplatform.us>
// Licensed under the Apache License, Version 2.0

import path from "node:path";

import { formatError, type IToolError } from "@gadget/ai";
import type { AiToolbox } from "../toolbox.ts";
import { getProjectRoot, toolError } from "../system/common.ts";

export interface ResolvedPlanPath {
  inputPath: string;
  absolutePath: string;
  displayPath: string;
}

export function getGadgetDir(toolbox: AiToolbox): string | undefined {
  const projectRoot = getProjectRoot(toolbox);
  if (!projectRoot) return undefined;
  return path.resolve(projectRoot, ".gadget");
}

export function resolvePlanPath(
  toolbox: AiToolbox,
  inputPath: string,
): ResolvedPlanPath | string {
  const gadgetDir = getGadgetDir(toolbox);
  if (!gadgetDir) {
    return toolError({
      code: "OPERATION_NOT_ALLOWED",
      message: "No active project workspace is configured for plan file tools.",
      recoveryHint: "Run this tool during an active Agent work order in Plan mode.",
    });
  }

  const trimmedPath = inputPath.trim();
  if (!trimmedPath) {
    return toolError({
      code: "MISSING_PARAMETER",
      message: "File path must not be empty.",
      parameter: "path",
      recoveryHint: "Provide a valid file path within the .gadget directory.",
    });
  }

  const absolutePath = path.isAbsolute(trimmedPath)
    ? path.resolve(trimmedPath)
    : path.resolve(gadgetDir, trimmedPath);
  const relative = path.relative(gadgetDir, absolutePath);

  if (relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))) {
    return {
      inputPath: trimmedPath,
      absolutePath,
      displayPath: relative || ".",
    };
  }

  return toolError({
    code: "SECURITY_VIOLATION",
    message: `Path is outside the .gadget directory: ${trimmedPath}`,
    parameter: "path",
    recoveryHint: "Use a relative path inside the project's .gadget directory.",
  });
}
