import { createInterface } from 'node:readline';
import type { JsonRpcRequest, JsonRpcResponse, JsonRpcNotification, JsonRpcMessage } from './types.js';
import type { McpRouter } from './router.js';

/**
 * STDIO-based MCP proxy server.
 *
 * Reads JSON-RPC messages from stdin and writes responses to stdout.
 * This is the transport that Claude Code uses to communicate with MCP servers.
 */
export class StdioProxyServer {
  private running = false;

  constructor(private router: McpRouter) {}

  start(): void {
    this.running = true;

    // Forward notifications from upstreams to client
    this.router.setNotificationHandler((notification) => {
      if (this.running) {
        this.sendNotification(notification);
      }
    });

    const rl = createInterface({ input: process.stdin });

    rl.on('line', (line) => {
      if (!this.running) return;

      this.handleLine(line).catch((err) => {
        process.stderr.write(`Proxy error: ${err}\n`);
      });
    });

    rl.on('close', () => {
      this.running = false;
    });
  }

  private async handleLine(line: string): Promise<void> {
    let msg: JsonRpcMessage;
    try {
      msg = JSON.parse(line) as JsonRpcMessage;
    } catch {
      return; // Skip invalid JSON
    }

    // Only handle requests (messages with an id)
    if (!('id' in msg) || msg.id === undefined) {
      // Notification - no response needed
      return;
    }

    const request = msg as JsonRpcRequest;
    const response = await this.router.route(request);
    this.sendResponse(response);
  }

  private sendResponse(response: JsonRpcResponse): void {
    process.stdout.write(JSON.stringify(response) + '\n');
  }

  private sendNotification(notification: JsonRpcNotification): void {
    process.stdout.write(JSON.stringify(notification) + '\n');
  }

  stop(): void {
    this.running = false;
  }
}
