<?php
// admin/mikrotik_connection_lib.php
// Stage 10: single safe MikroTik connection/call layer.
// This file does not change command logic. It only centralizes connection, calls, and disconnect helpers.

require_once __DIR__ . '/routeros_api.php';

if (!function_exists('ua_mt_normalize_port')) {
  function ua_mt_normalize_port($port): int {
    $p = (int)$port;
    return ($p >= 1 && $p <= 65535) ? $p : 8728;
  }
}

if (!function_exists('ua_mt_router_label')) {
  function ua_mt_router_label(array $router): string {
    $host = trim((string)($router['host'] ?? ''));
    $port = ua_mt_normalize_port($router['api_port'] ?? ($router['port'] ?? 8728));
    return $host !== '' ? ($host . ':' . $port) : 'MikroTik';
  }
}

if (!function_exists('ua_mt_config_from_settings')) {
  function ua_mt_config_from_settings($cfg): ?array {
    if (!is_array($cfg) || empty($cfg)) return null;
    return [
      'id'       => (int)($cfg['id'] ?? 0),
      'name'     => trim((string)($cfg['name'] ?? ($cfg['host'] ?? 'MikroTik'))),
      'host'     => trim((string)($cfg['host'] ?? '')),
      'username' => trim((string)($cfg['username'] ?? '')),
      'password' => (string)($cfg['password'] ?? ''),
      'api_port' => ua_mt_normalize_port($cfg['api_port'] ?? ($cfg['port'] ?? 8728)),
      'role'     => (string)($cfg['role'] ?? 'default'),
      'is_enabled' => (int)($cfg['is_enabled'] ?? 1),
    ];
  }
}

if (!function_exists('ua_mt_set_last_error')) {
  function ua_mt_set_last_error(string $message): void {
    $GLOBALS['mt_last_error'] = $message;
  }
}

if (!function_exists('ua_mt_connect_config')) {
  /**
   * Connect to a RouterOS router from a normalized config array.
   * Returns RouterOSAPI on success, false on failure. The error is written to $error and $GLOBALS['mt_last_error'].
   */
  function ua_mt_connect_config(array $router, ?string &$error = null, float $probeTimeout = 0.8) {
    static $failCache = [];

    $error = '';
    $router = ua_mt_config_from_settings($router) ?: [];
    $host = trim((string)($router['host'] ?? ''));
    $user = trim((string)($router['username'] ?? ''));
    $pass = (string)($router['password'] ?? '');
    $port = ua_mt_normalize_port($router['api_port'] ?? 8728);

    if ($host === '' || $user === '') {
      $error = 'بيانات MikroTik غير مكتملة (host/username).';
      ua_mt_set_last_error($error);
      return false;
    }

    $cacheKey = md5($host . '|' . $port . '|' . $user);
    $now = microtime(true);
    if (isset($failCache[$cacheKey]) && ($failCache[$cacheKey]['until'] ?? 0) > $now) {
      $error = (string)($failCache[$cacheKey]['error'] ?? 'تعذر الاتصال بالراوتر');
      ua_mt_set_last_error($error);
      return false;
    }

    $errno = 0;
    $errstr = '';
    $target = 'tcp://' . $host . ':' . $port;
    $sock = @stream_socket_client($target, $errno, $errstr, max(0.2, $probeTimeout), STREAM_CLIENT_CONNECT);
    if (!$sock) {
      $hint = '';
      $e = trim((string)$errstr);
      if (stripos($e, 'refused') !== false || (int)$errno === 111) {
        $hint = " (منفذ API مغلق: غالباً خدمة API معطّلة على الراوتر. نفّذ: /ip service enable api ; /ip service set api disabled=no port={$port})";
      } elseif (stripos($e, 'timed out') !== false || (int)$errno === 110) {
        $hint = " (Timeout: قد يكون فايروال يمنع الوصول إلى المنفذ {$port} أو العنوان غير صحيح)";
      } elseif ((int)$errno === 10013 || stripos($e, 'forbidden by its access permissions') !== false) {
        $hint = " (Windows منع فتح الاتصال: افحص سماح Apache/PHP في الجدار الناري واتصال بطاقة الشبكة المحلية بالراوتر)";
      }
      $error = "تعذر الاتصال بـ MikroTik على {$host}:{$port} — " . ($e ?: 'socket error') . $hint;
      ua_mt_set_last_error($error);
      $failCache[$cacheKey] = ['error' => $error, 'until' => $now + 3.0];
      return false;
    }
    @fclose($sock);

    try {
      $api = new RouterOSAPI($host, $user, $pass, $port);
      if (!($api instanceof RouterOSAPI) || empty($api->connected)) {
        $error = ($api instanceof RouterOSAPI && !empty($api->last_error)) ? $api->last_error : 'فشل الاتصال بالراوتر';
        ua_mt_set_last_error($error);
        $failCache[$cacheKey] = ['error' => $error, 'until' => $now + 3.0];
        return false;
      }
      return $api;
    } catch (Throwable $e) {
      $error = $e->getMessage();
      ua_mt_set_last_error($error);
      $failCache[$cacheKey] = ['error' => $error, 'until' => $now + 3.0];
      return false;
    }
  }
}

if (!function_exists('ua_mt_safe_disconnect')) {
  function ua_mt_safe_disconnect($api): void {
    if (is_object($api) && method_exists($api, 'disconnect')) {
      try { $api->disconnect(); } catch (Throwable $e) {}
    }
  }
}

if (!function_exists('ua_mt_call')) {
  /**
   * Unified RouterOS call helper.
   * Supports both PEAR-style comm($path,$params) and this project's command([$words]) API.
   */
  function ua_mt_call($api, string $path, array $params = []) {
    if (!is_object($api)) return null;

    if (method_exists($api, 'comm')) {
      return $api->comm($path, $params);
    }

    if (method_exists($api, 'command')) {
      $cmd = [$path];
      foreach ($params as $k => $v) {
        $key = (string)$k;
        if ($key === '') continue;
        if ($key[0] === '?') {
          $cmd[] = $key . '=' . $v;
        } elseif ($key[0] === '=') {
          $cmd[] = $key . '=' . $v;
        } else {
          $cmd[] = '=' . $key . '=' . $v;
        }
      }
      return $api->command($cmd);
    }

    return null;
  }
}

// Backward-compatible names used by older pages.
if (!function_exists('mt_call')) {
  function mt_call($api, $path, $params = []) {
    return ua_mt_call($api, (string)$path, is_array($params) ? $params : []);
  }
}

if (!function_exists('mt_api_disconnect')) {
  function mt_api_disconnect($api): void {
    ua_mt_safe_disconnect($api);
  }
}

if (!function_exists('mt_connect')) {
  function mt_connect($conn = null) {
    if (function_exists('mt_api_connect')) {
      return mt_api_connect($conn);
    }
    return false;
  }
}
