pragma Singleton

import QtQuick
import Quickshell
import Quickshell.Io
import qs.Commons
import qs.Services.Compositor
import qs.Services.Noctalia
import qs.Services.System

Singleton {
  id: root

  property bool initialized: false
  property bool isSending: false
  property int totalRamGb: 0
  property string instanceId: ""

  readonly property string telemetryEndpoint: Quickshell.env("NOCTALIA_TELEMETRY_ENDPOINT") || "https://api.noctalia.dev/ping"

  function init() {
    if (initialized)
      return;

    initialized = true;

    if (!Settings.data.general.telemetryEnabled) {
      Logger.d("Telemetry", "Telemetry disabled by user");
      return;
    }

    // Get or generate instance ID from ShellState
    instanceId = ShellState.getTelemetryInstanceId();
    if (!instanceId) {
      instanceId = generateRandomId();
      ShellState.setTelemetryInstanceId(instanceId);
      Logger.d("Telemetry", "Generated new random instance ID");
    } else {
      Logger.d("Telemetry", "Using stored instance ID");
    }

    // Read RAM info, then send ping
    memInfoProcess.running = true;
  }

  function generateRandomId() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }

  function getInstanceId() {
    return instanceId;
  }

  Process {
    id: memInfoProcess
    command: ["sh", "-c", "grep MemTotal /proc/meminfo | awk '{print int($2/1048576)}'"]
    running: false

    stdout: StdioCollector {
      onStreamFinished: {
        const ramGb = parseInt(text.trim()) || 0;
        root.totalRamGb = ramGb;
        root.sendPing();
      }
    }

    onExited: function (exitCode) {
      if (exitCode !== 0) {
        // Still send ping even if RAM detection fails
        root.sendPing();
      }
    }
  }

  function sendPing() {
    if (isSending)
      return;

    isSending = true;

    const payload = {
      instanceId: instanceId,
      version: UpdateService.currentVersion,
      compositor: getCompositorType(),
      os: HostService.osPretty || "Unknown",
      ramGb: totalRamGb,
      monitors: getMonitorInfo(),
      ui: {
        scaleRatio: Settings.data.general.scaleRatio,
        fontDefaultScale: Settings.data.ui.fontDefaultScale,
        fontFixedScale: Settings.data.ui.fontFixedScale
      }
    };

    Logger.d("Telemetry", "Sending anonymous ping:", JSON.stringify(payload));

    const request = new XMLHttpRequest();
    request.onreadystatechange = function () {
      if (request.readyState === XMLHttpRequest.DONE) {
        if (request.status >= 200 && request.status < 300) {
          Logger.d("Telemetry", "Ping sent successfully");
        } else {
          Logger.d("Telemetry", "Ping failed with status:", request.status);
        }
        isSending = false;
      }
    };

    request.open("POST", telemetryEndpoint);
    request.setRequestHeader("Content-Type", "application/json");
    request.send(JSON.stringify(payload));
  }

  function getMonitorInfo() {
    const monitors = [];
    const screens = Quickshell.screens || [];
    const scales = CompositorService.displayScales || {};

    for (let i = 0; i < screens.length; i++) {
      const screen = screens[i];
      const name = screen.name || "Unknown";
      const scaleData = scales[name];
      // Extract just the numeric scale value
      const scaleValue = (typeof scaleData === "object" && scaleData !== null) ? (scaleData.scale || 1.0) : (scaleData || 1.0);
      monitors.push({
                      width: screen.width || 0,
                      height: screen.height || 0,
                      scale: scaleValue
                    });
    }

    return monitors;
  }

  function getCompositorType() {
    if (CompositorService.isHyprland)
      return "Hyprland";
    if (CompositorService.isNiri)
      return "Niri";
    if (CompositorService.isScroll)
      return "Scroll";
    if (CompositorService.isSway)
      return "Sway";
    if (CompositorService.isMango)
      return "MangoWC";
    if (CompositorService.isLabwc)
      return "LabWC";
    if (CompositorService.isExtWorkspace)
      return "ExtWorkspace";
    return "Unknown";
  }
}
