#!/usr/bin/env node

import * as http from 'http';
import { EventEmitter } from 'node:events';
import cors from 'cors';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';

export class SSESession extends EventEmitter {
  public id: string;
  private response: http.ServerResponse;
  private heartbeatInterval: NodeJS.Timeout;

  constructor(response: http.ServerResponse) {
    super();
    this.id = Math.random().toString(36).substring(2, 15);
    this.response = response;
    
    // Setup heartbeat
    this.heartbeatInterval = setInterval(() => {
      this.sendEvent('heartbeat', { timestamp: Date.now() });
    }, 30000);
  }

  public sendEvent(type: string, data: any): void {
    this.response.write(`event: ${type}\n`);
    this.response.write(`data: ${JSON.stringify(data)}\n\n`);
  }

  public close(): void {
    clearInterval(this.heartbeatInterval);
    this.response.end();
  }
}

export class SSEMCPServer extends EventEmitter {
  private server: http.Server;
  private sessions: Map<string, SSESession> = new Map();
  private mcpServer: Server;

  constructor() {
    super();
    this.mcpServer = new Server({
      name: 'trackex-mcp-server',
      version: '1.0.0',
      capabilities: {
        tools: {},
      },
    });
    this.server = http.createServer();
    this.setupServer();
  }

  private setupServer(): void {
    // Enable CORS for all routes
    const corsMiddleware = cors({
      origin: ['https://claude.ai', 'http://localhost:3000'],
      methods: ['GET', 'POST', 'OPTIONS'],
      allowedHeaders: ['Content-Type', 'Authorization'],
      credentials: true
    });

    this.server.on('request', (req: http.IncomingMessage, res: http.ServerResponse) => {
      // Handle CORS preflight
      if (req.method === 'OPTIONS') {
        corsMiddleware(req, res, () => {
          res.writeHead(204);
          res.end();
        });
        return;
      }

      // Handle SSE connection
      if (req.method === 'GET' && req.url === '/events') {
        this.handleSSEConnection(req, res);
        return;
      }

      // Handle MCP requests
      if (req.method === 'POST') {
        let body = '';
        req.on('data', chunk => {
          body += chunk.toString();
        });
        req.on('end', () => {
          this.handleMCPRequest(req, res, body);
        });
        return;
      }

      res.writeHead(404);
      res.end();
    });
  }

  private handleSSEConnection(req: http.IncomingMessage, res: http.ServerResponse): void {
    const session = new SSESession(res);
    this.sessions.set(session.id, session);
    
    // Set SSE headers
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
      'Access-Control-Allow-Origin': 'https://claude.ai',
      'Access-Control-Allow-Credentials': 'true'
    });

    // Send initial connection message
    session.sendEvent('connected', { sessionId: session.id });

    // Handle client disconnect
    req.on('close', () => {
      this.sessions.delete(session.id);
      this.emit('sessionDisconnected', session);
    });
  }

  private async handleMCPRequest(req: http.IncomingMessage, res: http.ServerResponse, body: string): Promise<void> {
    try {
      const request = JSON.parse(body);
      const session = this.sessions.get(request.params?.sessionId);

      if (!session) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: 'Invalid session' }));
        return;
      }

      // Process the request and send response
      const response = {
        jsonrpc: '2.0',
        id: request.id,
        result: {
          success: true,
          message: 'Request processed successfully'
        }
      };
      
      session.sendEvent('mcp-response', response);
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ success: true }));
    } catch (error) {
      res.writeHead(400);
      res.end(JSON.stringify({ error: 'Invalid request' }));
    }
  }

  public async start(port: number = 3334): Promise<void> {
    return new Promise((resolve, reject) => {
      this.server.listen(port, (error?: Error) => {
        if (error) {
          reject(error);
        } else {
          console.log(`🚀 SSE MCP Server started on port ${port}`);
          resolve();
        }
      });
    });
  }

  public async stop(): Promise<void> {
    return new Promise((resolve, reject) => {
      this.server.close((error?: Error) => {
        if (error) {
          reject(error);
        } else {
          console.log('SSE MCP Server stopped');
          resolve();
        }
      });
    });
  }
} 