import os from 'os';
import path from 'path';
import { execFileSync } from 'child_process';
import fs from 'fs';
import { pool } from '../config/database.js';

/**
 * Get CPU usage percentage
 */
const getCpuUsage = () => {
  const cpus = os.cpus();
  let totalIdle = 0;
  let totalTick = 0;

  cpus.forEach((cpu) => {
    for (const type in cpu.times) {
      totalTick += cpu.times[type];
    }
    totalIdle += cpu.times.idle;
  });

  const idle = totalIdle / cpus.length;
  const total = totalTick / cpus.length;
  const percent = Math.round(((total - idle) / total) * 100);

  return { percent };
};

/**
 * Get memory usage (Linux - reads /proc/meminfo for accurate values)
 */
const getMemoryUsage = () => {
  try {
    // Read /proc/meminfo for accurate memory stats (like htop)
    const meminfo = fs.readFileSync('/proc/meminfo', 'utf8');
    const lines = meminfo.split('\n');

    const getValue = (key) => {
      const line = lines.find(l => l.startsWith(key));
      if (!line) return 0;
      const match = line.match(/(\d+)/);
      return match ? parseInt(match[1]) : 0;
    };

    const totalKB = getValue('MemTotal');
    const freeKB = getValue('MemFree');
    const buffersKB = getValue('Buffers');
    const cachedKB = getValue('Cached');
    const sreclaimableKB = getValue('SReclaimable');

    // Available = Free + Buffers + Cached + SReclaimable (like htop calculates)
    const availableKB = freeKB + buffersKB + cachedKB + sreclaimableKB;
    const usedKB = totalKB - availableKB;

    // Convert to GB
    const totalGB = Math.round((totalKB / (1024 ** 2)) * 10) / 10;
    const usedGB = Math.round((usedKB / (1024 ** 2)) * 10) / 10;

    return {
      used: usedGB,
      total: totalGB,
      unit: 'GB',
    };
  } catch {
    // Fallback to os module
    const totalBytes = os.totalmem();
    const freeBytes = os.freemem();
    const usedBytes = totalBytes - freeBytes;

    return {
      used: Math.round((usedBytes / (1024 ** 3)) * 10) / 10,
      total: Math.round((totalBytes / (1024 ** 3)) * 10) / 10,
      unit: 'GB',
    };
  }
};

/**
 * Get disk usage (Linux/macOS)
 */
const getDiskUsage = () => {
  try {
    const output = execFileSync('df', ['-BG', '/'], { encoding: 'utf8' });
    const lines = output.trim().split('\n');
    const parts = lines[lines.length - 1].split(/\s+/);

    const totalGB = parseInt(parts[1]) || 0;
    const usedGB = parseInt(parts[2]) || 0;

    return {
      used: usedGB,
      total: totalGB,
      unit: 'GB',
    };
  } catch {
    return { used: 0, total: 0, unit: 'GB' };
  }
};

/**
 * Get Node.js backend process stats (CPU + RAM)
 */
const getBackendStats = () => {
  const memUsage = process.memoryUsage();

  // Get CPU usage for this process
  const cpuUsage = process.cpuUsage();
  const cpuPercent = Math.round(((cpuUsage.user + cpuUsage.system) / 1000000) * 100) / 100;

  return {
    memoryMB: Math.round((memUsage.rss / (1024 ** 2)) * 10) / 10,
    heapMB: Math.round((memUsage.heapUsed / (1024 ** 2)) * 10) / 10,
    cpuTime: cpuPercent, // CPU time in seconds
  };
};

/**
 * Get uploads directory size
 */
const getUploadsSize = () => {
  try {
    const uploadsPath = path.join(process.cwd(), 'uploads');
    const output = execFileSync('du', ['-sm', uploadsPath], { encoding: 'utf8' });
    const sizeMB = parseInt(output.split('\t')[0]) || 0;

    return {
      sizeMB,
      unit: 'MB',
    };
  } catch {
    return { sizeMB: 0, unit: 'MB' };
  }
};

/**
 * Get database table count
 */
const getTableCount = async () => {
  try {
    const result = await pool.query(`
      SELECT COUNT(*) as count
      FROM information_schema.tables
      WHERE table_schema = 'public'
      AND table_type = 'BASE TABLE'
    `);
    return parseInt(result.rows[0]?.count) || 0;
  } catch {
    return 0;
  }
};

/**
 * Get system uptime in seconds
 */
const getSystemUptime = () => {
  return Math.floor(os.uptime());
};

/**
 * Get Node.js process uptime in seconds
 */
const getProcessUptime = () => {
  return Math.floor(process.uptime());
};

/**
 * Get complete server status
 */
export const getServerStatus = async () => {
  const tableCount = await getTableCount();

  return {
    cpu: getCpuUsage(),
    memory: getMemoryUsage(),
    disk: getDiskUsage(),
    backend: getBackendStats(),
    uploads: getUploadsSize(),
    database: {
      tableCount,
    },
    systemUptimeSec: getSystemUptime(),
    backendUptimeSec: getProcessUptime(),
    hostname: os.hostname(),
    platform: os.platform(),
    nodeVersion: process.version,
    timestamp: new Date().toISOString(),
  };
};
