<?php
// admin/quota_setup.php
// One-click setup: install/update MikroTik quota_enforcer script + scheduler.
// Works even if program is closed because MikroTik runs the scheduler itself.

if (session_status() === PHP_SESSION_NONE) session_start();

require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/lang.php';
require_once __DIR__ . '/auth.php';
require_once __DIR__ . '/db_bootstrap.php';
require_once __DIR__ . '/mikrotik_lib.php';

require_login('index.php?login=1');
if (function_exists('require_perm')) require_perm('can_manage_subscribers'); // عدّلها إذا عندك صلاحية خاصة

$page_title = 'تهيئة نظام الحجم والقص (MikroTik)';

// ✅ لا نعيد تعريف h() لأن helpers.php يعرفها.
// لكن لو لم تكن موجودة لأي سبب، نعرّفها بشكل آمن.
if (!function_exists('h')) {
  function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}

/**
 * Backward-compatible fallback only. The canonical implementation lives in mikrotik_connection_lib.php.
 */
if (!function_exists('mt_call')) {
function mt_call($api, $path, $params = []) {
  if (is_object($api) && method_exists($api, 'comm')) {
    return $api->comm($path, $params);
  }
  if (is_object($api) && method_exists($api, 'command')) {
    $cmd = [$path];
    foreach ($params as $k => $v) {
      if ($k === '.id') $cmd[] = '=.id=' . $v;
      else $cmd[] = '=' . $k . '=' . $v;
    }
    return $api->command($cmd);
  }
  return null;
}
}

// Script source (RouterOS). Keep it as-is.
$script_name = 'quota_enforcer';
$sched_name  = 'quota-enforcer';
$interval    = '1m';
$limitRate   = '512k/512k';

// Package map: change here if needed
$pkg50  = 50;
$pkg75  = 75;
$pkg100 = 100;
$pkg125 = 125;

$script_source = <<<ROS
# quota_enforcer
# PPPoE quota enforcer - runs on MikroTik (independent from the program)
# Uses /ppp active bytes-in/out (active sessions).
# Stores:
#   UB= used bytes accumulator
#   LB= last seen bytes counter
#   STATE=OK/QUOTA
# Reads:
#   Q= override quota in GB (subscriber override)
#   PKG= package name (50G/75G/100G/125G/مفتوح or OPEN)
# Applies:
#   rate-limit={$limitRate} when quota exceeded, then disconnects session to apply quickly.

:local limitRate "{$limitRate}"

:local pkg50 {$pkg50}
:local pkg75 {$pkg75}
:local pkg100 {$pkg100}
:local pkg125 {$pkg125}

:local getTag do={
  :local c \$1
  :local t (\$2."=")
  :local p [:find \$c \$t]
  :if (\$p = -1) do={ :return "" }
  :local s (\$p + [:len \$t])
  :local e [:find \$c " | " \$s]
  :if (\$e = -1) do={ :return [:pick \$c \$s [:len \$c]] }
  :return [:pick \$c \$s \$e]
}

:local setTag do={
  :local c \$1
  :local t (\$2."=")
  :local p [:find \$c \$t]
  :if (\$p = -1) do={
    :if ([:len \$c] = 0) do={ :return (\$t.\$3) }
    :return (\$c." | ".\$t.\$3)
  }
  :local vs (\$p + [:len \$t])
  :local e [:find \$c " | " \$vs]
  :if (\$e = -1) do={ :return ([:pick \$c 0 \$vs].\$3) }
  :return ([:pick \$c 0 \$vs].\$3.[:pick \$c \$e [:len \$c]])
}

:foreach a in=[/ppp active find] do={
  :local name [/ppp active get \$a name]
  :local bin [/ppp active get \$a bytes-in]
  :local bout [/ppp active get \$a bytes-out]
  :local cur (\$bin + \$bout)

  :local sid [/ppp secret find where name=\$name]
  :if ([:len \$sid] = 0) do={ :continue }

  :local c [/ppp secret get \$sid comment]

  :local qStr [\$getTag \$c "Q"]
  :local pkgStr [\$getTag \$c "PKG"]

  :local quotaGB 0
  :if ([:len \$qStr] > 0) do={
    :set quotaGB [:tonum \$qStr]
  } else={
    :if (\$pkgStr = "50G") do={ :set quotaGB \$pkg50 }
    :if (\$pkgStr = "75G") do={ :set quotaGB \$pkg75 }
    :if (\$pkgStr = "100G") do={ :set quotaGB \$pkg100 }
    :if (\$pkgStr = "125G") do={ :set quotaGB \$pkg125 }
    :if (\$pkgStr = "مفتوح" || \$pkgStr = "OPEN") do={ :set quotaGB 0 }
  }

  :if (\$quotaGB <= 0) do={
    :local st [\$getTag \$c "STATE"]
    :if (\$st = "QUOTA") do={
      /ppp secret set \$sid rate-limit=""
      :set c [\$setTag \$c "STATE" "OK"]
      /ppp secret set \$sid comment=\$c
    }
    :continue
  }

  :local ubStr [\$getTag \$c "UB"]
  :local lbStr [\$getTag \$c "LB"]
  :local used 0
  :local last 0
  :if ([:len \$ubStr] > 0) do={ :set used [:tonum \$ubStr] }
  :if ([:len \$lbStr] > 0) do={ :set last [:tonum \$lbStr] }

  :local delta (\$cur - \$last)
  :if (\$delta < 0) do={ :set delta \$cur }
  :set used (\$used + \$delta)

  :set c [\$setTag \$c "UB" \$used]
  :set c [\$setTag \$c "LB" \$cur]

  :local quotaBytes (\$quotaGB * 1024 * 1024 * 1024)

  :if (\$used >= \$quotaBytes) do={
    /ppp secret set \$sid rate-limit=\$limitRate
    :set c [\$setTag \$c "STATE" "QUOTA"]
    /ppp secret set \$sid comment=\$c
    /ppp active remove \$a
  } else={
    :local st [\$getTag \$c "STATE"]
    :if (\$st = "QUOTA") do={
      /ppp secret set \$sid rate-limit=""
      :set c [\$setTag \$c "STATE" "OK"]
    }
    /ppp secret set \$sid comment=\$c
  }
}
ROS;

$log = [];
$err = '';

if (isset($_POST['do_setup'])) {
  $api = mt_api_connect();
  if (!$api) {
    $err = '❌ فشل الاتصال بالمايكروتك';
  } else {
    // 1) Ensure script exists (add or update)
    $scripts = mt_call($api, '/system/script/print', []);
    $script_id = null;
    if (is_array($scripts)) {
      foreach ($scripts as $s) {
        if (($s['name'] ?? '') === $script_name) { $script_id = $s['.id'] ?? null; break; }
      }
    }

    if ($script_id) {
      mt_call($api, '/system/script/set', ['.id' => $script_id, 'name' => $script_name, 'source' => $script_source]);
      $log[] = "✅ تم تحديث Script: {$script_name}";
    } else {
      mt_call($api, '/system/script/add', ['name' => $script_name, 'source' => $script_source]);
      $log[] = "✅ تم إنشاء Script: {$script_name}";
    }

    // 2) Ensure scheduler exists (add or update)
    $scheds = mt_call($api, '/system/scheduler/print', []);
    $sched_id = null;
    if (is_array($scheds)) {
      foreach ($scheds as $s) {
        if (($s['name'] ?? '') === $sched_name) { $sched_id = $s['.id'] ?? null; break; }
      }
    }

    if ($sched_id) {
      mt_call($api, '/system/scheduler/set', [
        '.id' => $sched_id,
        'name' => $sched_name,
        'interval' => $interval,
        'on-event' => $script_name,
        'disabled' => 'no'
      ]);
      $log[] = "✅ تم تحديث Scheduler: {$sched_name} (كل {$interval})";
    } else {
      mt_call($api, '/system/scheduler/add', [
        'name' => $sched_name,
        'interval' => $interval,
        'on-event' => $script_name,
        'disabled' => 'no'
      ]);
      $log[] = "✅ تم إنشاء Scheduler: {$sched_name} (كل {$interval})";
    }

    // 3) Show router identity
    $ident = mt_call($api, '/system/identity/print', []);
    if (is_array($ident) && isset($ident[0]['name'])) {
      $log[] = "ℹ️ الراوتر: " . $ident[0]['name'];
    }

    if (function_exists('mt_api_disconnect')) mt_api_disconnect($api);
  }
}

$UA_FORCE_DESIGN_V2 = true;
$uaAndroidQuotaSetup = ((string)($_GET['ua_android'] ?? '') === '1') || stripos((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 'NetworkCustomersAndroid/') !== false;
if ($uaAndroidQuotaSetup) $UA_PAGE_CSS = ['assets/css/android_quota_setup.css'];
include __DIR__ . '/header.php';
include __DIR__ . '/sidebar.php';
if ($uaAndroidQuotaSetup) { require __DIR__ . '/android_quota_setup.php'; include __DIR__ . '/footer.php'; return; }
?>
<div class="content-wrapper ua-extracted-page">
  <section class="content-header">
    <div class="container-fluid d-flex justify-content-between align-items-center">
      <h1 class="mb-0">تهيئة نظام الحجم والقص (MikroTik)</h1>
      <a href="subscribers.php" class="btn btn-secondary">⬅ رجوع</a>
    </div>
  </section>

  <section class="content">
    <div class="container-fluid">

      <?php if ($err): ?>
        <div class="alert alert-danger"><?= h($err) ?></div>
      <?php endif; ?>

      <?php if ($log): ?>
        <div class="alert alert-success">
          <?php foreach ($log as $l): ?>
            <?= h($l) ?><br>
          <?php endforeach; ?>
        </div>
      <?php endif; ?>

      <div class="card">
        <div class="card-body">
          <p class="mb-2">
            هذا الزر يثبت (أو يحدّث) سكربت <b>quota_enforcer</b> و Scheduler على MikroTik.
            بعد التثبيت يصبح القص تلقائيًا حتى لو كان البرنامج مغلق.
          </p>

          <ul>
            <li><b>Interval:</b> <?= h($interval) ?></li>
            <li><b>Limit Rate عند انتهاء الحجم:</b> <?= h($limitRate) ?></li>
            <li><b>الأولوية:</b> Q= (استثناء المشترك) ثم PKG= (الباقة)</li>
          </ul>

          <form method="post" onsubmit="return confirm('تأكيد تثبيت/تحديث نظام الحجم والقص على MikroTik؟');">
            <button class="btn btn-primary" name="do_setup" value="1">⚙️ تثبيت / تحديث نظام الحجم والقص</button>
          </form>

          <hr>
          <p class="mb-1"><b>للتحقق من WinBox:</b></p>
          <pre class="ua-u-pre-wrap">/system script print where name="quota_enforcer"
/system scheduler print where name="quota-enforcer"</pre>
        </div>
      </div>

    </div>
  </section>
</div>
<?php include __DIR__ . '/footer.php'; ?>
