<?php
require_once __DIR__ . '/../auth.php';
require_once __DIR__ . '/../helpers.php';
require_once __DIR__ . '/../mikrotik_lib.php';
require_once __DIR__ . '/../subscriber_history_lib.php';
require_once __DIR__ . '/../subscribers_lib.php';
require_once __DIR__ . '/../db_bootstrap.php';
require_once __DIR__ . '/../receiver_match_refresh_lib.php';
require_once __DIR__ . '/../subscriber_id_sequence_lib.php';
ensure_db(true);
$conn = $GLOBALS['conn'] ?? null;
if (function_exists('subs_ensure_pppoe_cols')) subs_ensure_pppoe_cols($conn);
if (function_exists('sh_ensure_schema')) sh_ensure_schema($conn);

require_login();
if(function_exists('require_perm')) require_perm('can_mikrotik_sync');

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

function j($a){
  echo json_encode($a, JSON_UNESCAPED_UNICODE);
  exit;
}

try {
  if(($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST'){
    j(['ok'=>false,'error'=>'Method not allowed']);
  }

  $hotspot = !empty($_GET['hotspot']);
  $ppp     = !empty($_GET['ppp']);
  $overwrite = !empty($_GET['overwrite']);

  if(!$hotspot && !$ppp){
    j(['ok'=>true,'inserted'=>0,'updated'=>0,'skipped'=>0]);
  }

  if(!table_exists($conn,'subscribers')){
    j(['ok'=>false,'error'=>'جدول subscribers غير موجود']);
  }

  // Prepare existing map -> id
  $existing = [];
  $r = $conn->query("SELECT id, username, password_plain, full_name, package_name, speed_name,
            ppp_username, ppp_password, ppp_profile, ppp_rate_limit,
            mt_source_type, mt_profile, mt_rate_limit, mt_limit_bytes_in, mt_limit_bytes_out, mt_limit_bytes_total, mt_disabled, mt_comment
            FROM subscribers WHERE username IS NOT NULL AND username<>''");
  if($r){
    while($row = $r->fetch_assoc()){
      $existing[trim((string)$row['username'])] = $row;
    }
  }

  // Collect items
  $items = [];
  if($hotspot){
    foreach(mt_hotspot_users($conn) as $u){
      $items[] = [
        'type' => 'hotspot',
        'username' => trim((string)$u['username']),
        'password' => (string)$u['password'],
        'package_name' => trim((string)$u['profile']),
        'speed_name' => '',
        'profile' => trim((string)$u['profile']),
        'rate_limit' => '',
        'limit_bytes_in' => (int)($u['limit_bytes_in'] ?? 0),
        'limit_bytes_out' => (int)($u['limit_bytes_out'] ?? 0),
        'limit_bytes_total' => (int)($u['limit_bytes_total'] ?? 0),
        'disabled' => !empty($u['disabled']),
        'comment' => (string)($u['comment'] ?? ''),
      ];
    }
  }
  if($ppp){
    foreach(mt_ppp_secrets($conn) as $u){
      $items[] = [
        'type' => 'pppoe',
        'username' => trim((string)$u['username']),
        'password' => (string)$u['password'],
        'package_name' => trim((string)$u['profile']),
        'speed_name' => trim((string)$u['rate_limit']),
        'profile' => trim((string)$u['profile']),
        'rate_limit' => trim((string)$u['rate_limit']),
        'limit_bytes_in' => (int)($u['limit_bytes_in'] ?? 0),
        'limit_bytes_out' => (int)($u['limit_bytes_out'] ?? 0),
        'limit_bytes_total' => 0,
        'disabled' => !empty($u['disabled']),
        'comment' => (string)($u['comment'] ?? ''),
      ];
    }
  }

  $inserted=0; $updated=0; $skipped=0;
  ua_subscriber_ensure_id_sequence($conn);

  // Robust direct queries (escaping). This keeps the feature portable for EXE packaging.
  foreach($items as $it){
    $username = trim((string)$it['username']);
    if($username===''){ $skipped++; continue; }
    $pwd = (string)$it['password'];
    $pkg = trim((string)$it['package_name']);
    $spd = trim((string)$it['speed_name']);

    if(!isset($existing[$username])){
      $u = $conn->real_escape_string($username);
      $p = $conn->real_escape_string($pwd);
      $full = $conn->real_escape_string($username);
      $pkgE = $conn->real_escape_string($pkg);
      $spdE = $conn->real_escape_string($spd);
      $type = (string)($it['type'] ?? '');
      $prof = trim((string)($it['profile'] ?? ''));
      $rate = trim((string)($it['rate_limit'] ?? ''));
      $lbi  = (int)($it['limit_bytes_in'] ?? 0);
      $lbo  = (int)($it['limit_bytes_out'] ?? 0);
      $lbt  = (int)($it['limit_bytes_total'] ?? 0);
      $dis  = !empty($it['disabled']) ? 1 : 0;
      $cmt  = (string)($it['comment'] ?? '');

      $typeE = $conn->real_escape_string($type);
      $profE = $conn->real_escape_string($prof);
      $rateE = $conn->real_escape_string($rate);
      $cmtE  = $conn->real_escape_string($cmt);

      $pppU = ($type === 'pppoe') ? $u : '';
      $pppP = ($type === 'pppoe') ? $p : '';
      $pppProf = ($type === 'pppoe') ? $profE : '';
      $pppRate = ($type === 'pppoe') ? $rateE : '';

      $sql = "INSERT INTO subscribers
        (username,password_plain,full_name,status,package_name,speed_name,speed_state,base_speed,current_speed,
         ppp_username,ppp_password,ppp_profile,ppp_rate_limit,ppp_last_sync,registered_at,
         mt_source_type,mt_profile,mt_rate_limit,mt_limit_bytes_in,mt_limit_bytes_out,mt_limit_bytes_total,mt_disabled,mt_comment,mt_last_sync)
        VALUES
        ('$u','$p','$full','نشط','$pkgE','$spdE','ORIGINAL','$spdE','$spdE',
         '$pppU','$pppP','$pppProf','$pppRate',NOW(),NOW(),
         '$typeE','$profE','$rateE',$lbi,$lbo,$lbt,$dis,'$cmtE',NOW())";
      if($conn->query($sql)) { $inserted++; sh_ensure_registered($conn, (int)$conn->insert_id, date('Y-m-d H:i:s')); } else $skipped++;
      continue;
    }

    // Existing subscriber
    $row = $existing[$username];
    $id = (int)$row['id'];

    // Base fields (keep user's existing data unless overwrite or empty)
    if(!$overwrite){
      $newPwd  = ($row['password_plain'] ?? '') !== '' ? ($row['password_plain'] ?? '') : $pwd;
      $newPkg  = ($row['package_name'] ?? '') !== '' ? ($row['package_name'] ?? '') : $pkg;
      $newSpd  = ($row['speed_name'] ?? '') !== '' ? ($row['speed_name'] ?? '') : $spd;
    } else {
      $newPwd  = $pwd;
      $newPkg  = $pkg;
      $newSpd  = $spd;
    }

    // MikroTik snapshot: always refresh (doesn't affect billing logic)
    $type = (string)($it['type'] ?? '');
    $prof = trim((string)($it['profile'] ?? ''));
    $rate = trim((string)($it['rate_limit'] ?? ''));
    $lbi  = (int)($it['limit_bytes_in'] ?? 0);
    $lbo  = (int)($it['limit_bytes_out'] ?? 0);
    $lbt  = (int)($it['limit_bytes_total'] ?? 0);
    $dis  = !empty($it['disabled']) ? 1 : 0;
    $cmt  = (string)($it['comment'] ?? '');

    // PPP fields: refresh for PPPoE (keep old unless overwrite or empty)
    if ($type === 'pppoe') {
      if ($overwrite || trim((string)($row['ppp_username'] ?? '')) === '') $row['ppp_username'] = $username;
      if ($overwrite || trim((string)($row['ppp_password'] ?? '')) === '') $row['ppp_password'] = $pwd;
      if ($overwrite || trim((string)($row['ppp_profile'] ?? '')) === '') $row['ppp_profile'] = $prof;
      if ($overwrite || trim((string)($row['ppp_rate_limit'] ?? '')) === '') $row['ppp_rate_limit'] = $rate;
    }

    // Skip only if absolutely nothing will change (base + MT snapshot + PPP snapshot)
    $noChange =
      (string)($row['password_plain'] ?? '') === (string)$newPwd &&
      (string)($row['package_name'] ?? '') === (string)$newPkg &&
      (string)($row['speed_name'] ?? '') === (string)$newSpd &&
      (string)($row['mt_source_type'] ?? '') === (string)$type &&
      (string)($row['mt_profile'] ?? '') === (string)$prof &&
      (string)($row['mt_rate_limit'] ?? '') === (string)$rate &&
      (int)($row['mt_limit_bytes_in'] ?? 0) === (int)$lbi &&
      (int)($row['mt_limit_bytes_out'] ?? 0) === (int)$lbo &&
      (int)($row['mt_limit_bytes_total'] ?? 0) === (int)$lbt &&
      (int)($row['mt_disabled'] ?? 0) === (int)$dis &&
      (string)($row['mt_comment'] ?? '') === (string)$cmt;

    if ($noChange && !$overwrite) { $skipped++; continue; }

    $pE    = $conn->real_escape_string($newPwd);
    $pkgE  = $conn->real_escape_string($newPkg);
    $spdE  = $conn->real_escape_string($newSpd);

    $typeE = $conn->real_escape_string($type);
    $profE = $conn->real_escape_string($prof);
    $rateE = $conn->real_escape_string($rate);
    $cmtE  = $conn->real_escape_string($cmt);

    $pppU = $conn->real_escape_string((string)($row['ppp_username'] ?? ''));
    $pppP = $conn->real_escape_string((string)($row['ppp_password'] ?? ''));
    $pppProfE = $conn->real_escape_string((string)($row['ppp_profile'] ?? ''));
    $pppRateE = $conn->real_escape_string((string)($row['ppp_rate_limit'] ?? ''));

    $sql = "UPDATE subscribers SET
        password_plain='$pE',
        package_name='$pkgE',
        speed_name='$spdE',
        ppp_username='$pppU',
        ppp_password='$pppP',
        ppp_profile='$pppProfE',
        ppp_rate_limit='$pppRateE',
        ppp_last_sync=NOW(),
        mt_source_type='$typeE',
        mt_profile='$profE',
        mt_rate_limit='$rateE',
        mt_limit_bytes_in=$lbi,
        mt_limit_bytes_out=$lbo,
        mt_limit_bytes_total=$lbt,
        mt_disabled=$dis,
        mt_comment='$cmtE',
        mt_last_sync=NOW()
      WHERE id=$id";
    if($conn->query($sql)) $updated++; else $skipped++;
  }

  try { if (function_exists('ua_receiver_match_rebuild_from_cache')) ua_receiver_match_rebuild_from_cache($conn, 'mikrotik_import_run'); } catch (Throwable $rxE) {}
  j(['ok'=>true,'inserted'=>$inserted,'updated'=>$updated,'skipped'=>$skipped]);

} catch (Throwable $e) {
  j(['ok'=>false,'error'=>$e->getMessage()]);
}
