#!/usr/bin/env node
import { z } from 'zod';
import { createStripeServer } from './server.js';

/**
 * Environment variable schema
 */
const EnvSchema = z.object({
  STRIPE_SECRET_KEY: z.string().min(1, 'STRIPE_SECRET_KEY is required'),
  STRIPE_WEBHOOK_SECRET: z.string().optional(),
  PORT: z.string().optional().default('3000'),
  NODE_ENV: z.enum(['development', 'production', 'test']).optional().default('production'),
});

type Env = z.infer<typeof EnvSchema>;

/**
 * Validate environment variables
 */
function validateEnv(): Env {
  try {
    return EnvSchema.parse(process.env);
  } catch (error) {
    if (error instanceof z.ZodError) {
      console.error('❌ Environment validation failed:');
      for (const issue of error.issues) {
        console.error(`  - ${issue.path.join('.')}: ${issue.message}`);
      }
      console.error('\nRequired environment variables:');
      console.error('  STRIPE_SECRET_KEY - Your Stripe secret key (starts with sk_test_ or sk_live_)');
      console.error('\nOptional environment variables:');
      console.error('  STRIPE_WEBHOOK_SECRET - Webhook signing secret (starts with whsec_)');
      console.error('  PORT - HTTP server port for SSE transport (default: 3000)');
      console.error('\nExample:');
      console.error('  export STRIPE_SECRET_KEY=sk_test_xxxxx');
      console.error('  npm start');
      process.exit(1);
    }
    throw error;
  }
}

/**
 * Health check endpoint data
 */
function getHealthInfo() {
  return {
    status: 'healthy',
    service: '@mcpengine/stripe',
    version: '1.0.0',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    node: process.version,
  };
}

/**
 * Setup graceful shutdown
 */
function setupGracefulShutdown(cleanup: () => Promise<void>): void {
  const signals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT', 'SIGUSR2'];
  
  signals.forEach(signal => {
    process.on(signal, async () => {
      console.error(`\n📡 Received ${signal}, shutting down gracefully...`);
      
      try {
        await cleanup();
        console.error('✅ Cleanup complete');
        process.exit(0);
      } catch (error) {
        console.error('❌ Error during cleanup:', error);
        process.exit(1);
      }
    });
  });

  // Handle uncaught errors
  process.on('uncaughtException', (error) => {
    console.error('❌ Uncaught exception:', error);
    process.exit(1);
  });

  process.on('unhandledRejection', (reason, promise) => {
    console.error('❌ Unhandled rejection at:', promise, 'reason:', reason);
    process.exit(1);
  });
}

/**
 * Start HTTP/SSE server for dual transport support
 */
async function startHttpServer(server: ReturnType<typeof createStripeServer>, port: number): Promise<void> {
  const { createServer } = await import('http');
  const { SSEServerTransport } = await import('@modelcontextprotocol/sdk/server/sse.js');

  const httpServer = createServer(async (req, res) => {
    // Health check endpoint
    if (req.url === '/health' || req.url === '/') {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(getHealthInfo(), null, 2));
      return;
    }

    // SSE endpoint
    if (req.url === '/sse') {
      console.error('📡 SSE client connected');
      
      const transport = new SSEServerTransport('/message', res);
      await server.getServer().connect(transport);
      
      // Handle client disconnect
      req.on('close', () => {
        console.error('📡 SSE client disconnected');
      });
      return;
    }

    // 404 for other routes
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not found' }));
  });

  httpServer.listen(port, () => {
    console.error(`🌐 HTTP/SSE server listening on http://localhost:${port}`);
    console.error(`   Health: http://localhost:${port}/health`);
    console.error(`   SSE: http://localhost:${port}/sse`);
  });
}

/**
 * Main entry point
 */
async function main(): Promise<void> {
  console.error('🚀 Starting Stripe MCP Server...\n');

  // Validate environment
  const env = validateEnv();
  
  console.error('✅ Environment validated');
  console.error(`   API Key: ${env.STRIPE_SECRET_KEY.substring(0, 12)}...`);
  if (env.STRIPE_WEBHOOK_SECRET) {
    console.error(`   Webhook Secret: ${env.STRIPE_WEBHOOK_SECRET.substring(0, 12)}...`);
  }
  console.error('');

  // Create server
  const server = createStripeServer({
    apiKey: env.STRIPE_SECRET_KEY,
    webhookSecret: env.STRIPE_WEBHOOK_SECRET,
  });

  // Setup graceful shutdown
  setupGracefulShutdown(async () => {
    await server.close();
  });

  // Determine transport mode
  const transportMode = process.env.TRANSPORT_MODE || 'stdio';

  if (transportMode === 'http' || transportMode === 'dual') {
    const port = parseInt(env.PORT, 10);
    await startHttpServer(server, port);
  }

  if (transportMode === 'stdio' || transportMode === 'dual') {
    // Connect to stdio (this is the default for MCP)
    await server.connectStdio();
  }

  if (transportMode !== 'http' && transportMode !== 'stdio' && transportMode !== 'dual') {
    console.error(`❌ Unknown transport mode: ${transportMode}`);
    console.error('   Valid modes: stdio, http, dual');
    process.exit(1);
  }

  console.error('✅ Server ready\n');
}

// Run the server
main().catch((error) => {
  console.error('❌ Fatal error:', error);
  process.exit(1);
});
