<?php
// admin/api/hud_stats.php
// LIVE HUD data:
// 1) WAN (ISP) traffic from /interface/monitor-traffic  -> "wan_rx_mbps / wan_tx_mbps"
// 2) مجموع سرعة جميع الجلسات (PPP Active) عبر دلتا عدادات rx/tx-bytes -> "sess_rx_mbps / sess_tx_mbps"
// Uses same MikroTik settings/connection as the program (mikrotik_lib.php)

require_once __DIR__ . '/../auth.php';
if (function_exists('require_login')) require_login('login.php');
require_once __DIR__ . '/../db_bootstrap.php';
if (function_exists('ensure_db')) ensure_db(true);

require_once __DIR__ . '/../mikrotik_lib.php';
require_once __DIR__ . '/../ua_unified_stats_lib.php';
require_once __DIR__ . '/../stats_snapshot_lib.php';

header('Content-Type: application/json; charset=utf-8');

$conn = $GLOBALS['conn'] ?? null;
if (!($conn instanceof mysqli)) {
  http_response_code(500);
  echo json_encode(['ok'=>false,'reason'=>'db_not_ready']);
  exit;
}

mysqli_report(MYSQLI_REPORT_OFF);

/* ---------------- settings (DB) ----------------
   Support BOTH schemas:
   - legacy: (key,value)
   - current: (id, setting_key, setting_value)
*/
function ua_app_settings_schema(mysqli $conn): string {
  static $schema = null;
  if ($schema !== null) return $schema;
  try {
    $rs = @$conn->query("SHOW COLUMNS FROM app_settings LIKE 'setting_key'");
    if ($rs && $rs->num_rows > 0) { $schema = 'setting_key'; return $schema; }
  } catch (Throwable $e) {}
  $schema = 'key';
  return $schema;
}
function ensure_settings_table(mysqli $conn): void {
  $sql = "CREATE TABLE IF NOT EXISTS app_settings (
    `id` INT AUTO_INCREMENT PRIMARY KEY,
    `setting_key` VARCHAR(100) NOT NULL,
    `setting_value` LONGTEXT NULL,
    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY `uniq_setting_key` (`setting_key`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
  @$conn->query($sql);
}
function get_setting(mysqli $conn, string $key, $default=null) {
  $schema = ua_app_settings_schema($conn);
  $keyEsc = $conn->real_escape_string($key);
  if ($schema === 'setting_key') {
    $r = @$conn->query("SELECT `setting_value` AS v FROM app_settings WHERE `setting_key`='$keyEsc' LIMIT 1");
  } else {
    $r = @$conn->query("SELECT `value` AS v FROM app_settings WHERE `key`='$keyEsc' LIMIT 1");
  }
  if ($r && ($row=$r->fetch_assoc())) return $row['v'];
  return $default;
}
function set_setting(mysqli $conn, string $key, string $value): void {
  $schema = ua_app_settings_schema($conn);
  if ($schema === 'setting_key') {
    $stmt = @$conn->prepare("INSERT INTO app_settings (`setting_key`,`setting_value`) VALUES (?,?)
      ON DUPLICATE KEY UPDATE `setting_value`=VALUES(`setting_value`), updated_at=NOW()");
  } else {
    $stmt = @$conn->prepare("INSERT INTO app_settings (`key`,`value`) VALUES (?,?)
      ON DUPLICATE KEY UPDATE `value`=VALUES(`value`), updated_at=NOW()");
  }
  if ($stmt) {
    $stmt->bind_param('ss', $key, $value);
    $stmt->execute();
    $stmt->close();
  }
}
ensure_settings_table($conn);

$mode = get_setting($conn, 'hud_iface_mode', 'auto');            // auto|manual
$manualIface = trim((string)get_setting($conn, 'hud_iface_name', ''));
$maxMbps = (float)get_setting($conn, 'hud_max_mbps', '300');
if ($maxMbps < 10) $maxMbps = 300;

/* --------- cache table for PPP delta aggregation ---------- */
function ensure_ppp_cache(mysqli $conn): void {
  $sql = "CREATE TABLE IF NOT EXISTS hud_ppp_cache (
    username VARCHAR(120) NOT NULL PRIMARY KEY,
    last_rx BIGINT NOT NULL DEFAULT 0,
    last_tx BIGINT NOT NULL DEFAULT 0,
    last_at INT NOT NULL DEFAULT 0
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
  @$conn->query($sql);
}

/* ---------- Persisted PPP usage (monthly) ---------- */
function ensure_ppp_usage_monthly(mysqli $conn): void {
  // Table may already exist in your DB; this is safe.
  $sql = "CREATE TABLE IF NOT EXISTS ppp_usage_monthly (
    id INT AUTO_INCREMENT PRIMARY KEY,
    subscriber_id INT NOT NULL,
    month_key CHAR(7) NOT NULL,
    used_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uq_sub_month (subscriber_id, month_key),
    KEY idx_month (month_key),
    KEY idx_sub (subscriber_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
  @$conn->query($sql);
}

/* ---------------- unified subscriber counts ---------------- */
$uaCounts = function_exists('ua_app_stats_snapshot') ? ua_app_stats_snapshot($conn, 10, false) : (function_exists('ua_unified_stats') ? ua_unified_stats($conn, 10) : []);
$subscribersTotal = (int)($uaCounts['total'] ?? 0);
$subscribersOnline = (int)($uaCounts['online'] ?? 0);

$out = [
  'ok' => true,
  'router' => ['state' => 'OFFLINE', 'host' => null],
  'users' => ['db_online' => $subscribersOnline, 'ppp_active' => $subscribersOnline, 'total' => $subscribersTotal, 'offline'=>(int)($uaCounts['offline'] ?? 0), 'disabled'=>(int)($uaCounts['disabled'] ?? 0), 'unsafe_speed'=>(int)($uaCounts['unsafe_speed'] ?? 0), 'source'=>(string)($uaCounts['online_source'] ?? 'unified')],
  'kpi' => [
    'wan_rx_mbps'=>0.0,'wan_tx_mbps'=>0.0,'wan_total_mbps'=>0.0,
    'sess_rx_mbps'=>0.0,'sess_tx_mbps'=>0.0,'sess_total_mbps'=>0.0,
    'cpu_pct'=>0,'ram_pct'=>0,'uptime'=>"—"
  ],
  'gauges' => [
    'isp_download_mbps'=>0.0,
    'isp_upload_mbps'=>0.0,
    'sessions_download_mbps'=>0.0,
    'sessions_upload_mbps'=>0.0,
    'max_mbps'=>$maxMbps
  ],
  'alerts' => 0,
  'server_time' => date('Y-m-d H:i:s'),
  'iface' => ['mode'=>$mode, 'manual'=>$manualIface, 'selected'=>null],
];

$cfg = mt_get_settings($conn);
if ($cfg) $out['router']['host'] = trim((string)($cfg['host'] ?? '')) ?: null;

$api = mt_api_connect($conn);
if (!$api) {
  $out['ok'] = false;
  $out['reason'] = 'mikrotik_connect_failed';
  $out['error'] = (string)($GLOBALS['mt_last_error'] ?? 'فشل الاتصال بالراوتر');
  echo json_encode($out);
  exit;
}

$out['router']['state'] = 'ONLINE';

try {
  // system resources
  $rows = $api->command(['/system/resource/print']);
  foreach ($rows as $r) {
    if (($r['.type'] ?? '') !== '!re') continue;
    $cpu = (int)($r['cpu-load'] ?? 0);
    $free = (int)($r['free-memory'] ?? 0);
    $total = (int)($r['total-memory'] ?? 0);
    $ramPct = ($total > 0) ? (int)round((1 - ($free / $total)) * 100) : 0;

    $out['kpi']['cpu_pct'] = max(0, min(100, $cpu));
    $out['kpi']['ram_pct'] = max(0, min(100, $ramPct));
    $out['kpi']['uptime']  = (string)($r['uptime'] ?? '—');
    break;
  }

  // PPP active rows (per-session counters)
  $ppp = mt_ppp_active($conn);
  // اترك عداد المشتركين من المصدر الموحد؛ نستخدم الجلسات هنا فقط لحساب سرعات الجلسات.
  if (is_array($ppp)) $out['users']['ppp_active_raw'] = count($ppp);

  // ---------- Interface selection (WAN / ISP) ----------
  $selectedIface = null;

  if ($mode === 'manual' && $manualIface !== '') {
    $selectedIface = $manualIface;
  }

  // cached auto (10 minutes)
  if (!$selectedIface && $mode !== 'manual') {
    $cached = trim((string)get_setting($conn, 'hud_iface_last', ''));
    $cachedAt = (int)get_setting($conn, 'hud_iface_last_at', '0');
    if ($cached !== '' && $cachedAt > 0 && (time() - $cachedAt) < 600) $selectedIface = $cached;
  }

  // best-effort guess based on default route / running iface
  if (!$selectedIface && $mode !== 'manual' && function_exists('mt_autodetect_wan_iface')) {
    $guess = trim((string)mt_autodetect_wan_iface($api));
    if ($guess !== '') $selectedIface = $guess;
  }

  // Read WAN traffic
  $wan_rx_bps = 0;
  $wan_tx_bps = 0;
  if ($selectedIface) {
    $m = mt_monitor_traffic($api, $selectedIface);
    $wan_rx_bps = (int)($m['rx_bps'] ?? 0);
    $wan_tx_bps = (int)($m['tx_bps'] ?? 0);
  }

  // If still no traffic and auto mode -> scan best interface
  if ($mode !== 'manual' && (!$selectedIface || ($wan_rx_bps + $wan_tx_bps) <= 0)) {
    $cands = [];
    foreach (['pppoe-out1','ether1','ether2','bridge','bridge1','WAN','wan','internet','sfp1','wlan1'] as $c) $cands[] = $c;

    if (function_exists('mt_list_interfaces')) {
      $list = mt_list_interfaces($api, 200);
      foreach ($list as $it) {
        $name = trim((string)($it['name'] ?? ''));
        if ($name === '') continue;
        if (!in_array($name, $cands, true)) $cands[] = $name;
        if (count($cands) >= 30) break;
      }
    }

    $bestIface = null;
    $bestSum = 0;
    $bestRx = 0; $bestTx = 0;

    foreach ($cands as $iface) {
      $m = mt_monitor_traffic($api, $iface);
      $rxb = (int)($m['rx_bps'] ?? 0);
      $txb = (int)($m['tx_bps'] ?? 0);
      $sum = $rxb + $txb;
      if ($sum > $bestSum) {
        $bestSum = $sum;
        $bestIface = $iface;
        $bestRx = $rxb;
        $bestTx = $txb;
      }
    }

    if ($bestIface) {
      $selectedIface = $bestIface;
      $wan_rx_bps = $bestRx;
      $wan_tx_bps = $bestTx;
      set_setting($conn, 'hud_iface_last', $selectedIface);
      set_setting($conn, 'hud_iface_last_at', (string)time());
    }
  }

  $out['iface']['selected'] = $selectedIface;

  $wan_rx = $wan_rx_bps / 1000000.0;
  $wan_tx = $wan_tx_bps / 1000000.0;

  $out['kpi']['wan_rx_mbps'] = round($wan_rx, 1);
  $out['kpi']['wan_tx_mbps'] = round($wan_tx, 1);
  $out['kpi']['wan_total_mbps'] = round($wan_rx + $wan_tx, 1);

  // ---------- Sessions totals (delta aggregation from /ppp/active rx/tx bytes) ----------
  $sess_rx_mbps = 0.0;
  $sess_tx_mbps = 0.0;

  if (is_array($ppp)) {
    ensure_ppp_cache($conn);
    ensure_ppp_usage_monthly($conn);

    $now = time();
    $sum_rx_bps = 0.0;
    $sum_tx_bps = 0.0;

    $sel = $conn->prepare("SELECT last_rx,last_tx,last_at FROM hud_ppp_cache WHERE username=? LIMIT 1");
    $up  = $conn->prepare("INSERT INTO hud_ppp_cache (username,last_rx,last_tx,last_at) VALUES (?,?,?,?)
              ON DUPLICATE KEY UPDATE last_rx=VALUES(last_rx), last_tx=VALUES(last_tx), last_at=VALUES(last_at)");

    
    // Map PPP usernames to subscriber IDs (ppp_username preferred, fallback to username)
    $pppUsers = [];
    foreach ($ppp as $r) {
      $n = trim((string)($r['name'] ?? ''));
      if ($n !== '') $pppUsers[$n] = true;
    }
    $subIdByUser = [];
    if ($pppUsers) {
      $list = array_keys($pppUsers);
      $ph = implode(',', array_fill(0, count($list), '?'));
      $sqlMap = "SELECT id, ppp_username, username FROM subscribers WHERE (ppp_username IN ($ph)) OR (username IN ($ph))";
      $stmtMap = $conn->prepare($sqlMap);
      if ($stmtMap) {
        $types = str_repeat('s', count($list) * 2);
        $args = array_merge($list, $list);
        $stmtMap->bind_param($types, ...$args);
        if ($stmtMap->execute()) {
          $rsMap = $stmtMap->get_result();
          while ($r = $rsMap->fetch_assoc()) {
            $sid = (int)($r['id'] ?? 0);
            $pu  = trim((string)($r['ppp_username'] ?? ''));
            $un  = trim((string)($r['username'] ?? ''));
            if ($sid > 0) {
              if ($pu !== '') $subIdByUser[$pu] = $sid;
              if ($un !== '' && !isset($subIdByUser[$un])) $subIdByUser[$un] = $sid;
            }
          }
        }
        $stmtMap->close();
      }
    }

    $monthKey = date('Y-m');
    $upMonth = $conn->prepare("INSERT INTO ppp_usage_monthly (subscriber_id, month_key, used_bytes) VALUES (?,?,?)
                    ON DUPLICATE KEY UPDATE used_bytes = used_bytes + VALUES(used_bytes)");
foreach ($ppp as $row) {
      $u = trim((string)($row['name'] ?? ''));
      if ($u === '') continue;

      $rxB = (int)($row['rx_bytes'] ?? 0);
      $txB = (int)($row['tx_bytes'] ?? 0);

      $last_rx = 0; $last_tx = 0; $last_at = 0;
      if ($sel) {
        $sel->bind_param('s', $u);
        if ($sel->execute()) {
          $res = $sel->get_result();
          if ($res && ($r0 = $res->fetch_assoc())) {
            $last_rx = (int)($r0['last_rx'] ?? 0);
            $last_tx = (int)($r0['last_tx'] ?? 0);
            $last_at = (int)($r0['last_at'] ?? 0);
          }
        }
      }

      $dt = $now - $last_at;
      if ($dt <= 0 || $dt > 600) $dt = 0;

      if ($dt > 0) {
        $drx = $rxB - $last_rx;
        $dtx = $txB - $last_tx;
        if ($drx < 0) $drx = 0;
        if ($dtx < 0) $dtx = 0;

        $sum_rx_bps += ($drx * 8.0) / $dt;
        $sum_tx_bps += ($dtx * 8.0) / $dt;
      }

      
      // Persist monthly usage so reboot won't reset displayed consumption
      $deltaBytes = ($rxB + $txB) - ($last_rx + $last_tx);
      if ($deltaBytes < 0) {
        // counters reset (reboot / reconnect) -> keep previous total and add current session counters
        $deltaBytes = ($rxB + $txB);
      }
      if ($deltaBytes > 0 && isset($subIdByUser[$u]) && $upMonth) {
        $sid = (int)$subIdByUser[$u];
        $deltaStr = (string)$deltaBytes;
        $upMonth->bind_param('iss', $sid, $monthKey, $deltaStr);
        $upMonth->execute();
      }

if ($up) {
        $up->bind_param('siii', $u, $rxB, $txB, $now);
        $up->execute();
      }
    }

    if ($sel) $sel->close();
    if ($up) $up->close();
    if ($upMonth) $upMonth->close();

    $sess_rx_mbps = ($sum_rx_bps / 1000000.0);
    $sess_tx_mbps = ($sum_tx_bps / 1000000.0);
  }

  $out['kpi']['sess_rx_mbps'] = round($sess_rx_mbps, 1);
  $out['kpi']['sess_tx_mbps'] = round($sess_tx_mbps, 1);
  $out['kpi']['sess_total_mbps'] = round($sess_rx_mbps + $sess_tx_mbps, 1);

  // Gauges mapping
  $out['gauges']['isp_download_mbps'] = $out['kpi']['wan_rx_mbps'];
  $out['gauges']['isp_upload_mbps']   = $out['kpi']['wan_tx_mbps'];
  $out['gauges']['sessions_download_mbps'] = $out['kpi']['sess_rx_mbps'];
  $out['gauges']['sessions_upload_mbps']   = $out['kpi']['sess_tx_mbps'];

  echo json_encode($out);
  exit;

} catch (Throwable $e) {
  $out['ok'] = false;
  $out['reason'] = 'exception';
  $out['error'] = $e->getMessage();
  echo json_encode($out);
  exit;
} finally {
  try { $api->disconnect(); } catch (Throwable $e) {}
}
