/**
 * Package executor client
 * Calls the remote sandbox service for secure package execution
 */

import type { ExecutionResult, ExecutorOptions } from './types.js';

const DEFAULT_TIMEOUT = 10000; // 10 seconds

// Ensure URL has protocol
function getSandboxUrl(): string {
  const url = process.env.SANDBOX_EXECUTOR_URL || 'http://localhost:3000';
  // If URL doesn't start with http:// or https://, add https://
  if (!url.startsWith('http://') && !url.startsWith('https://')) {
    return `https://${url}`;
  }
  return url;
}

const SANDBOX_URL = getSandboxUrl();

/**
 * Execute a package function with parameters via remote sandbox
 */
export async function executePackage(
  packageName: string,
  functionName: string,
  params: Record<string, unknown>,
  options: ExecutorOptions = {}
): Promise<ExecutionResult> {
  const startTime = Date.now();
  const timeout = options.timeout || DEFAULT_TIMEOUT;

  try {
    // Call the remote sandbox service
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    const response = await fetch(`${SANDBOX_URL}/execute`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        packageName,
        functionName,
        params,
      }),
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    const executionTimeMs = Date.now() - startTime;

    if (!response.ok) {
      const errorData = (await response.json().catch(() => ({ error: 'Unknown error' }))) as {
        error?: string;
      };
      return {
        success: false,
        error: errorData.error || `Sandbox service error: ${response.status}`,
        executionTimeMs,
      };
    }

    const result = (await response.json()) as {
      success: boolean;
      output?: unknown;
      error?: string;
      executionTimeMs?: number;
    };

    return {
      success: result.success,
      output: result.output,
      error: result.error,
      executionTimeMs: result.executionTimeMs || executionTimeMs,
    };
  } catch (error) {
    const executionTimeMs = Date.now() - startTime;

    if (error instanceof Error && error.name === 'AbortError') {
      return {
        success: false,
        error: 'Execution timeout',
        executionTimeMs,
      };
    }

    return {
      success: false,
      error: error instanceof Error ? error.message : String(error),
      executionTimeMs,
    };
  }
}

/**
 * Clear the package cache on the remote sandbox
 */
export async function clearCache(): Promise<void> {
  try {
    const response = await fetch(`${SANDBOX_URL}/cache/clear`, {
      method: 'POST',
    });

    if (!response.ok) {
      throw new Error(`Failed to clear cache: ${response.status}`);
    }
  } catch (error) {
    console.error('Failed to clear sandbox cache:', error);
    throw error;
  }
}

/**
 * Check if the sandbox service is healthy
 */
export async function checkHealth(): Promise<boolean> {
  try {
    const response = await fetch(`${SANDBOX_URL}/health`, {
      method: 'GET',
    });

    return response.ok;
  } catch {
    return false;
  }
}
