#!/usr/bin/env node

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { logger } from "hono/logger";
import open from "open";
import { registerInspectorRoutes } from "./shared-routes.js";
import type { InspectorMode } from "./shared-static.js";
import { registerStaticRoutes } from "./shared-static.js";
import { setServerPort } from "./tunnel.js";
import { findAvailablePort, isValidUrl } from "./utils.js";
import { getInspectorVersion } from "./version.js";

// Parse command line arguments
const args = process.argv.slice(2);
let mcpUrl: string | undefined;
let startPort = 8080;
let noOpen = false;

for (let i = 0; i < args.length; i++) {
  if (args[i] === "--url") {
    if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
      console.error("Error: --url requires a value");
      process.exit(1);
    }
    const url = args[i + 1];
    if (!isValidUrl(url)) {
      console.error(`Error: Invalid URL format: ${url}`);
      console.error("URL must start with http://, https://, ws://, or wss://");
      process.exit(1);
    }
    mcpUrl = url;
    i++;
  } else if (args[i] === "--port") {
    if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
      console.error("Error: --port requires a value");
      process.exit(1);
    }
    const parsedPort = Number.parseInt(args[i + 1], 10);
    if (Number.isNaN(parsedPort) || parsedPort < 1 || parsedPort > 65535) {
      console.error(
        `Error: Port must be a number between 1 and 65535, got: ${args[i + 1]}`
      );
      process.exit(1);
    }
    startPort = parsedPort;
    i++;
  } else if (args[i] === "--no-open") {
    noOpen = true;
  } else if (args[i] === "--version" || args[i] === "-v") {
    console.log(getInspectorVersion());
    process.exit(0);
  } else if (args[i] === "--help" || args[i] === "-h") {
    console.log(`
MCP Inspector - Inspect and debug MCP servers

Usage:
  npx @mcp-use/inspector [options]

Options:
  --url <url>    MCP server URL to auto-connect to (e.g., http://localhost:3000/mcp)
  --port <port>  Starting port to try (default: 8080, will find next available)
  --no-open      Do not auto-open inspector in browser
  --version, -v  Show the inspector version
  --help, -h     Show this help message

Examples:
  # Run inspector with auto-connect
  npx @mcp-use/inspector --url http://localhost:3000/mcp

  # Run starting from custom port
  npx @mcp-use/inspector --url http://localhost:3000/mcp --port 9000

  # Run without auto-connect
  npx @mcp-use/inspector
`);
    process.exit(0);
  } else {
    console.error(`Error: Unknown option: ${args[i]}`);
    console.error("Run with --help to see available options.");
    process.exit(1);
  }
}

const app = new Hono();

// Middleware - expose mcp-session-id for cross-origin requests (FastMCP session management)
app.use(
  "*",
  cors({
    origin: "*",
    exposeHeaders: ["*"], // Expose all headers since this is a proxy
  })
);
// Apply logger middleware only to proxy routes
app.use("/inspector/api/proxy/*", logger());

registerInspectorRoutes(app, { autoConnectUrl: mcpUrl });

// Detect the deployment mode. The same CLI binary powers both local standalone
// usage (`npx @mcp-use/inspector`) and the cloud-hosted Railway deployment at
// inspector.mcpus.com — Railway sets RAILWAY_ENVIRONMENT_NAME, so we use that
// as the primary cloud signal, with an explicit MCP_INSPECTOR_MODE override
// for other hosted environments.
const inspectorMode: InspectorMode =
  (process.env.MCP_INSPECTOR_MODE as InspectorMode | undefined) ??
  (process.env.RAILWAY_ENVIRONMENT_NAME ? "cloud" : "standalone");

// Register static file serving (must be last as it includes catch-all route).
// Runtime env vars here override what was baked in at `vite build` time — this
// lets a single pre-built npm tarball be configured per deploy.
registerStaticRoutes(app, undefined, {
  inspectorMode,
  manufactChatUrl: process.env.MANUFACT_CHAT_URL,
});

// Start the server with automatic port selection
async function startServer() {
  try {
    const port = await findAvailablePort(startPort);
    serve({
      fetch: app.fetch,
      port,
    });
    setServerPort(port);
    console.log(`🚀 MCP Inspector running on http://localhost:${port}`);
    if (mcpUrl) {
      console.log(`📡 Auto-connecting to: ${mcpUrl}`);
    }
    // Auto-open browser (unless --no-open flag is present)
    if (!noOpen) {
      try {
        await open(`http://localhost:${port}/inspector`);
        console.log(`🌐 Browser opened`);
      } catch {
        console.log(
          `🌐 Please open http://localhost:${port}/inspector in your browser`
        );
      }
    }
    return { port, fetch: app.fetch };
  } catch (error) {
    console.error("Failed to start server:", error);
    process.exit(1);
  }
}

// Start the server
startServer();
