import http from 'node:http';
import https from 'node:https';
import { readFileSync } from 'node:fs';
import { config } from './config.js';

const agentCa = config.agentCaFile ? readFileSync(config.agentCaFile, 'utf8') : undefined;

export async function agentRequest(node, path, options = {}) {
  const url = new URL(`${node.baseUrl}/api${path}`);
  const data = options.body ? JSON.stringify(options.body) : '';
  const response = await requestJson(url, {
    method: options.method || 'GET',
    headers: {
      Authorization: `Bearer ${node.token}`,
      'Content-Type': 'application/json',
      ...(data ? { 'Content-Length': Buffer.byteLength(data) } : {}),
      ...(options.headers || {}),
    },
    body: data,
    timeout: options.timeout || 20000,
  });

  if (response.status < 200 || response.status >= 300) {
    const error = new Error(response.data?.error || `Agent request failed with ${response.status}`);
    error.status = response.status;
    throw error;
  }
  return response.data;
}

function requestJson(url, options) {
  return new Promise((resolve, reject) => {
    const transport = url.protocol === 'https:' ? https : http;
    const request = transport.request({
      protocol: url.protocol,
      hostname: url.hostname,
      port: url.port,
      path: `${url.pathname}${url.search}`,
      method: options.method,
      headers: options.headers,
      timeout: options.timeout,
      ...(url.protocol === 'https:' && agentCa ? { ca: agentCa } : {}),
    }, (response) => {
      let text = '';
      response.setEncoding('utf8');
      response.on('data', (chunk) => {
        text += chunk;
      });
      response.on('end', () => {
        try {
          resolve({
            status: response.statusCode || 0,
            data: text ? JSON.parse(text) : null,
          });
        } catch (error) {
          reject(error);
        }
      });
    });

    request.on('timeout', () => {
      request.destroy(new Error('Agent request timed out.'));
    });
    request.on('error', reject);
    if (options.body) request.write(options.body);
    request.end();
  });
}

export function publicNode(node) {
  return {
    id: node.id,
    name: node.name,
    baseUrl: node.baseUrl,
    enabled: node.enabled,
    lastHealthStatus: node.lastHealthStatus,
    lastHealthAt: node.lastHealthAt,
    createdAt: node.createdAt,
    updatedAt: node.updatedAt,
  };
}
