/**
 * MCP Server: MT4 Connector
 *
 * Exposes MT4 trading capabilities as MCP tools for AI agents.
 * Communicates with mt4-gateway service to execute trading operations.
 *
 * @version 0.1.0
 * @author Trading Platform Trading Platform
 */

import express, { Request, Response, NextFunction } from 'express';
import dotenv from 'dotenv';
import { mcpToolSchemas, toolHandlers } from './tools';
import { getMT4Client } from './services/mt4-client';

// Load environment variables
dotenv.config();

const app = express();
const PORT = process.env.PORT || 3605;
const SERVICE_NAME = 'mcp-mt4-connector';
const VERSION = '0.1.0';

// ==========================================
// Middleware
// ==========================================

app.use(express.json());

// Request logging
app.use((req: Request, _res: Response, next: NextFunction) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
  next();
});

// ==========================================
// Health & Status Endpoints
// ==========================================

/**
 * Health check endpoint
 */
app.get('/health', async (_req: Request, res: Response) => {
  try {
    const client = getMT4Client();
    const mt4Connected = await client.isConnected();

    res.json({
      status: 'ok',
      service: SERVICE_NAME,
      version: VERSION,
      timestamp: new Date().toISOString(),
      dependencies: {
        mt4Gateway: mt4Connected ? 'connected' : 'disconnected',
      },
    });
  } catch (error) {
    res.json({
      status: 'degraded',
      service: SERVICE_NAME,
      version: VERSION,
      timestamp: new Date().toISOString(),
      dependencies: {
        mt4Gateway: 'error',
      },
      error: error instanceof Error ? error.message : 'Unknown error',
    });
  }
});

/**
 * List available MCP tools
 */
app.get('/tools', (_req: Request, res: Response) => {
  res.json({
    tools: mcpToolSchemas,
    count: mcpToolSchemas.length,
  });
});

/**
 * Get specific tool schema
 */
app.get('/tools/:toolName', (req: Request, res: Response) => {
  const { toolName } = req.params;
  const tool = mcpToolSchemas.find(t => t.name === toolName);

  if (!tool) {
    res.status(404).json({
      error: `Tool '${toolName}' not found`,
      availableTools: mcpToolSchemas.map(t => t.name),
    });
    return;
  }

  res.json(tool);
});

// ==========================================
// MCP Tool Execution Endpoints
// ==========================================

/**
 * Execute an MCP tool
 * POST /tools/:toolName
 * Body: { parameters: {...} }
 */
app.post('/tools/:toolName', async (req: Request, res: Response) => {
  const { toolName } = req.params;
  const { parameters = {} } = req.body;

  // Validate tool exists
  const handler = toolHandlers[toolName];
  if (!handler) {
    res.status(404).json({
      success: false,
      error: `Tool '${toolName}' not found`,
      availableTools: Object.keys(toolHandlers),
    });
    return;
  }

  try {
    console.log(`[${new Date().toISOString()}] Executing tool: ${toolName}`);
    console.log(`Parameters: ${JSON.stringify(parameters)}`);

    const result = await handler(parameters);

    res.json({
      success: true,
      tool: toolName,
      result,
    });
  } catch (error) {
    console.error(`[${new Date().toISOString()}] Tool error: ${toolName}`, error);

    // Handle Zod validation errors
    if (error && typeof error === 'object' && 'issues' in error) {
      res.status(400).json({
        success: false,
        error: 'Validation error',
        details: (error as { issues: unknown[] }).issues,
      });
      return;
    }

    res.status(500).json({
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    });
  }
});

// ==========================================
// MCP Protocol Endpoints (Standard)
// ==========================================

/**
 * MCP Initialize
 * Returns server capabilities
 */
app.post('/mcp/initialize', (_req: Request, res: Response) => {
  res.json({
    protocolVersion: '2024-11-05',
    capabilities: {
      tools: {},
    },
    serverInfo: {
      name: SERVICE_NAME,
      version: VERSION,
    },
  });
});

/**
 * MCP List Tools
 * Returns all available tools in MCP format
 */
app.post('/mcp/tools/list', (_req: Request, res: Response) => {
  res.json({
    tools: mcpToolSchemas.map(tool => ({
      name: tool.name,
      description: tool.description,
      inputSchema: tool.inputSchema,
    })),
  });
});

/**
 * MCP Call Tool
 * Execute a tool with parameters
 */
app.post('/mcp/tools/call', async (req: Request, res: Response) => {
  const { name, arguments: args = {} } = req.body;

  if (!name) {
    res.status(400).json({
      error: {
        code: 'invalid_request',
        message: 'Tool name is required',
      },
    });
    return;
  }

  const handler = toolHandlers[name];
  if (!handler) {
    res.status(404).json({
      error: {
        code: 'unknown_tool',
        message: `Tool '${name}' not found`,
      },
    });
    return;
  }

  try {
    const result = await handler(args);
    res.json(result);
  } catch (error) {
    // Handle Zod validation errors
    if (error && typeof error === 'object' && 'issues' in error) {
      res.status(400).json({
        error: {
          code: 'invalid_params',
          message: 'Invalid tool parameters',
          data: (error as { issues: unknown[] }).issues,
        },
      });
      return;
    }

    res.status(500).json({
      error: {
        code: 'internal_error',
        message: error instanceof Error ? error.message : 'Unknown error',
      },
    });
  }
});

// ==========================================
// Error Handler
// ==========================================

app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
  console.error(`[${new Date().toISOString()}] Unhandled error:`, err);
  res.status(500).json({
    error: 'Internal server error',
    message: err.message,
  });
});

// ==========================================
// Start Server
// ==========================================

app.listen(PORT, () => {
  console.log('');
  console.log('╔══════════════════════════════════════════════════════════╗');
  console.log('║           MCP MT4 Connector - Trading Platform           ║');
  console.log('╠══════════════════════════════════════════════════════════╣');
  console.log(`║  Service: ${SERVICE_NAME.padEnd(45)}║`);
  console.log(`║  Version: ${VERSION.padEnd(45)}║`);
  console.log(`║  Port: ${String(PORT).padEnd(48)}║`);
  console.log('╠══════════════════════════════════════════════════════════╣');
  console.log('║  Endpoints:                                              ║');
  console.log(`║  - Health: http://localhost:${PORT}/health`.padEnd(63) + '║');
  console.log(`║  - Tools:  http://localhost:${PORT}/tools`.padEnd(63) + '║');
  console.log('╠══════════════════════════════════════════════════════════╣');
  console.log('║  MCP Tools Available:                                    ║');
  mcpToolSchemas.forEach(tool => {
    console.log(`║  - ${tool.name.padEnd(54)}║`);
  });
  console.log('╚══════════════════════════════════════════════════════════╝');
  console.log('');
});

// ==========================================
// Graceful Shutdown
// ==========================================

process.on('SIGTERM', () => {
  console.log('Received SIGTERM, shutting down gracefully...');
  process.exit(0);
});

process.on('SIGINT', () => {
  console.log('Received SIGINT, shutting down gracefully...');
  process.exit(0);
});
