/**
 * Uptime Kuma Service — Socket.IO direct connection
 * 
 * Kuma 2.x uses Socket.IO for monitor CRUD (REST only exposes status pages).
 * Auth via login event with username/password.
 * 
 * Required .env:
 *   UPTIME_KUMA_URL=http://localhost:3001
 *   UPTIME_KUMA_USERNAME=admin
 *   UPTIME_KUMA_PASSWORD=your_password
 */
const { io } = require('socket.io-client');

const KUMA_URL = process.env.UPTIME_KUMA_URL || 'http://localhost:3001';
const KUMA_USER = process.env.UPTIME_KUMA_USERNAME || 'admin';
const KUMA_PASS = process.env.UPTIME_KUMA_PASSWORD || '';

/**
 * Connect to Kuma, authenticate, run a callback, then disconnect.
 * Keeps connections short-lived — no persistent socket.
 */
async function withKuma(callback) {
  const socket = io(KUMA_URL, {
    reconnection: false,
    timeout: 10000
  });

  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      socket.disconnect();
      reject(new Error('Uptime Kuma connection timed out'));
    }, 15000);

    socket.on('connect', () => {
      socket.emit('login', {
        username: KUMA_USER,
        password: KUMA_PASS,
        token: ''
      }, async (res) => {
        if (!res.ok) {
          clearTimeout(timeout);
          socket.disconnect();
          reject(new Error(`Kuma auth failed: ${res.msg}`));
          return;
        }
        try {
          const result = await callback(socket);
          clearTimeout(timeout);
          socket.disconnect();
          resolve(result);
        } catch (err) {
          clearTimeout(timeout);
          socket.disconnect();
          reject(err);
        }
      });
    });

    socket.on('connect_error', (err) => {
      clearTimeout(timeout);
      reject(new Error(`Kuma connect failed: ${err.message}`));
    });
  });
}

/**
 * Get all monitors.
 */
async function getMonitors() {
  return withKuma((socket) => {
    return new Promise((resolve) => {
      socket.emit('getMonitorList', (res) => {
        resolve(Object.values(res));
      });
    });
  });
}

/**
 * Create a TCP port monitor for a Minecraft server.
 * @param {string} name - Monitor name (e.g. "Stoneblock 4 - TX")
 * @param {string} hostname - Server hostname/IP
 * @param {number} port - Server port (usually 25565)
 */
async function createMonitor(name, hostname, port) {
  return withKuma((socket) => {
    return new Promise((resolve, reject) => {
      socket.emit('add', {
        type: 'port',
        name: name,
        hostname: hostname,
        port: port,
        interval: 60,
        retryInterval: 60,
        maxretries: 3,
        active: true
      }, (res) => {
        if (res.ok) {
          console.log(`[Kuma] Created monitor: ${name} (ID: ${res.monitorID})`);
          resolve(res.monitorID);
        } else {
          reject(new Error(`Kuma create failed: ${res.msg}`));
        }
      });
    });
  });
}

/**
 * Delete a monitor by name.
 * Finds the monitor first, then deletes by ID.
 * @param {string} name - Monitor name to delete
 */
async function deleteMonitor(name) {
  return withKuma((socket) => {
    return new Promise((resolve, reject) => {
      socket.emit('getMonitorList', (monitors) => {
        const list = Object.values(monitors);
        const monitor = list.find(m => m.name === name);
        if (!monitor) {
          console.log(`[Kuma] Monitor not found: ${name}`);
          resolve(null);
          return;
        }
        socket.emit('deleteMonitor', monitor.id, (res) => {
          if (res.ok) {
            console.log(`[Kuma] Deleted monitor: ${name} (ID: ${monitor.id})`);
            resolve(monitor.id);
          } else {
            reject(new Error(`Kuma delete failed: ${res.msg}`));
          }
        });
      });
    });
  });
}

module.exports = { getMonitors, createMonitor, deleteMonitor };
