// Cloudflare Worker for Cursor Full Stack AI IDE Backend
import { WebSocketDurableObject } from './websocket-do.js';

// Export the Durable Object class
export { WebSocketDurableObject };

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    
    // CORS headers
    const corsHeaders = {
      'Access-Control-Allow-Origin': env.CORS_ORIGIN || '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
      'Access-Control-Max-Age': '86400',
    };

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

    try {
      // Health check endpoint
      if (url.pathname === '/health') {
        return new Response(JSON.stringify({
          status: 'healthy',
          timestamp: new Date().toISOString(),
          environment: env.ENVIRONMENT || 'production',
          version: '1.0.0'
        }), {
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }

      // AI Providers endpoint
      if (url.pathname === '/api/providers') {
        return new Response(JSON.stringify({
          providers: [
            { id: 'openai', name: 'OpenAI', models: ['gpt-4', 'gpt-3.5-turbo', 'gpt-4-turbo'] },
            { id: 'anthropic', name: 'Anthropic', models: ['claude-3-sonnet', 'claude-3-haiku', 'claude-3-opus'] },
            { id: 'google', name: 'Google Gemini', models: ['gemini-pro', 'gemini-pro-vision', 'gemini-1.5-pro'] },
            { id: 'mistral', name: 'Mistral', models: ['mistral-large', 'mistral-medium', 'mistral-small'] },
            { id: 'openrouter', name: 'OpenRouter', models: ['meta-llama/llama-2-70b-chat', 'meta-llama/llama-2-13b-chat', 'microsoft/wizardlm-13b', 'openai/gpt-4', 'anthropic/claude-3-sonnet'] }
          ]
        }), {
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }

      // Chat endpoint
      if (url.pathname === '/api/chat' && request.method === 'POST') {
        const { message, provider, apiKey, model, useTools = false } = await request.json();
        
        if (!message || !provider || !apiKey) {
          return new Response(JSON.stringify({ 
            error: 'Missing required fields',
            details: 'Please provide message, provider, and apiKey'
          }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        }

        try {
          const response = await handleAIChat(message, provider, apiKey, model, useTools);
          return new Response(JSON.stringify({ 
            response,
            provider,
            model: model || 'default'
          }), {
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        } catch (error) {
          return new Response(JSON.stringify({ 
            error: 'AI request failed',
            details: error.message
          }), {
            status: 500,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        }
      }

      // Tools endpoint
      if (url.pathname === '/api/tools' && request.method === 'GET') {
        return new Response(JSON.stringify({
          tools: [
            { name: 'file_read', description: 'Read contents of a file', parameters: { filePath: { type: 'string' } } },
            { name: 'file_write', description: 'Write content to a file', parameters: { filePath: { type: 'string' }, content: { type: 'string' } } },
            { name: 'file_list', description: 'List files in a directory', parameters: { directory: { type: 'string' } } },
            { name: 'terminal_command', description: 'Execute a terminal command', parameters: { command: { type: 'string' } } },
            { name: 'git_status', description: 'Get git status', parameters: {} },
            { name: 'git_commit', description: 'Commit changes to git', parameters: { message: { type: 'string' } } },
            { name: 'search_code', description: 'Search for code patterns', parameters: { query: { type: 'string' } } },
            { name: 'create_file', description: 'Create a new file', parameters: { filePath: { type: 'string' }, content: { type: 'string' } } }
          ]
        }), {
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }

      // Tool execution endpoint
      if (url.pathname === '/api/tools/execute' && request.method === 'POST') {
        const { toolName, params } = await request.json();
        
        if (!toolName) {
          return new Response(JSON.stringify({ error: 'Tool name is required' }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        }

        try {
          const result = await executeTool(toolName, params, env);
          return new Response(JSON.stringify(result), {
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        } catch (error) {
          return new Response(JSON.stringify({ 
            error: 'Tool execution failed',
            details: error.message
          }), {
            status: 500,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' }
          });
        }
      }

      // File operations
      if (url.pathname.startsWith('/api/workspace/')) {
        return handleFileOperations(request, env, corsHeaders);
      }

      // WebSocket upgrade
      if (request.headers.get('Upgrade') === 'websocket') {
        const durableObjectId = env.WEBSOCKET_DO.idFromName('websocket');
        const durableObject = env.WEBSOCKET_DO.get(durableObjectId);
        return durableObject.fetch(request);
      }

      return new Response('Not Found', { 
        status: 404,
        headers: corsHeaders
      });

    } catch (error) {
      return new Response(JSON.stringify({ 
        error: 'Internal server error',
        details: error.message
      }), {
        status: 500,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' }
      });
    }
  }
};

// AI Chat Handler
async function handleAIChat(message, provider, apiKey, model, useTools) {
  const providers = {
    openai: async (message, apiKey, model) => {
      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          model: model || 'gpt-4',
          messages: [{ role: 'user', content: message }],
          max_tokens: 1000
        })
      });
      
      if (!response.ok) {
        throw new Error(`OpenAI API error: ${response.status}`);
      }
      
      const data = await response.json();
      return data.choices[0]?.message?.content || 'No response generated';
    },
    
    anthropic: async (message, apiKey, model) => {
      const response = await fetch('https://api.anthropic.com/v1/messages', {
        method: 'POST',
        headers: {
          'x-api-key': apiKey,
          'Content-Type': 'application/json',
          'anthropic-version': '2023-06-01'
        },
        body: JSON.stringify({
          model: model || 'claude-3-sonnet-20240229',
          max_tokens: 1000,
          messages: [{ role: 'user', content: message }]
        })
      });
      
      if (!response.ok) {
        throw new Error(`Anthropic API error: ${response.status}`);
      }
      
      const data = await response.json();
      return data.content[0]?.text || 'No response generated';
    },
    
    google: async (message, apiKey, model) => {
      const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model || 'gemini-pro'}:generateContent?key=${apiKey}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          contents: [{ parts: [{ text: message }] }]
        })
      });
      
      if (!response.ok) {
        throw new Error(`Google API error: ${response.status}`);
      }
      
      const data = await response.json();
      return data.candidates[0]?.content?.parts[0]?.text || 'No response generated';
    },
    
    mistral: async (message, apiKey, model) => {
      const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          model: model || 'mistral-large-latest',
          messages: [{ role: 'user', content: message }],
          max_tokens: 1000
        })
      });
      
      if (!response.ok) {
        throw new Error(`Mistral API error: ${response.status}`);
      }
      
      const data = await response.json();
      return data.choices[0]?.message?.content || 'No response generated';
    },
    
    openrouter: async (message, apiKey, model) => {
      const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
          'HTTP-Referer': 'https://cursor-fullstack-ai-ide.com',
          'X-Title': 'Cursor Full Stack AI IDE'
        },
        body: JSON.stringify({
          model: model || 'meta-llama/llama-2-70b-chat',
          messages: [{ role: 'user', content: message }],
          max_tokens: 1000
        })
      });
      
      if (!response.ok) {
        throw new Error(`OpenRouter API error: ${response.status}`);
      }
      
      const data = await response.json();
      return data.choices[0]?.message?.content || 'No response generated';
    }
  };

  const providerHandler = providers[provider];
  if (!providerHandler) {
    throw new Error(`Unsupported provider: ${provider}`);
  }

  return await providerHandler(message, apiKey, model);
}

// Tool Execution Handler
async function executeTool(toolName, params, env) {
  const tools = {
    file_read: async (params) => {
      const { filePath } = params;
      const file = await env.FILE_STORAGE_KV.get(filePath);
      return { success: true, content: file || '', filePath };
    },
    
    file_write: async (params) => {
      const { filePath, content } = params;
      await env.FILE_STORAGE_KV.put(filePath, content);
      return { success: true, filePath };
    },
    
    file_list: async (params) => {
      const { directory = '' } = params;
      const files = await env.FILE_STORAGE_KV.list({ prefix: directory });
      return { success: true, files: files.objects.map(obj => ({
        name: obj.key.split('/').pop(),
        path: obj.key,
        type: 'file',
        size: obj.size
      })) };
    },
    
    search_code: async (params) => {
      const { query } = params;
      const files = await env.FILE_STORAGE_KV.list();
      const results = [];
      
      for (const file of files.objects) {
        const content = await env.FILE_STORAGE_KV.get(file.key);
        if (content && content.includes(query)) {
          results.push({
            filePath: file.key,
            content: content.substring(0, 200) + '...'
          });
        }
      }
      
      return { success: true, results, query, count: results.length };
    },
    
    create_file: async (params) => {
      const { filePath, content } = params;
      await env.FILE_STORAGE_KV.put(filePath, content);
      return { success: true, filePath };
    }
  };

  const tool = tools[toolName];
  if (!tool) {
    return { success: false, error: `Unknown tool: ${toolName}` };
  }

  try {
    return await tool(params);
  } catch (error) {
    return { success: false, error: error.message };
  }
}

// File Operations Handler
async function handleFileOperations(request, env, corsHeaders) {
  const url = new URL(request.url);
  const path = url.pathname.replace('/api/workspace/', '');
  
  if (request.method === 'GET' && path === 'files') {
    const files = await env.FILE_STORAGE_KV.list();
    return new Response(JSON.stringify({
      files: files.objects.map(obj => ({
        name: obj.key.split('/').pop(),
        path: obj.key,
        type: 'file',
        size: obj.size
      }))
    }), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
  
  if (request.method === 'GET' && path) {
    const content = await env.FILE_STORAGE_KV.get(path);
    if (!content) {
      return new Response('File not found', { 
        status: 404,
        headers: corsHeaders
      });
    }
    return new Response(JSON.stringify({ content }), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
  
  if (request.method === 'POST' && path) {
    const { content } = await request.json();
    await env.FILE_STORAGE_KV.put(path, content);
    return new Response(JSON.stringify({ success: true }), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
  
  return new Response('Not Found', { 
    status: 404,
    headers: corsHeaders
  });
}
