import fetch from "node-fetch";

const PROMETHEUS_URL = "http://localhost:9090";

const SERVER_JOBS = {
  "vrising": "vrising",
  "factorio": "factorio",
  "minecraft": "minecraft",
  "zomboid": "zomboid",
  "palworld": "palworld",
  "terraria": "terraria",
  "openttd": "openttd"
};

export async function queryPrometheus(query) {
  const url = `${PROMETHEUS_URL}/api/v1/query?query=${encodeURIComponent(query)}`;
  const res = await fetch(url);
  const data = await res.json();
  if (data.status !== "success") {
    throw new Error(`Prometheus query failed: ${data.error}`);
  }
  return data.data.result;
}

export async function queryPrometheusRange(query, start, end, step) {
  const url = `${PROMETHEUS_URL}/api/v1/query_range?query=${encodeURIComponent(query)}&start=${start}&end=${end}&step=${step}`;
  const res = await fetch(url);
  const data = await res.json();
  if (data.status !== "success") {
    throw new Error(`Prometheus query failed: ${data.error}`);
  }
  return data.data.result;
}

export async function getServerMetricsHistory(serverId, range = "1h") {
  const job = SERVER_JOBS[serverId];
  if (!job) {
    throw new Error(`Unknown server ID: ${serverId}`);
  }

  const end = Math.floor(Date.now() / 1000);
  let duration, step;
  switch (range) {
    case "15m": duration = 15 * 60; step = 15; break;
    case "1h": duration = 60 * 60; step = 60; break;
    case "6h": duration = 6 * 60 * 60; step = 300; break;
    case "24h": duration = 24 * 60 * 60; step = 900; break;
    default: duration = 60 * 60; step = 60;
  }
  const start = end - duration;

  const cpuQuery = `100 - (avg by(instance) (irate(node_cpu_seconds_total{job="${job}",mode="idle"}[5m])) * 100)`;
  const memQuery = `100 * (1 - ((node_memory_MemAvailable_bytes{job="${job}"} or node_memory_MemFree_bytes{job="${job}"}) / node_memory_MemTotal_bytes{job="${job}"}))`;
  const netRxQuery = `sum(irate(node_network_receive_bytes_total{job="${job}",device!~"lo|veth.*|docker.*|br-.*"}[5m]))`;
  const netTxQuery = `sum(irate(node_network_transmit_bytes_total{job="${job}",device!~"lo|veth.*|docker.*|br-.*"}[5m]))`;

  try {
    const [cpuResult, memResult, netRxResult, netTxResult] = await Promise.all([
      queryPrometheusRange(cpuQuery, start, end, step),
      queryPrometheusRange(memQuery, start, end, step),
      queryPrometheusRange(netRxQuery, start, end, step),
      queryPrometheusRange(netTxQuery, start, end, step)
    ]);

    const cpu = cpuResult[0]?.values?.map(([ts, val]) => ({ timestamp: ts * 1000, value: parseFloat(val) || 0 })) || [];
    const memory = memResult[0]?.values?.map(([ts, val]) => ({ timestamp: ts * 1000, value: parseFloat(val) || 0 })) || [];
    const networkRx = netRxResult[0]?.values?.map(([ts, val]) => ({ timestamp: ts * 1000, value: parseFloat(val) || 0 })) || [];
    const networkTx = netTxResult[0]?.values?.map(([ts, val]) => ({ timestamp: ts * 1000, value: parseFloat(val) || 0 })) || [];

    return { cpu, memory, networkRx, networkTx };
  } catch (error) {
    console.error("Prometheus query error:", error);
    return { cpu: [], memory: [], networkRx: [], networkTx: [] };
  }
}

export async function getCurrentMetrics(serverId) {
  const job = SERVER_JOBS[serverId];
  if (!job) {
    throw new Error(`Unknown server ID: ${serverId}`);
  }

  const cpuQuery = `100 - (avg by(instance) (irate(node_cpu_seconds_total{job="${job}",mode="idle"}[5m])) * 100)`;
  const memPercentQuery = `100 * (1 - ((node_memory_MemAvailable_bytes{job="${job}"} or node_memory_MemFree_bytes{job="${job}"}) / node_memory_MemTotal_bytes{job="${job}"}))`;
  const memUsedQuery = `node_memory_MemTotal_bytes{job="${job}"} - (node_memory_MemAvailable_bytes{job="${job}"} or node_memory_MemFree_bytes{job="${job}"})`;
  const memTotalQuery = `node_memory_MemTotal_bytes{job="${job}"}`;
  const uptimeQuery = `node_time_seconds{job="${job}"} - node_boot_time_seconds{job="${job}"}`;
  const cpuCoresQuery = `count(node_cpu_seconds_total{job="${job}",mode="idle"})`;

  try {
    const [cpuResult, memPercentResult, memUsedResult, memTotalResult, uptimeResult, cpuCoresResult] = await Promise.all([
      queryPrometheus(cpuQuery),
      queryPrometheus(memPercentQuery),
      queryPrometheus(memUsedQuery),
      queryPrometheus(memTotalQuery),
      queryPrometheus(uptimeQuery),
      queryPrometheus(cpuCoresQuery)
    ]);

    return {
      cpu: parseFloat(cpuResult[0]?.value?.[1]) || 0,
      memory: parseFloat(memPercentResult[0]?.value?.[1]) || 0,
      memoryUsed: parseFloat(memUsedResult[0]?.value?.[1]) || 0,
      memoryTotal: parseFloat(memTotalResult[0]?.value?.[1]) || 0,
      uptime: parseFloat(uptimeResult[0]?.value?.[1]) || 0,
      cpuCores: parseInt(cpuCoresResult[0]?.value?.[1]) || 1
    };
  } catch (error) {
    console.error("Prometheus current metrics error:", error);
    return { cpu: 0, memory: 0, memoryUsed: 0, memoryTotal: 0, uptime: 0, cpuCores: 1 };
  }
}
