/**
 * Cloudflare Worker - Server Recommendation System Entry Point
 *
 * AI-powered server recommendation service using Workers AI, D1, and KV.
 */

import type { Env } from './types';
import { getAllowedOrigin, checkRateLimit, jsonResponse, isAllowedProvisionOrigin } from './utils';
import { handleHealth } from './handlers/health';
import { handleGetServers } from './handlers/servers';
import { handleRecommend } from './handlers/recommend';
import { handleReport } from './handlers/report';
import {
  handleProvision,
  handleGetOrders,
  handleGetOrder,
  handleDeleteOrder,
  handleGetBalance,
} from './handlers/provision';
import { handleProvisionQueue } from './handlers/queue';
import type { ProvisionQueueMessage } from './types';

/**
 * Main request handler
 */
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const requestId = crypto.randomUUID();

    try {
      const url = new URL(request.url);
      const path = url.pathname;

      // Rate limiting (except for health checks)
      if (path !== '/api/health') {
        const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
        const rateCheck = await checkRateLimit(clientIP, env);

        if (!rateCheck.allowed) {
          const origin = getAllowedOrigin(request);
          return jsonResponse(
            { error: 'Too many requests', request_id: rateCheck.requestId },
            429,
            {
              'Access-Control-Allow-Origin': origin,
              'Vary': 'Origin',
            }
          );
        }
      }

      // CORS headers for all responses
      const origin = getAllowedOrigin(request);
      const corsHeaders = {
        'Access-Control-Allow-Origin': origin,
        'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Vary': 'Origin',
      };

      // Handle preflight requests
      if (request.method === 'OPTIONS') {
        return new Response(null, { headers: corsHeaders });
      }

      // Route handling
      if (path === '/api/health') {
        return handleHealth(corsHeaders);
      }

      if (path === '/api/servers' && request.method === 'GET') {
        return handleGetServers(request, env, corsHeaders);
      }

      if (path === '/api/recommend' && request.method === 'POST') {
        return handleRecommend(request, env, corsHeaders);
      }

      if (path === '/api/recommend/report' && request.method === 'GET') {
        return handleReport(request, env, corsHeaders);
      }

      // Provisioning endpoints (restricted to *.kappa-d8e.workers.dev + API key)
      if (path.startsWith('/api/provision')) {
        // Check API key (required for all provision requests)
        const apiKey = request.headers.get('X-API-Key');
        if (!env.PROVISION_API_KEY || apiKey !== env.PROVISION_API_KEY) {
          return jsonResponse(
            { error: 'Unauthorized: Invalid or missing API key', code: 'UNAUTHORIZED' },
            401,
            corsHeaders
          );
        }

        // Check origin for browser requests
        if (!isAllowedProvisionOrigin(request)) {
          return jsonResponse(
            { error: 'Forbidden: Invalid origin', code: 'FORBIDDEN' },
            403,
            corsHeaders
          );
        }

        if (path === '/api/provision' && request.method === 'POST') {
          return handleProvision(request, env, corsHeaders);
        }

        if (path === '/api/provision/orders' && request.method === 'GET') {
          return handleGetOrders(request, env, corsHeaders);
        }

        if (path === '/api/provision/balance' && request.method === 'GET') {
          return handleGetBalance(request, env, corsHeaders);
        }

        // Dynamic route: /api/provision/orders/:id
        const orderMatch = path.match(/^\/api\/provision\/orders\/([a-zA-Z0-9-]+)$/);
        if (orderMatch) {
          const orderId = orderMatch[1];
          if (request.method === 'GET') {
            return handleGetOrder(request, env, orderId, corsHeaders);
          }
          if (request.method === 'DELETE') {
            return handleDeleteOrder(request, env, orderId, corsHeaders);
          }
        }
      }

      return jsonResponse(
        { error: 'Not found', request_id: requestId },
        404,
        corsHeaders
      );
    } catch (error) {
      console.error('[Worker] Unhandled error:', error);
      const origin = getAllowedOrigin(request);
      return jsonResponse(
        {
          error: 'Internal server error',
          request_id: requestId,
        },
        500,
        {
          'Access-Control-Allow-Origin': origin,
          'Vary': 'Origin',
        }
      );
    }
  },

  /**
   * Queue handler for async server provisioning
   */
  async queue(batch: MessageBatch<ProvisionQueueMessage>, env: Env): Promise<void> {
    await handleProvisionQueue(batch, env);
  },
};
