<?php
// admin/speed_gauges_lib.php
// Single authoritative data source for speed gauge readings.
// UI widgets must consume api/speed_gauges.php; this library owns MikroTik/settings calculations.

if (!function_exists('ua_speed_bytes_to_gb')) {
  function ua_speed_bytes_to_gb($b){ return round(((float)$b) / 1073741824.0, 3); }
}

if (!function_exists('ua_speed_normalize_iface_name')) {
  function ua_speed_normalize_iface_name($v){
    // Convert whatever comes back (string/array/object) into a clean interface name string.
    if (is_string($v)) return trim($v);
    if (is_numeric($v)) return trim((string)$v);

    if (is_array($v)) {
      // Common case: ['name' => 'ether1', ...]
      if (isset($v['name']) && is_scalar($v['name'])) return trim((string)$v['name']);
      // Sometimes: ['iface' => 'ether1'] or similar
      foreach (['iface','interface','wan','value'] as $k) {
        if (isset($v[$k]) && is_scalar($v[$k])) return trim((string)$v[$k]);
      }
      // Fallback: first scalar element
      $first = reset($v);
      if (is_scalar($first)) return trim((string)$first);
      return '';
    }

    if (is_object($v)) {
      if (isset($v->name) && is_scalar($v->name)) return trim((string)$v->name);
      return '';
    }

    return '';
  }
}

if (!function_exists('ua_speed_parse_ros_rate')) {
  function ua_speed_parse_ros_rate($v){
    if (is_int($v) || is_float($v)) return (float)$v;
    $s = trim((string)$v);
    if ($s === '') return 0.0;

    if (strpos($s, '/') !== false) {
      $parts = explode('/', $s, 2);
      return ua_speed_parse_ros_rate($parts[0]) + ua_speed_parse_ros_rate($parts[1]);
    }

    if (!preg_match('/([0-9]+(?:\.[0-9]+)?)(\s*[kKmMgGtT]?[bB]?(?:ps)?)?/', $s, $m)) return 0.0;
    $num = (float)$m[1];
    $unit = strtolower(trim($m[2] ?? ''));

    if (strpos($unit, 'g') !== false) $num *= 1e9;
    else if (strpos($unit, 'm') !== false) $num *= 1e6;
    else if (strpos($unit, 'k') !== false) $num *= 1e3;

    if (strpos($unit, 'b') === false && strpos($unit, 'B') !== false) $num *= 8.0;
    return $num;
  }
}

if (!function_exists('ua_speed_sum_hotspot_active_bps')) {
  function ua_speed_sum_hotspot_active_bps($api){
    $sum = 0.0;
    $rows = $api->command(['/ip/hotspot/active/print']);
    foreach($rows as $r){
      if (($r['.type'] ?? '') !== '!re') continue;
      $sum += ua_speed_parse_ros_rate($r['rx-rate'] ?? 0);
      $sum += ua_speed_parse_ros_rate($r['tx-rate'] ?? 0);
    }
    return (int)round($sum);
  }
}

if (!function_exists('ua_speed_sum_simple_queue_bps')) {
  function ua_speed_sum_simple_queue_bps($api){
    $sum = 0.0;
    $rows = $api->command(['/queue/simple/print']);
    foreach($rows as $r){
      if (($r['.type'] ?? '') !== '!re') continue;
      if (isset($r['rate'])) $sum += ua_speed_parse_ros_rate($r['rate']);
      elseif (isset($r['current-rate'])) $sum += ua_speed_parse_ros_rate($r['current-rate']);
    }
    return (int)round($sum);
  }
}

if (!function_exists('ua_speed_default_payload')) {
  function ua_speed_default_payload(): array {
    return [
      'status' => 'offline',
      'rx_bps' => 0,
      'tx_bps' => 0,
      'consumed_bps' => 0,
      'rx_gb'  => 0,
      'tx_gb'  => 0,
      'iface'  => null,
      'message'=> 'لا يوجد اتصال MikroTik — العدادات ثابتة على 0'
    ];
  }
}

if (!function_exists('ua_speed_gauges_payload')) {
  function ua_speed_gauges_payload(): array {
    $admin = __DIR__;

    if (is_file($admin.'/helpers.php')) require_once $admin.'/helpers.php';
    if (is_file($admin.'/db_bootstrap.php')) require_once $admin.'/db_bootstrap.php';
    if (is_file($admin.'/mikrotik_lib.php')) require_once $admin.'/mikrotik_lib.php';

    $resp = ua_speed_default_payload();

    $conn = null;
    if (function_exists('ensure_db')) {
      try { $conn = ensure_db(false); } catch (Throwable $e) { $conn = null; }
    } elseif (isset($GLOBALS['conn']) && $GLOBALS['conn'] instanceof mysqli) {
      $conn = $GLOBALS['conn'];
    }

    if (!($conn instanceof mysqli) || !function_exists('mt_api_connect')) return $resp;

    // Determine WAN iface
    $iface = '';
    // Prefer explicit WAN interface from MikroTik settings page (stored in app_settings)
    if (function_exists('get_app_setting')) {
      $iface = ua_speed_normalize_iface_name(get_app_setting($conn, 'mikrotik_wan_interface', ''));
      if ($iface === '') $iface = ua_speed_normalize_iface_name(get_app_setting($conn, 'speed_iface', ''));
    }

    if ($iface === '' && function_exists('mt_autodetect_wan_iface')) {
      try {
        $det = mt_autodetect_wan_iface($conn);
        $iface = ua_speed_normalize_iface_name($det);
      } catch (Throwable $e) {
        $iface = '';
      }

      if ($iface !== '' && function_exists('set_app_setting')) {
        try { set_app_setting($conn, 'speed_iface', $iface); } catch (Throwable $e) {}
      }
    }

    $resp['iface'] = ($iface !== '') ? $iface : null;

    try {
      $api = mt_api_connect($conn);

      // consumed total
      $cons = 0;
      try { $cons = ua_speed_sum_hotspot_active_bps($api); } catch (Throwable $e) { $cons = 0; }
      if ($cons <= 0) {
        try { $cons = ua_speed_sum_simple_queue_bps($api); } catch (Throwable $e) { $cons = 0; }
      }
      $resp['consumed_bps'] = max(0, (int)$cons);

      // WAN speed
      if ($iface !== '' && function_exists('mt_monitor_traffic')) {
        try {
          $t = mt_monitor_traffic($conn, $iface);
          $resp['rx_bps'] = (int)($t['rx_bps'] ?? 0);
          $resp['tx_bps'] = (int)($t['tx_bps'] ?? 0);
        } catch (Throwable $e) {}
      }

      // daily usage via interface counters (optional)
      $rx_bytes = 0; $tx_bytes = 0;
      if ($iface !== '') {
        try {
          $rows = $api->command(['/interface/print']);
          foreach($rows as $r){
            if (($r['.type'] ?? '') !== '!re') continue;
            if (($r['name'] ?? '') !== $iface) continue;
            $rx_bytes = (int)($r['rx-byte'] ?? $r['rx-bytes'] ?? 0);
            $tx_bytes = (int)($r['tx-byte'] ?? $r['tx-bytes'] ?? 0);
            break;
          }
        } catch (Throwable $e) {}
      }

      $tot_rx = 0; $tot_tx = 0;
      if (function_exists('get_app_setting') && function_exists('set_app_setting')) {
        $today = date('Y-m-d');
        $day = (string)get_app_setting($conn, 'speed_usage_day', '');
        if ($day !== $today) {
          set_app_setting($conn, 'speed_usage_day', $today);
          set_app_setting($conn, 'speed_usage_total_rx', '0');
          set_app_setting($conn, 'speed_usage_total_tx', '0');
          set_app_setting($conn, 'speed_usage_last_rx', (string)$rx_bytes);
          set_app_setting($conn, 'speed_usage_last_tx', (string)$tx_bytes);
        } else {
          $last_rx = (int)get_app_setting($conn, 'speed_usage_last_rx', '0');
          $last_tx = (int)get_app_setting($conn, 'speed_usage_last_tx', '0');
          $tot_rx  = (int)get_app_setting($conn, 'speed_usage_total_rx', '0');
          $tot_tx  = (int)get_app_setting($conn, 'speed_usage_total_tx', '0');

          if ($rx_bytes > 0 && $rx_bytes >= $last_rx) $tot_rx += ($rx_bytes - $last_rx);
          if ($tx_bytes > 0 && $tx_bytes >= $last_tx) $tot_tx += ($tx_bytes - $last_tx);

          set_app_setting($conn, 'speed_usage_last_rx', (string)$rx_bytes);
          set_app_setting($conn, 'speed_usage_last_tx', (string)$tx_bytes);
          set_app_setting($conn, 'speed_usage_total_rx', (string)$tot_rx);
          set_app_setting($conn, 'speed_usage_total_tx', (string)$tot_tx);
        }
      }

      $resp['rx_gb'] = max(0, ua_speed_bytes_to_gb($tot_rx));
      $resp['tx_gb'] = max(0, ua_speed_bytes_to_gb($tot_tx));

      // Connected if API succeeded (even when traffic is 0)
      $resp['status'] = 'ok';
      $resp['message'] = 'ok';

      if (isset($api) && is_object($api) && method_exists($api, 'disconnect')) {
        try { $api->disconnect(); } catch (Throwable $e) {}
      }
    } catch (Throwable $e) {
      $resp['status'] = 'offline';
      $resp['message'] = (string)($GLOBALS['mt_last_error'] ?? $e->getMessage() ?? 'لا يوجد اتصال MikroTik');
    }

    return $resp;
  }
}
