/**
 * Workflow API Call Proxy Endpoint
 * 
 * This endpoint acts as a proxy for API calls made during workflow execution.
 * It handles the new API node structure with proper authorization and avoids CORS issues.
 */

// Helper function to substitute variables in a string
function substituteVariables(str, variables) {
  if (typeof str !== 'string') return str;
  
  // Replace {{variable}} first
  str = str.replace(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g, (match, varName) => {
    const value = variables[varName];
    if (value === undefined || value === null) return '';
    if (typeof value === 'object') {
      return JSON.stringify(value);
    }
    return String(value);
  });
  
  // Then replace {variable}
  str = str.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, varName) => {
    const value = variables[varName];
    if (value === undefined || value === null) return '';
    if (typeof value === 'object') {
      return JSON.stringify(value);
    }
    return String(value);
  });
  
  return str;
}

// Build API request from node data
function buildApiRequest(nodeData, variables) {
  // 1. URL (with param substitution)
  let url = substituteVariables(nodeData.apiUrl, variables);
  
  // 2. Params (for GET, DELETE, etc.)
  let params = Array.isArray(nodeData.params) ? nodeData.params : [];
  if (params.length) {
    const query = params
      .filter(p => p.key)
      .map(p => `${encodeURIComponent(substituteVariables(p.key, variables))}=${encodeURIComponent(substituteVariables(p.value, variables))}`)
      .join('&');
    if (query) {
      url += (url.includes('?') ? '&' : '?') + query;
    }
  }
  
  // 3. Headers
  let headers = {};
  if (Array.isArray(nodeData.headers)) {
    nodeData.headers.forEach(h => {
      if (h.key) headers[substituteVariables(h.key, variables)] = substituteVariables(h.value, variables);
    });
  } else if (typeof nodeData.headers === 'object') {
    headers = { ...nodeData.headers };
  }
  
  // 4. Authorization
  if (nodeData.authorization && nodeData.authorization.type && nodeData.authorization.type !== 'none') {
    const auth = nodeData.authorization;
    if (auth.type === 'bearer' && auth.token) {
      headers['Authorization'] = `Bearer ${substituteVariables(auth.token, variables)}`;
    } else if (auth.type === 'basic') {
      if (auth.token) {
        // Basic Auth with token (JWT or other token)
        headers['Authorization'] = `Basic ${substituteVariables(auth.token, variables)}`;
      } else if (auth.username && auth.password) {
        // Basic Auth with username/password
        const token = Buffer.from(`${substituteVariables(auth.username, variables)}:${substituteVariables(auth.password, variables)}`).toString('base64');
        headers['Authorization'] = `Basic ${token}`;
      }
    } else if (auth.type === 'apiKey' && auth.key && auth.value) {
      if (auth.in === 'header') {
        headers[substituteVariables(auth.key, variables)] = substituteVariables(auth.value, variables);
      } else if (auth.in === 'query') {
        url += (url.includes('?') ? '&' : '?') + `${encodeURIComponent(substituteVariables(auth.key, variables))}=${encodeURIComponent(substituteVariables(auth.value, variables))}`;
      }
    }
  }
  
  // 5. Body
  let body;
  if (nodeData.body && nodeData.body.type && nodeData.body.type !== 'none') {
    if (['form-data', 'x-www-form-urlencoded'].includes(nodeData.body.type)) {
      const dataArr = Array.isArray(nodeData.body.data) ? nodeData.body.data : [];
      if (nodeData.body.type === 'form-data') {
        // For server-side, we'll use URLSearchParams for form-data
        const formData = new URLSearchParams();
        dataArr.forEach(item => {
          if (item.key) formData.append(substituteVariables(item.key, variables), substituteVariables(item.value, variables));
        });
        body = formData.toString();
        headers['Content-Type'] = 'application/x-www-form-urlencoded';
      } else {
        // x-www-form-urlencoded
        body = dataArr
          .filter(item => item.key)
          .map(item => `${encodeURIComponent(substituteVariables(item.key, variables))}=${encodeURIComponent(substituteVariables(item.value, variables))}`)
          .join('&');
        headers['Content-Type'] = 'application/x-www-form-urlencoded';
      }
    } else if (nodeData.body.type === 'raw') {
      body = substituteVariables(nodeData.body.data, variables);
      // Try to detect JSON
      if (body && body.trim().startsWith('{')) {
        headers['Content-Type'] = 'application/json';
      }
    }
  }
  
  return { url, headers, body };
}

export default defineEventHandler(async (event) => {
  try {
    // Get request body
    const body = await readBody(event);
    
    // Extract node configuration and process variables
    const { nodeData, processVariables } = body;
    
    // Validate input
    if (!nodeData || !nodeData.apiUrl) {
      return {
        success: false,
        error: {
          message: 'Invalid API node configuration. Missing apiUrl.'
        }
      };
    }
    
    // Build the API request
    const { url, headers, body: requestBody } = buildApiRequest(nodeData, processVariables);
    const apiMethod = nodeData.apiMethod || 'GET';
    const outputVariable = nodeData.outputVariable || 'apiResponse';
    const errorVariable = nodeData.errorVariable || 'apiError';
    const continueOnError = nodeData.continueOnError || false;
    

    
    // Prepare fetch options
    const fetchOptions = {
      method: apiMethod,
      headers
    };
    
    // Add body for non-GET requests
    if (!['GET', 'HEAD'].includes(apiMethod) && requestBody) {
      fetchOptions.body = requestBody;
    }
    
    // Make the API call
    const response = await fetch(url, fetchOptions);
    
    // Get response data
    let responseData;
    const contentType = response.headers.get('content-type');
    
    if (contentType && contentType.includes('application/json')) {
      responseData = await response.json();
    } else {
      responseData = await response.text();
    }
    
    // Prepare result
    const result = {
      success: response.ok,
      data: responseData,
      status: response.status,
      statusText: response.statusText,
      headers: Object.fromEntries([...response.headers.entries()])
    };
    
    if (!response.ok) {
      result.error = {
        message: `API call failed with status ${response.status}`,
        status: response.status,
        statusText: response.statusText,
        data: responseData
      };
    }
    
    return result;
    
  } catch (error) {
    return {
      success: false,
      error: {
        message: error.message || 'An error occurred while making the API call',
        stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
      }
    };
  }
}); 