import type { UpstreamConnection, JsonRpcRequest, JsonRpcResponse } from '../types.js';
import type { McpdClient } from '../http/mcpd-client.js';

interface McpdProxyRequest {
  serverId: string;
  method: string;
  params?: Record<string, unknown> | undefined;
}

interface McpdProxyResponse {
  result?: unknown;
  error?: { code: number; message: string; data?: unknown };
}

/**
 * An upstream that routes MCP requests through mcpd's /api/v1/mcp/proxy endpoint.
 * mcpd holds the credentials and manages the actual MCP server connections.
 */
export class McpdUpstream implements UpstreamConnection {
  readonly name: string;
  readonly description?: string;
  private alive = true;

  constructor(
    private serverId: string,
    serverName: string,
    private mcpdClient: McpdClient,
    serverDescription?: string,
  ) {
    this.name = serverName;
    if (serverDescription !== undefined) this.description = serverDescription;
  }

  async send(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    if (!this.alive) {
      return {
        jsonrpc: '2.0',
        id: request.id,
        error: { code: -32603, message: `Upstream '${this.name}' is closed` },
      };
    }

    const proxyRequest: McpdProxyRequest = {
      serverId: this.serverId,
      method: request.method,
      params: request.params,
    };

    try {
      const result = await this.mcpdClient.post<McpdProxyResponse>('/api/v1/mcp/proxy', proxyRequest);
      if (result.error) {
        return { jsonrpc: '2.0', id: request.id, error: result.error };
      }
      return { jsonrpc: '2.0', id: request.id, result: result.result };
    } catch (err) {
      return {
        jsonrpc: '2.0',
        id: request.id,
        error: { code: -32603, message: `mcpd proxy error: ${(err as Error).message}` },
      };
    }
  }

  async close(): Promise<void> {
    this.alive = false;
  }

  isAlive(): boolean {
    return this.alive;
  }
}
