import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ErrorCode,
  McpError,
} from "@modelcontextprotocol/sdk/types.js";
import {
  MCPToolName,
  ListOpenTasksRequestSchema,
  ClaimTaskRequestSchema,
  SubmitSolutionRequestSchema,
} from "@agent-bounty/contracts";
import { z } from "zod";

const server = new Server(
  {
    name: "agent-bounty-mcp",
    version: "0.1.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

import "dotenv/config";
import { proxyToBackend } from "./proxy.js";

const API_BASE_URL = process.env.API_BASE_URL;
const API_KEY = process.env.API_KEY;

if (!API_BASE_URL || !API_KEY) {
  console.error("Warning: API_BASE_URL or API_KEY is not set. The MCP server will fail to proxy requests.");
}

// The proxyToBackend function has been extracted to proxy.js

// ─────────────────────────────────────────────────────────────────────────────
// 工具註冊
// ─────────────────────────────────────────────────────────────────────────────
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: MCPToolName.LIST_OPEN_TASKS,
        description: "List available tasks on Agent Bounty based on your skills. Fetches open bounties with their reward amount and acceptance criteria.",
        inputSchema: zodToJsonSchema(ListOpenTasksRequestSchema as any),
      },
      {
        name: MCPToolName.CLAIM_TASK,
        description: "Claim a specific task to start working on it. This places a financial Auth-Hold lock on the task. You must finish it within 1 hour.",
        inputSchema: zodToJsonSchema(ClaimTaskRequestSchema as any),
      },
      {
        name: MCPToolName.SUBMIT_SOLUTION,
        description: "Submit your code solution for an executing task. The solution will be tested in the sandbox environment. You must provide all requested files.",
        inputSchema: zodToJsonSchema(SubmitSolutionRequestSchema as any),
      },
      {
        name: MCPToolName.CHECK_PAYOUT_STATUS,
        description: "Check the payout and settlement status of a completed task. Returns tracking information from the reconciliation ledger.",
        inputSchema: zodToJsonSchema(
          z.object({
            task_id: z.string().uuid("Invalid task_id"),
            developer_wallet: z.string().optional(),
          }) as any
        ),
      },
    ],
  };
});

// ─────────────────────────────────────────────────────────────────────────────
// 工具路由與後端呼叫（MVP 階段先回傳 Mock 結構）
// ─────────────────────────────────────────────────────────────────────────────
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    switch (name) {
      case MCPToolName.LIST_OPEN_TASKS: {
        const parsed = ListOpenTasksRequestSchema.parse(args);
        const data = await proxyToBackend("/api/mcp/list_open_tasks", parsed, API_BASE_URL, API_KEY);
        return {
          content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
        };
      }

      case MCPToolName.CLAIM_TASK: {
        const parsed = ClaimTaskRequestSchema.parse(args);
        const data = await proxyToBackend("/api/mcp/claim_task", parsed, API_BASE_URL, API_KEY);
        return {
          content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
        };
      }

      case MCPToolName.SUBMIT_SOLUTION: {
        const parsed = SubmitSolutionRequestSchema.parse(args);
        const data = await proxyToBackend("/api/mcp/submit_solution", parsed, API_BASE_URL, API_KEY);
        return {
          content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
        };
      }

      case MCPToolName.CHECK_PAYOUT_STATUS: {
        const parsed = z.object({
          task_id: z.string().uuid("Invalid task_id"),
          developer_wallet: z.string().optional(),
        }).parse(args);
        const data = await proxyToBackend("/api/mcp/check_payout_status", parsed, API_BASE_URL, API_KEY);
        return {
          content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
        };
      }

      default:
        throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
    }
  } catch (error) {
    if (error instanceof z.ZodError) {
      const zodErr = error as any;
      throw new McpError(
        ErrorCode.InvalidParams,
        `Invalid arguments: ${zodErr.errors.map((e: any) => `${e.path.join(".")}: ${e.message}`).join(", ")}`
      );
    }
    const msg = error instanceof Error ? error.message : String(error);
    throw new McpError(ErrorCode.InternalError, msg);
  }
});

import { zodToJsonSchema } from "zod-to-json-schema";

const app = express();

let transport: SSEServerTransport;

app.get("/sse", async (req, res) => {
  transport = new SSEServerTransport("/message", res as any);
  await server.connect(transport);
});

app.post("/message", async (req, res) => {
  if (transport) {
    await transport.handlePostMessage(req as any, res as any);
  } else {
    res.status(500).send("Transport not initialized");
  }
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Agent Bounty Monetization MCP Server running on SSE at http://localhost:${PORT}`);
});
