import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";
import { z } from "zod";

const API_BASE_URL = process.env.PLANILLA_API_URL || "http://localhost:4000";

async function fetchJSON(path, options = {}) {
  const res = await fetch(`${API_BASE_URL}${path}`, {
    headers: {
      'Content-Type': 'application/json'
    },
    ...options
  });
  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`API request failed (${res.status}): ${txt}`);
  }
  return res.json();
}

function createServer() {
  const server = new McpServer({
    name: "planilla-mcp",
    version: "0.1.0",
  });

  // ----- Resources -----
  // List all planillas
  server.resource(
    "planilla-list",
    "planilla://list",
    async (uri) => {
      const planillas = await fetchJSON('/api/planillas');
      return {
        contents: [{ uri: uri.href, text: JSON.stringify(planillas) }]
      };
    }
  );

  // Get planilla by ID
  server.resource(
    "planilla",
    new ResourceTemplate("planilla://{id}", { list: undefined }),
    async (uri, { id }) => {
      const planilla = await fetchJSON(`/api/planillas/${id}`);
      return {
        contents: [{ uri: uri.href, text: JSON.stringify(planilla) }]
      };
    }
  );

  // ----- Tools -----
  // Create a new planilla
  server.tool(
    "create-planilla",
    "Crea una planilla",
    {
      empleado_id: z.number(),
      fecha_desde: z.string(),
      fecha_hasta: z.string(),
      titulo: z.string(),
      total: z.number().optional(),
      estado: z.string().optional(),
      fecha_anulado: z.string().optional(),
      creador_id: z.number().optional(),
      anulador_id: z.number().optional(),
    },
    async (params) => {
      const body = JSON.stringify(params);
      const planilla = await fetchJSON('/api/planillas', { method: 'POST', body });
      return { content: [{ type: 'text', text: JSON.stringify(planilla) }] };
    }
  );

  // Update planilla by ID
  server.tool(
    "update-planilla",
    "Actualiza una planilla existente",
    {
      id: z.number(),
      empleado_id: z.number().optional(),
      fecha_desde: z.string().optional(),
      fecha_hasta: z.string().optional(),
      titulo: z.string().optional(),
      total: z.number().optional(),
      estado: z.string().optional(),
      fecha_anulado: z.string().optional(),
      anulador_id: z.number().optional(),
    },
    async ({ id, ...updates }) => {
      const body = JSON.stringify(updates);
      const planilla = await fetchJSON(`/api/planillas/${id}`, {
        method: 'PUT',
        body,
      });
      return { content: [{ type: 'text', text: JSON.stringify(planilla) }] };
    }
  );

  // Delete planilla by ID
  server.tool(
    "delete-planilla",
    "Elimina una planilla",
    { id: z.number() },
    async ({ id }) => {
      await fetchJSON(`/api/planillas/${id}`, { method: 'DELETE' });
      return { content: [{ type: 'text', text: `Planilla ${id} eliminada` }] };
    }
  );

  return server;
}

async function main() {
  const useStdio = process.argv.includes("--stdio");
  if (useStdio) {
    const server = createServer();
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.log("MCP Planilla server listo (stdio)");
  } else {
    const app = express();
    app.use(express.json());
    const port = process.env.PORT || 5000;

    app.post("/mcp", async (req, res) => {
      try {
        const server = createServer();
        const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
        res.on("close", () => {
          transport.close();
          server.close();
        });
        await server.connect(transport);
        await transport.handleRequest(req, res, req.body);
      } catch (error) {
        console.error("Error handling MCP request:", error);
        if (!res.headersSent) {
          res.status(500).json({
            jsonrpc: "2.0",
            error: { code: -32603, message: "Internal server error" },
            id: null,
          });
        }
      }
    });

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

    app.delete("/mcp", async (_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(`MCP Planilla HTTP server listening on port ${port}`);
    });
  }
}

main().catch((err) => {
  console.error("Error fatal en MCP server:", err);
  process.exit(1);
});
