#!/usr/bin/env node

process.env.MCP_HTTP = "1";

import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import { createServer } from "./index.js";

const PORT = parseInt(process.env.MCP_PORT ?? "3902", 10);

const app = createMcpExpressApp({ host: "0.0.0.0" });

const AUTH_FREE_METHODS = new Set(["initialize", "notifications/initialized", "tools/list"]);
const AUTH_FREE_TOOLS = new Set(["get_setup_guide"]);

app.post("/mcp", async (req, res) => {
  const body = req.body;
  const method = body?.method as string | undefined;
  const toolName = method === "tools/call" ? (body?.params?.name as string | undefined) : undefined;
  const isAuthFree = (method != null && AUTH_FREE_METHODS.has(method))
    || (toolName != null && AUTH_FREE_TOOLS.has(toolName));

  const apiKey = (req.headers["x-api-key"] as string | undefined)
    ?? (req.query?.apikey as string | undefined);

  if (!apiKey && !isAuthFree) {
    res.status(401).json({
      jsonrpc: "2.0",
      error: { code: -32001, message: "Missing API key. Pass via X-API-Key header or ?apikey= query parameter." },
      id: body?.id ?? null,
    });
    return;
  }

  const server = createServer(apiKey ?? "");
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: undefined,
  });
  await server.connect(transport);
  await transport.handleRequest(req, res, body);
  res.on("close", () => {
    transport.close();
    server.close();
  });
});

app.get("/mcp", (_req, res) => {
  res.writeHead(405).end(JSON.stringify({
    jsonrpc: "2.0",
    error: { code: -32000, message: "Method not allowed." },
    id: null,
  }));
});

app.delete("/mcp", (_req, res) => {
  res.writeHead(405).end(JSON.stringify({
    jsonrpc: "2.0",
    error: { code: -32000, message: "Method not allowed." },
    id: null,
  }));
});

app.listen(PORT, () => {
  console.log(`SwapWizard MCP HTTP server listening on port ${PORT}`);
});

process.on("SIGINT", () => {
  process.exit(0);
});
