import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import {
  loadManifest,
  validateSlotContent,
  correctSlotContent,
  summarizeValidationIssues,
} from "@mandujs/core";
import { getProjectPaths, isInsideProject } from "../utils/project.js";
import path from "path";

export const slotToolDefinitions: Tool[] = [
  {
    name: "mandu.slot.read",
    annotations: {
      readOnlyHint: true,
    },
    description:
      "Read the TypeScript source of a route's slot file and validate its structure.",
    inputSchema: {
      type: "object",
      properties: {
        routeId: {
          type: "string",
          description: "The route ID whose slot file to read (use mandu_list_routes to find IDs)",
        },
      },
      required: ["routeId"],
    },
  },
  {
    name: "mandu.slot.validate",
    annotations: {
      readOnlyHint: true,
    },
    description:
      "Validate TypeScript slot content against structural rules without writing files. Returns errors, warnings, and auto-fix previews.",
    inputSchema: {
      type: "object",
      properties: {
        content: {
          type: "string",
          description: "The TypeScript slot source code to validate",
        },
      },
      required: ["content"],
    },
  },
];

export function slotTools(projectRoot: string) {
  const paths = getProjectPaths(projectRoot);

  const handlers: Record<string, (args: Record<string, unknown>) => Promise<unknown>> = {
    "mandu.slot.read": async (args: Record<string, unknown>) => {
      const { routeId } = args as { routeId: string };

      // Load manifest to find the route
      const manifestResult = await loadManifest(paths.manifestPath);
      if (!manifestResult.success || !manifestResult.data) {
        return { error: manifestResult.errors };
      }

      const route = manifestResult.data.routes.find((r) => r.id === routeId);
      if (!route) {
        return { error: `Route not found: ${routeId}` };
      }

      if (!route.slotModule) {
        return {
          error: `Route '${routeId}' does not have a slotModule defined`,
          tip: "Add slotModule to the route spec or use mandu_update_route",
        };
      }

      const slotPath = path.join(projectRoot, route.slotModule);

      // Security check
      if (!isInsideProject(slotPath, projectRoot)) {
        return { error: "Slot path is outside project directory" };
      }

      try {
        const file = Bun.file(slotPath);
        if (!(await file.exists())) {
          return {
            exists: false,
            slotPath: route.slotModule,
            message: "Slot file does not exist. Run mandu.generate to create it.",
          };
        }

        const content = await file.text();

        // Validate existing slot content structure
        const validation = validateSlotContent(content);

        return {
          exists: true,
          slotPath: route.slotModule,
          content,
          lineCount: content.split("\n").length,
          validation: {
            valid: validation.valid,
            summary: summarizeValidationIssues(validation.issues),
            issues: validation.issues,
          },
        };
      } catch (error) {
        return {
          error: `Failed to read slot file: ${error instanceof Error ? error.message : String(error)}`,
        };
      }
    },

    "mandu.slot.validate": async (args: Record<string, unknown>) => {
      const { content } = args as { content: string };

      const validation = validateSlotContent(content);

      // Classify issues by whether they can be auto-fixed
      const autoFixable = validation.issues.filter((i) => i.autoFixable);
      const manualFix = validation.issues.filter((i) => !i.autoFixable);

      // Generate correction preview for auto-fixable issues
      let correctionPreview = null;
      if (autoFixable.length > 0) {
        const correction = correctSlotContent(content, validation.issues);
        correctionPreview = {
          wouldFix: correction.appliedFixes.length,
          fixes: correction.appliedFixes,
          resultingContent:
            correction.corrected
              ? `(${correction.content.split("\n").length} lines after correction)`
              : null,
        };
      }

      return {
        valid: validation.valid,
        summary: summarizeValidationIssues(validation.issues),
        errors: validation.issues.filter((i) => i.severity === "error"),
        warnings: validation.issues.filter((i) => i.severity === "warning"),
        autoFixable: autoFixable.map((i) => ({
          code: i.code,
          message: i.message,
          line: i.line,
        })),
        manualFixRequired: manualFix.map((i) => ({
          code: i.code,
          message: i.message,
          suggestion: i.suggestion,
          line: i.line,
        })),
        correctionPreview,
        tip: validation.valid
          ? "Content is valid. Use Edit tool to write the slot file."
          : autoFixable.length > 0
            ? "Auto-fixable issues found. Apply corrections and use Edit tool to write."
            : "Manual fixes required before writing. Use Edit tool after fixing.",
      };
    },
  };

  // Backward-compatible aliases
  handlers["mandu_read_slot"] = handlers["mandu.slot.read"];
  handlers["mandu_validate_slot"] = handlers["mandu.slot.validate"];

  return handlers;
}
