<?php
// admin/subscribers_import_excel.php
if (session_status() === PHP_SESSION_NONE) session_start();
if (!ob_get_level()) ob_start();

$page_title = 'استيراد بيانات المشتركين من Excel';
// هذه الصفحة تعمل كنافذة داخلية دائماً داخل صفحة المشتركين.
// إبقاء وضع embed/popup مفعلاً يمنع ظهور السايدبار والشريط العلوي داخل نافذة الاستيراد،
// خصوصاً بعد Redirect الذي يحصل بعد تنفيذ الاستيراد.
$GLOBALS['UA_POPUP'] = true;
if (!defined('UA_POPUP')) define('UA_POPUP', true);
if (!defined('UA_EMBED')) define('UA_EMBED', true);

require_once __DIR__ . '/auth.php';
require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/db_bootstrap.php';
require_once __DIR__ . '/subscriber_plan_schema.php';
require_once __DIR__ . '/super_admin_guard.php';
require_once __DIR__ . '/receiver_match_refresh_lib.php';
require_once __DIR__ . '/subscriber_id_sequence_lib.php';

require_login();
if (function_exists('require_perm')) require_perm('can_edit_subscriber');
if (function_exists('ensure_db')) ensure_db(true);
$conn = $GLOBALS['conn'] ?? null;
if (!($conn instanceof mysqli)) { http_response_code(500); die('Database connection error'); }
ua_subscriber_id_registry_ensure($conn);

function sie_h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
function sie_col_exists(mysqli $conn, string $table, string $col): bool {
  static $cache = [];
  $key = $table.'|'.$col;
  if (array_key_exists($key, $cache)) return $cache[$key];
  $t = $conn->real_escape_string($table); $c = $conn->real_escape_string($col);
  $rs = @$conn->query("SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='$t' AND COLUMN_NAME='$c' LIMIT 1");
  return $cache[$key] = ($rs && $rs->num_rows > 0);
}
function sie_norm_username($v): string {
  $v = trim((string)$v);
  $v = preg_replace('/^[\xEF\xBB\xBF]+/', '', $v);
  $v = preg_replace('/\s+/u', '', $v);
  $v = preg_replace('/@.*/', '', $v);
  return mb_strtolower(trim($v), 'UTF-8');
}
function sie_clean_cell($v): string {
  $v = (string)$v;
  $v = preg_replace('/^[\xEF\xBB\xBF]+/', '', $v);
  $v = str_replace(["\r\n","\r"], "\n", $v);
  $v = preg_replace('/[\t ]+/u', ' ', $v);
  return trim($v);
}
function sie_csv_rows(string $path): array {
  $rows = [];
  $fh = fopen($path, 'rb');
  if (!$fh) return $rows;
  $first = fgets($fh);
  if ($first === false) { fclose($fh); return []; }
  $first = preg_replace('/^\xEF\xBB\xBF/', '', $first);
  $delimiter = (substr_count($first, ';') > substr_count($first, ',')) ? ';' : ',';
  rewind($fh);
  while (($r = fgetcsv($fh, 0, $delimiter)) !== false) {
    $rows[] = array_map('sie_clean_cell', $r);
  }
  fclose($fh);
  return $rows;
}
function sie_xlsx_col_index(string $ref): int {
  preg_match('/^([A-Z]+)/i', $ref, $m);
  $letters = strtoupper($m[1] ?? 'A');
  $n = 0;
  for ($i=0; $i<strlen($letters); $i++) $n = $n * 26 + (ord($letters[$i]) - 64);
  return max(0, $n - 1);
}
function sie_xlsx_first_sheet_rows(string $path): array {
  if (!class_exists('ZipArchive')) throw new RuntimeException('إضافة ZipArchive غير مفعلة في PHP، لذلك لا يمكن قراءة xlsx. جرّب CSV أو فعّل zip extension.');
  $zip = new ZipArchive();
  if ($zip->open($path) !== true) throw new RuntimeException('تعذر فتح ملف Excel.');
  $shared = [];
  $ss = $zip->getFromName('xl/sharedStrings.xml');
  if ($ss !== false) {
    $xml = @simplexml_load_string($ss);
    if ($xml) {
      foreach ($xml->si as $si) {
        $txt = '';
        if (isset($si->t)) $txt .= (string)$si->t;
        if (isset($si->r)) foreach ($si->r as $run) $txt .= (string)$run->t;
        $shared[] = sie_clean_cell($txt);
      }
    }
  }
  $sheetPath = 'xl/worksheets/sheet1.xml';
  $wb = $zip->getFromName('xl/workbook.xml');
  $rels = $zip->getFromName('xl/_rels/workbook.xml.rels');
  if ($wb !== false && $rels !== false) {
    $wbx = @simplexml_load_string($wb); $rx = @simplexml_load_string($rels);
    if ($wbx && $rx && isset($wbx->sheets->sheet[0])) {
      $attrs = $wbx->sheets->sheet[0]->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
      $rid = (string)($attrs['id'] ?? '');
      if ($rid !== '') {
        foreach ($rx->Relationship as $rel) {
          $a = $rel->attributes();
          if ((string)$a['Id'] === $rid) { $sheetPath = 'xl/' . ltrim((string)$a['Target'], '/'); break; }
        }
      }
    }
  }
  $sheet = $zip->getFromName($sheetPath);
  if ($sheet === false) { $zip->close(); throw new RuntimeException('لم يتم العثور على أول ورقة داخل ملف Excel.'); }
  $xml = @simplexml_load_string($sheet);
  if (!$xml) { $zip->close(); throw new RuntimeException('تعذر قراءة محتوى ملف Excel.'); }
  $rows = [];
  foreach ($xml->sheetData->row as $row) {
    $out = [];
    foreach ($row->c as $c) {
      $a = $c->attributes();
      $idx = sie_xlsx_col_index((string)($a['r'] ?? 'A1'));
      $type = (string)($a['t'] ?? '');
      $val = '';
      if ($type === 's') {
        $si = (int)$c->v;
        $val = $shared[$si] ?? '';
      } elseif ($type === 'inlineStr') {
        $val = (string)($c->is->t ?? '');
      } else {
        $val = (string)($c->v ?? '');
      }
      $out[$idx] = sie_clean_cell($val);
    }
    if (!empty($out)) {
      $max = max(array_keys($out));
      $line = [];
      for ($i=0; $i<=$max; $i++) $line[] = $out[$i] ?? '';
      $rows[] = $line;
    }
  }
  $zip->close();
  return $rows;
}
function sie_read_rows(string $path, string $name): array {
  $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  if ($ext === 'csv') return sie_csv_rows($path);
  if ($ext === 'xlsx') return sie_xlsx_first_sheet_rows($path);
  throw new RuntimeException('نوع الملف غير مدعوم. استخدم xlsx أو csv.');
}
function sie_ensure_tables(mysqli $conn): void {
  @$conn->query("CREATE TABLE IF NOT EXISTS subscriber_import_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(190) NULL,
    source_file VARCHAR(255) NULL,
    matched_count INT NOT NULL DEFAULT 0,
    updated_count INT NOT NULL DEFAULT 0,
    skipped_count INT NOT NULL DEFAULT 0,
    extra_count INT NOT NULL DEFAULT 0,
    duplicate_count INT NOT NULL DEFAULT 0,
    status VARCHAR(30) NOT NULL DEFAULT 'applied'
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
  @$conn->query("CREATE TABLE IF NOT EXISTS subscriber_import_changes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    batch_id INT NOT NULL,
    subscriber_id INT NOT NULL,
    ppp_username VARCHAR(190) NOT NULL,
    field_name VARCHAR(80) NOT NULL,
    old_value TEXT NULL,
    new_value TEXT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    KEY batch_id (batch_id),
    KEY subscriber_id (subscriber_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
}

function sie_field_catalog(mysqli $conn): array {
  $base = [
    'full_name'=>'الاسم الكامل','first_name'=>'الاسم','father_name'=>'اسم الأب','last_name'=>'الكنية','mother_name'=>'اسم الأم',
    'phone'=>'رقم الهاتف','birth_date'=>'تاريخ الميلاد','document_type'=>'نوع الوثيقة','document_number'=>'رقم الوثيقة',
    'national_id'=>'الرقم الوطني','record_number'=>'القيد',
    'address_area'=>'العنوان الحالي','notes'=>'ملاحظات','sector_id'=>'القطاع','vlan_id'=>'VLAN',
    'speed'=>'السرعة','package'=>'الباقة','speed_name'=>'اسم السرعة','package_name'=>'اسم الباقة',
    'base_speed'=>'السرعة الأساسية','current_speed'=>'السرعة الحالية','quota_gb'=>'الحجم GB',
    'ppp_username'=>'حساب PPPoE','ppp_password'=>'كلمة مرور PPPoE','ppp_profile'=>'بروفايل PPP','ppp_rate_limit'=>'Rate Limit',
    'pppoe_profile'=>'PPPoE Profile','status'=>'الحالة'
  ];
  $out = [];
  foreach ($base as $col=>$label) if (sie_col_exists($conn,'subscribers',$col)) $out[$col] = $label;
  return $out;
}
function sie_field_label(mysqli $conn, string $field): string {
  if ($field === '__id') return '#';
  $cat = sie_field_catalog($conn);
  return $cat[$field] ?? $field;
}

function sie_auto_norm_header(string $v): string {
  $v = sie_clean_cell($v);
  $v = str_replace(['ـ','–','—','-', '_', '.', ':', '/', '\\'], ' ', $v);
  $v = strtr($v, ['أ'=>'ا','إ'=>'ا','آ'=>'ا','ى'=>'ي','ة'=>'ه']);
  $v = preg_replace('/[\x{064B}-\x{065F}]/u', '', $v);
  $v = mb_strtolower($v, 'UTF-8');
  $v = preg_replace('/[^\p{L}\p{N}]+/u', ' ', $v);
  $v = trim(preg_replace('/\s+/u', ' ', $v));
  return $v;
}
function sie_auto_aliases_for_field(string $field, string $label): array {
  $aliases = [$field, $label];
  $map = [
    'ppp_username'=>['ppp username','pppoe username','pppoe user','ppp user','username','user','حساب pppoe','اسم المستخدم pppoe','اسم حساب pppoe','حساب المشترك','يوزر','اليوزر'],
    'full_name'=>['full name','fullname','name','subscriber name','customer name','الاسم الكامل','اسم المشترك','الاسم الثلاثي','الاسم'],
    'first_name'=>['first name','firstname','fname','الاسم','الاسم الاول','اسم'],
    'father_name'=>['father name','father','fathername','اسم الاب','الاب'],
    'last_name'=>['last name','lastname','lname','family name','الكنيه','الكنية','العائله','العائلة'],
    'mother_name'=>['mother name','mother','اسم الام','الام'],
    'phone'=>['phone','mobile','mobile phone','tel','telephone','gsm','رقم الهاتف','هاتف','جوال','موبايل','الموبايل'],
    'birth_date'=>['birth date','birthdate','dob','date of birth','تاريخ الميلاد','مواليد'],
    'document_type'=>['document type','identity document type','id document type','نوع الوثيقة','نوع وثيقة','نوع وثيقة الثبوتيات','نوع الثبوتيات'],
    'document_number'=>['document number','document no','document id','identity document number','رقم الوثيقة','رقم وثيقة الثبوتيات','رقم الثبوتيات','رقم الهوية','رقم جواز السفر'],
    'national_id'=>['national id','nationalid','national number','الرقم الوطني','الرقم القومي'],
    'record_number'=>['record number','record','reg no','القيد','رقم القيد'],
    'address_area'=>['address','area','location','العنوان','العنوان الحالي','المنطقة','السكن'],
    'notes'=>['notes','note','ملاحظات','ملاحظة'],
    'sector_id'=>['sector id','sector','القطاع','رقم القطاع'],
    'vlan_id'=>['vlan id','vlan','vlan_id'],
    'speed'=>['speed','السرعة'],
    'package'=>['package','plan','الباقة','الاشتراك'],
    'speed_name'=>['speed name','اسم السرعة','سرعة'],
    'package_name'=>['package name','plan name','اسم الباقة','باقة'],
    'base_speed'=>['base speed','السرعة الأساسية','السرعة الاساسيه'],
    'current_speed'=>['current speed','السرعة الحالية','السرعة الحاليه'],
    'quota_gb'=>['quota gb','quota','gb','الحجم gb','الحجم','الكوتا'],
    'ppp_password'=>['ppp password','pppoe password','password','pass','كلمة مرور pppoe','باسورد pppoe','كلمة المرور','الباسورد'],
    'ppp_profile'=>['ppp profile','profile','بروفايل ppp','البروفايل'],
    'ppp_rate_limit'=>['rate limit','ratelimit','rate','محدد السرعة','rate limit'],
    'pppoe_profile'=>['pppoe profile','pppoe_profile','بروفايل pppoe'],
    'status'=>['status','state','الحالة'],
  ];
  if (isset($map[$field])) $aliases = array_merge($aliases, $map[$field]);
  return array_values(array_unique(array_filter(array_map('strval', $aliases))));
}
function sie_auto_header_lookup(array $headers): array {
  $lookup = [];
  foreach ($headers as $i=>$h) {
    $n = sie_auto_norm_header((string)$h);
    if ($n !== '' && !array_key_exists($n, $lookup)) $lookup[$n] = (int)$i;
  }
  return $lookup;
}
function sie_auto_find_col(array $lookup, array $aliases): string {
  foreach ($aliases as $a) {
    $n = sie_auto_norm_header((string)$a);
    if ($n !== '' && array_key_exists($n, $lookup)) return (string)$lookup[$n];
  }
  return '';
}
function sie_auto_detect_map(mysqli $conn, array $headers): array {
  $lookup = sie_auto_header_lookup($headers);
  $cat = sie_field_catalog($conn);
  $map = ['full_mode'=>'none', 'full_name_col'=>'', 'username_col'=>''];
  $map['username_col'] = sie_auto_find_col($lookup, sie_auto_aliases_for_field('ppp_username', $cat['ppp_username'] ?? 'حساب PPPoE'));

  $full = sie_auto_find_col($lookup, sie_auto_aliases_for_field('full_name', $cat['full_name'] ?? 'الاسم الكامل'));
  if ($full !== '') {
    $map['full_mode'] = 'single';
    $map['full_name_col'] = $full;
  } else {
    $f = sie_auto_find_col($lookup, sie_auto_aliases_for_field('first_name', $cat['first_name'] ?? 'الاسم'));
    $fa = sie_auto_find_col($lookup, sie_auto_aliases_for_field('father_name', $cat['father_name'] ?? 'اسم الأب'));
    $l = sie_auto_find_col($lookup, sie_auto_aliases_for_field('last_name', $cat['last_name'] ?? 'الكنية'));
    if ($f !== '' && $fa !== '' && $l !== '') $map['full_mode'] = 'merge';
  }

  foreach ($cat as $field=>$label) {
    if ($field === 'full_name') continue;
    $map['field_col_'.$field] = sie_auto_find_col($lookup, sie_auto_aliases_for_field($field, $label));
  }
  $map['display_id_col'] = sie_auto_find_col($lookup, ['#','id','subscriber_id','subscriber id','رقم','الرقم المعروض']);
  return $map;
}
function sie_form_selected_col(array $autoMap, string $key, int $i): string {
  $current = array_key_exists($key, $_POST) ? (string)$_POST[$key] : (string)($autoMap[$key] ?? '');
  return ($current !== '' && $current === (string)$i) ? ' selected' : '';
}
function sie_form_selected_value(array $autoMap, string $key, string $value, string $default=''): string {
  $current = array_key_exists($key, $_POST) ? (string)$_POST[$key] : (string)($autoMap[$key] ?? $default);
  return $current === $value ? ' selected' : '';
}
function sie_update_subscriber_id(mysqli $conn, int $oldId, int $newId): void {
  if ($oldId <= 0 || $newId <= 0 || $oldId === $newId) return;
  $policy = ua_subscriber_id_series_policy($conn, $oldId);
  $validation = ua_subscriber_id_candidate_error($policy, $oldId, (string)$newId);
  if ($validation !== '') throw new RuntimeException($validation);
  ua_subscriber_change_id_in_transaction($conn, $oldId, $newId, 'excel_import');
}

function sie_current_user(): string {
  foreach (['username','admin_username','user_name','login'] as $k) if (!empty($_SESSION[$k])) return (string)$_SESSION[$k];
  if (!empty($_SESSION['user']) && is_array($_SESSION['user']) && !empty($_SESSION['user']['username'])) return (string)$_SESSION['user']['username'];
  return 'admin';
}
function sie_get_subscribers(mysqli $conn): array {
  $fields = ['id','username','ppp_username'];
  foreach (array_keys(sie_field_catalog($conn)) as $c) if (!in_array($c,$fields,true)) $fields[] = $c;
  foreach (['full_name','phone','address_area'] as $c) if (sie_col_exists($conn,'subscribers',$c) && !in_array($c,$fields,true)) $fields[] = $c;
  $where = sie_col_exists($conn,'subscribers','is_deleted') ? 'WHERE COALESCE(is_deleted,0)=0' : '';
  $sql = 'SELECT '.implode(',', array_map(fn($x)=>"`$x`", $fields))." FROM subscribers $where ORDER BY id ASC";
  $rs = $conn->query($sql);
  $rows = [];
  if ($rs) while ($r = $rs->fetch_assoc()) $rows[] = $r;
  return $rows;
}
function sie_build_preview(mysqli $conn, array $rows, array $map, string $sourceFile): array {
  $headerRow = max(0, (int)($map['header_row'] ?? 1) - 1);
  $headers = $rows[$headerRow] ?? [];
  $dataRows = array_slice($rows, $headerRow + 1);
  $idxUser = (int)$map['username_col'];
  $ignoreEmpty = !empty($map['ignore_empty']);
  $fields = [];
  if (($map['full_mode'] ?? '') === 'single' && ($map['full_name_col'] ?? '') !== '') $fields['full_name'] = ['type'=>'single','idx'=>(int)$map['full_name_col']];
  if (($map['full_mode'] ?? '') === 'merge') {
    // في الواجهة الموحّدة لا نعرض حقول دمج منفصلة حتى لا يتكرر اختيار الاسم/الأب/الكنية.
    // يتم تكوين الاسم الكامل من نفس خانات: الاسم + اسم الأب + الكنية الموجودة ضمن اختيار الأعمدة.
    $parts = [];
    foreach (['field_col_first_name','field_col_father_name','field_col_last_name'] as $k) if (($map[$k] ?? '') !== '') $parts[] = (int)$map[$k];
    // توافق احتياطي مع أي نسخة قديمة كانت ترسل full_part*_col.
    if (!$parts) foreach (['full_part1_col','full_part2_col','full_part3_col'] as $k) if (($map[$k] ?? '') !== '') $parts[] = (int)$map[$k];
    if ($parts) $fields['full_name'] = ['type'=>'merge','idxs'=>$parts];
  }
  foreach (sie_field_catalog($conn) as $field=>$label) {
    if (in_array($field, ['full_name'], true)) continue;
    $k = 'field_col_' . $field;
    if (($map[$k] ?? '') !== '') $fields[$field] = ['type'=>'single','idx'=>(int)$map[$k]];
  }
  if (!empty($map['update_display_id']) && ($map['display_id_col'] ?? '') !== '') {
    $fields['__id'] = ['type'=>'single','idx'=>(int)$map['display_id_col']];
  }

  $excel = []; $dups = [];
  foreach ($dataRows as $rn => $r) {
    $uRaw = $r[$idxUser] ?? '';
    $key = sie_norm_username($uRaw);
    if ($key === '') continue;
    if (isset($excel[$key])) { $dups[$key] = ($dups[$key] ?? 1) + 1; continue; }
    $excel[$key] = ['row_no'=>$headerRow + 2 + $rn, 'username_raw'=>sie_clean_cell($uRaw), 'row'=>$r];
  }

  $subs = sie_get_subscribers($conn);
  $matched = []; $programOnly = [];
  $usedExcel = [];
  foreach ($subs as $s) {
    $ppp = trim((string)($s['ppp_username'] ?? ''));
    $key = sie_norm_username($ppp);
    if ($key === '' || !isset($excel[$key]) || isset($dups[$key])) {
      $programOnly[] = ['id'=>(int)$s['id'], 'ppp_username'=>$ppp, 'full_name'=>$s['full_name'] ?? '', 'reason'=>$key===''?'اسم PPPoE فارغ في البرنامج':(isset($dups[$key])?'مكرر داخل Excel':'غير موجود في Excel')];
      continue;
    }
    $usedExcel[$key] = true;
    $row = $excel[$key]['row'];
    $changes = [];
    foreach ($fields as $field => $def) {
      if ($field !== '__id' && !sie_col_exists($conn,'subscribers',$field)) continue;
      if ($def['type'] === 'merge') {
        $vals = [];
        foreach ($def['idxs'] as $i) { $v = sie_clean_cell($row[$i] ?? ''); if ($v !== '') $vals[] = $v; }
        $new = trim(implode(' ', $vals));
      } else {
        $new = sie_clean_cell($row[$def['idx']] ?? '');
      }
      if ($field === 'document_type') {
        $normalizedType = function_exists('subscriber_document_type_normalize')
          ? subscriber_document_type_normalize($new, false)
          : $new;
        if ($new !== '' && $normalizedType === '') {
          throw new RuntimeException(
            'نوع الوثيقة «' . $new . '» غير صالح في صف Excel رقم ' . (int)$excel[$key]['row_no']
            . '. القيم المقبولة: ' . implode('، ', function_exists('subscriber_document_types') ? subscriber_document_types() : ['هوية شخصية','إخراج قيد','جواز سفر']) . '.'
          );
        }
        $new = $normalizedType;
      }
      if ($ignoreEmpty && $new === '') continue;
      if ($field === '__id') {
        $new = preg_replace('/\D+/', '', $new);
        if ($new === '') continue;
        $old = (string)((int)($s['id'] ?? 0));
      } else {
        $old = (string)($s[$field] ?? '');
      }
      if ($new !== $old) $changes[$field] = ['old'=>$old, 'new'=>$new];
    }
    $matched[] = [
      'id'=>(int)$s['id'], 'ppp_username'=>$ppp, 'excel_row'=>$excel[$key]['row_no'],
      'old_full_name'=>$s['full_name'] ?? '', 'old_phone'=>$s['phone'] ?? '', 'old_address_area'=>$s['address_area'] ?? '',
      'changes'=>$changes
    ];
  }
  $excelOnly = [];
  foreach ($excel as $key=>$e) if (empty($usedExcel[$key]) && empty($dups[$key])) $excelOnly[] = ['ppp_username'=>$e['username_raw'], 'excel_row'=>$e['row_no']];
  $dupList = [];
  foreach ($dups as $key=>$cnt) $dupList[] = ['ppp_username'=>$excel[$key]['username_raw'] ?? $key, 'count'=>$cnt];

  return [
    'token'=>bin2hex(random_bytes(12)), 'created_at'=>time(), 'source_file'=>$sourceFile,
    'headers'=>$headers, 'fields'=>array_keys($fields), 'ignore_empty'=>$ignoreEmpty,
    'import_mode'=>(($map['import_mode'] ?? '') === 'master' ? 'master' : 'normal'),
    'matched'=>$matched, 'program_only'=>$programOnly, 'excel_only'=>$excelOnly, 'duplicates'=>$dupList,
    'counts'=>[
      'matched'=>count($matched), 'will_update'=>count(array_filter($matched, fn($m)=>!empty($m['changes']))),
      'program_only'=>count($programOnly), 'excel_only'=>count($excelOnly), 'duplicates'=>count($dupList)
    ]
  ];
}

sie_ensure_tables($conn);
$msg = ''; $err = ''; $inlineMsg = '';
if (!empty($_SESSION['subscriber_import_flash'])) {
  $msg = (string)$_SESSION['subscriber_import_flash'];
  unset($_SESSION['subscriber_import_flash']);
}
$preview = $_SESSION['subscriber_excel_preview'] ?? null;

if (($_GET['action'] ?? '') === 'clear_import_silent') {
  unset($_SESSION['subscriber_excel_preview'], $_SESSION['subscriber_excel_rows'], $_SESSION['subscriber_excel_file']);
  http_response_code(204);
  exit;
}

if (($_GET['action'] ?? '') === 'clear_import') {
  unset($_SESSION['subscriber_excel_preview'], $_SESSION['subscriber_excel_rows'], $_SESSION['subscriber_excel_file']);
  header('Location: subscribers.php');
  exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'upload') {
  try {
    if (empty($_FILES['excel_file']['tmp_name']) || !is_uploaded_file($_FILES['excel_file']['tmp_name'])) throw new RuntimeException('اختر ملف Excel أولاً.');
    $name = basename((string)$_FILES['excel_file']['name']);
    $rows = sie_read_rows($_FILES['excel_file']['tmp_name'], $name);
    if (count($rows) < 2) throw new RuntimeException('الملف لا يحتوي على بيانات كافية.');
    $_SESSION['subscriber_excel_rows'] = $rows;
    $_SESSION['subscriber_excel_file'] = $name;
    unset($_SESSION['subscriber_excel_preview']);
    $preview = null;
    $inlineMsg = 'تم قراءة الملف. حدد الأعمدة ثم اضغط طبقة المطابقة.';
  } catch (Throwable $e) { $err = $e->getMessage(); }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'preview') {
  try {
    $rows = $_SESSION['subscriber_excel_rows'] ?? [];
    if (!$rows) throw new RuntimeException('ارفع ملف Excel أولاً.');
    if (($_POST['username_col'] ?? '') === '') throw new RuntimeException('يجب تحديد عمود اسم المستخدم PPPoE.');
    $map = $_POST;
    $map['ignore_empty'] = !empty($_POST['ignore_empty']);
    $map['import_mode'] = (($_POST['import_mode'] ?? '') === 'master') ? 'master' : 'normal';
    $preview = sie_build_preview($conn, $rows, $map, $_SESSION['subscriber_excel_file'] ?? 'excel');
    $_SESSION['subscriber_excel_preview'] = $preview;
    $inlineMsg = (($map['import_mode'] ?? 'normal') === 'master') ? 'تمت معاينة الاعتماد كمرجع رئيسي. راجع التنبيهات واختر التعامل مع الحسابات غير الموجودة في Excel.' : 'تمت طبقة المطابقة. راجع النتائج قبل الحفظ.';
  } catch (Throwable $e) { $err = $e->getMessage(); }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'commit') {
  try {
    $preview = $_SESSION['subscriber_excel_preview'] ?? null;
    if (!$preview || ($_POST['token'] ?? '') !== ($preview['token'] ?? '')) throw new RuntimeException('جلسة المعاينة غير صالحة. أعد المطابقة.');
    $conn->begin_transaction();
    $createdBy = $conn->real_escape_string(sie_current_user());
    $source = $conn->real_escape_string($preview['source_file'] ?? 'excel');
    $matchedCount = (int)($preview['counts']['matched'] ?? 0);
    $willUpdate = (int)($preview['counts']['will_update'] ?? 0);
    $skipped = (int)($preview['counts']['program_only'] ?? 0);
    $extra = (int)($preview['counts']['excel_only'] ?? 0);
    $dups = (int)($preview['counts']['duplicates'] ?? 0);
    $conn->query("INSERT INTO subscriber_import_logs(created_by,source_file,matched_count,updated_count,skipped_count,extra_count,duplicate_count,status) VALUES('$createdBy','$source',$matchedCount,0,$skipped,$extra,$dups,'applied')");
    $batchId = (int)$conn->insert_id;
    $updatedSubs = 0;
    foreach ($preview['matched'] as $m) {
      if (empty($m['changes'])) continue;
      $sets = [];
      $idChange = null;
      $allowed = array_keys(sie_field_catalog($conn));
      foreach ($m['changes'] as $field=>$ch) {
        if ($field === '__id') { $idChange = (int)$ch['new']; continue; }
        if (!in_array($field, $allowed, true) || !sie_col_exists($conn,'subscribers',$field)) continue;
        $newEsc = $conn->real_escape_string((string)$ch['new']);
        $sets[] = "`$field`='$newEsc'";
      }
      $sid = (int)$m['id'];
      if ($sets) $conn->query("UPDATE subscribers SET ".implode(',', $sets)." WHERE id=$sid LIMIT 1");
      foreach ($m['changes'] as $field=>$ch) {
        if ($field !== '__id' && !in_array($field, $allowed, true)) continue;
        $ppp = $conn->real_escape_string((string)$m['ppp_username']);
        $f = $conn->real_escape_string($field);
        $old = $conn->real_escape_string((string)$ch['old']);
        $new = $conn->real_escape_string((string)$ch['new']);
        $conn->query("INSERT INTO subscriber_import_changes(batch_id,subscriber_id,ppp_username,field_name,old_value,new_value) VALUES($batchId,$sid,'$ppp','$f','$old','$new')");
      }
      if ($idChange !== null && $idChange > 0 && $idChange !== $sid) sie_update_subscriber_id($conn, $sid, $idChange);
      $updatedSubs++;
    }
    $resetMissing = !empty($_POST['reset_missing']) && (($preview['import_mode'] ?? 'normal') === 'master');
    $resetSubs = 0;
    if ($resetMissing && !empty($preview['program_only'])) {
      foreach ($preview['program_only'] as $x) {
        $sid = (int)($x['id'] ?? 0);
        if ($sid <= 0) continue;
        $pppRaw = trim((string)($x['ppp_username'] ?? ''));
        if ($pppRaw === '') continue;
        $sets = [];
        // A subscriber missing from the master sheet may have operational
        // fields reset, but their personal name is never an operational PPP
        // value and must not be replaced by the login name.
        if (sie_col_exists($conn,'subscribers','phone')) { $sets[] = "`phone`=''"; }
        if (sie_col_exists($conn,'subscribers','address_area')) { $sets[] = "`address_area`=''"; }
        if (!$sets) continue;
        $oldRs = $conn->query("SELECT ".(sie_col_exists($conn,'subscribers','full_name')?'`full_name`':'NULL AS full_name').", ".(sie_col_exists($conn,'subscribers','phone')?'`phone`':'NULL AS phone').", ".(sie_col_exists($conn,'subscribers','address_area')?'`address_area`':'NULL AS address_area')." FROM subscribers WHERE id=$sid LIMIT 1");
        $oldRow = $oldRs ? ($oldRs->fetch_assoc() ?: []) : [];
        $conn->query("UPDATE subscribers SET ".implode(',', $sets)." WHERE id=$sid LIMIT 1");
        foreach (['phone'=>'','address_area'=>''] as $field=>$newVal) {
          if (!sie_col_exists($conn,'subscribers',$field)) continue;
          $oldVal = (string)($oldRow[$field] ?? '');
          if ($oldVal === (string)$newVal) continue;
          $ppp = $conn->real_escape_string($pppRaw);
          $f = $conn->real_escape_string($field);
          $old = $conn->real_escape_string($oldVal);
          $new = $conn->real_escape_string((string)$newVal);
          $conn->query("INSERT INTO subscriber_import_changes(batch_id,subscriber_id,ppp_username,field_name,old_value,new_value) VALUES($batchId,$sid,'$ppp','$f','$old','$new')");
        }
        $resetSubs++;
      }
    }
    $totalChanged = $updatedSubs + $resetSubs;
    $conn->query("UPDATE subscriber_import_logs SET updated_count=$totalChanged WHERE id=$batchId LIMIT 1");
    $conn->commit();
    ua_subscriber_ensure_id_sequence($conn);
    try { if (function_exists('ua_receiver_match_rebuild_from_cache')) ua_receiver_match_rebuild_from_cache($conn, 'excel_import'); } catch (Throwable $rxE) { @file_put_contents(__DIR__ . '/logs/receiver_match.log', '['.date('Y-m-d H:i:s').'] excel import snapshot failed: '.$rxE->getMessage().PHP_EOL, FILE_APPEND); }
    unset($_SESSION['subscriber_excel_preview'], $_SESSION['subscriber_excel_rows'], $_SESSION['subscriber_excel_file']);
    $_SESSION['subscriber_import_flash'] = 'تم تنفيذ الاستيراد بنجاح. رقم العملية: #' . $batchId . ' — تم تعديل ' . $updatedSubs . ' مشترك' . (!empty($resetSubs) ? '، وتنظيف البيانات التشغيلية لـ ' . $resetSubs . ' حساب مع حفظ أسماء المشتركين' : '') . '.';
    header('Location: subscribers_import_excel.php?embed=1&ua_modal=1&done=1');
    exit;
  } catch (Throwable $e) { try { $conn->rollback(); } catch(Throwable $x){} $err = $e->getMessage(); }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'rollback') {
  try {
    $batchId = (int)($_POST['batch_id'] ?? 0);
    if ($batchId <= 0) throw new RuntimeException('اختر عملية صحيحة للتراجع.');
    $log = $conn->query("SELECT * FROM subscriber_import_logs WHERE id=$batchId LIMIT 1")->fetch_assoc();
    if (!$log) throw new RuntimeException('عملية الاستيراد غير موجودة.');
    if (($log['status'] ?? '') === 'rolled_back') throw new RuntimeException('هذه العملية تم التراجع عنها سابقاً.');
    $rs = $conn->query("SELECT * FROM subscriber_import_changes WHERE batch_id=$batchId ORDER BY subscriber_id ASC, id ASC");
    $bySub = [];
    if ($rs) while ($r = $rs->fetch_assoc()) $bySub[(int)$r['subscriber_id']][$r['field_name']] = (string)$r['old_value'];
    $conn->begin_transaction();
    $n = 0;
    foreach ($bySub as $sid=>$fields) {
      $sets = [];
      foreach ($fields as $field=>$old) {
        if ($field === '__id') continue;
        if (!in_array($field, array_keys(sie_field_catalog($conn)), true) || !sie_col_exists($conn,'subscribers',$field)) continue;
        $sets[] = "`$field`='".$conn->real_escape_string($old)."'";
      }
      if ($sets) { $conn->query("UPDATE subscribers SET ".implode(',', $sets)." WHERE id=".(int)$sid." LIMIT 1"); $n++; }
    }
    $conn->query("UPDATE subscriber_import_logs SET status='rolled_back' WHERE id=$batchId LIMIT 1");
    $conn->commit();
    $msg = 'تم التراجع عن الاستيراد #' . $batchId . ' وإرجاع بيانات ' . $n . ' مشترك.';
  } catch (Throwable $e) { try { $conn->rollback(); } catch(Throwable $x){} $err = $e->getMessage(); }
}

$rows = $_SESSION['subscriber_excel_rows'] ?? [];
$headers = $rows[0] ?? [];
$autoMap = $headers ? sie_auto_detect_map($conn, $headers) : [];
$autoMatchedCount = count(array_filter($autoMap, fn($v)=>$v !== '' && $v !== 'none'));
$logs = [];
$rsLogs = @$conn->query("SELECT * FROM subscriber_import_logs ORDER BY id DESC LIMIT 10");
if ($rsLogs) while ($r = $rsLogs->fetch_assoc()) $logs[] = $r;

$UA_FORCE_DESIGN_V2 = true;
$UA_PAGE_CSS = ['assets/css/page_subscribers_import_excel.css'];
include __DIR__ . '/header.php';
?>
<div class="content-wrapper ua-extracted-page ua-subscriber-child-page ua-sub-child-import-excel sie-import-page">
  <section class="content sie-import-content">
    <div class="ua-page-v2 sie-import-shell">
      <header class="ua-page-head sie-page-head">
        <div class="sie-page-head-row">
          <div class="ua-page-title sie-page-title">
            <h1>استيراد بيانات المشتركين من Excel</h1>
          </div>
          <button
            type="button"
            class="sie-help-badge"
            aria-label="توضيح المطابقة"
            data-help-text="المطابقة تتم حسب ppp_username الموجود في البرنامج فقط. لا يتم إنشاء مشتركين جدد من Excel، وأي سطر زائد يبقى في التقرير فقط."
          >?</button>
        </div>
      </header>


      <section class="sie-card sie-upload-card">
        <div class="sie-card-head">
          <h2>1) رفع الملف</h2>
        </div>
        <div class="sie-card-body">
          <form method="post" enctype="multipart/form-data" class="sie-upload-form">
            <input type="hidden" name="action" value="upload">
            <div class="sie-field sie-file-field">
              <label>ملف Excel / CSV</label>
              <div class="sie-file-box" role="button" tabindex="0" aria-label="اختيار ملف">
                <input type="file" name="excel_file" id="sieExcelFile" class="sie-native-file" accept=".xlsx,.csv" required>
                <i class="fa fa-folder-open-o sie-file-icon" aria-hidden="true"></i>
                <div class="sie-file-meta">
                  <span class="sie-file-name" id="sieFileName">لم يتم اختيار أي ملف</span>
                  <small>يدعم ملفات xlsx و csv فقط</small>
                </div>
              </div>
            </div>
            <div class="sie-upload-action">
              <button class="sie-btn sie-btn-primary sie-btn-submit" type="submit"><i class="fa fa-file-import"></i><span>قراءة الملف</span></button>
            </div>
          </form>
        </div>
      </section>

      <?php if ($rows): ?>
      <section class="sie-card sie-map-card">
        <div class="sie-card-head">
          <h2>2) اختيار الأعمدة ثم طبقة المطابقة</h2>
        </div>
        <div class="sie-card-body">
          <form method="post" class="sie-map-form">
            <input type="hidden" name="action" value="preview">
            <input type="hidden" name="header_row" value="1">
            <input type="hidden" name="import_mode" id="importMode" value="normal">

            <div class="sie-auto-map-banner">
              <div>
                <b>مطابقة تلقائية:</b> تم التعرف على <?= (int)$autoMatchedCount ?> عمود حسب أسماء الأعمدة المطابقة لأسماء البرنامج.
                يمكنك تعديل أي اختيار يدوياً قبل المعاينة.
              </div>
              <button type="button" class="sie-btn sie-btn-secondary sie-btn-compact" id="sieAutoMapBtn"><i class="fa fa-magic"></i> مطابقة تلقائياً الآن</button>
            </div>

            <div class="sie-field-grid sie-field-grid-main">
              <div class="sie-field">
                <label>عمود اسم المستخدم PPPoE <span class="text-danger">*</span></label>
                <select name="username_col" class="sie-control" required>
                  <option value="">— اختر —</option>
                  <?php foreach($headers as $i=>$h): ?><option value="<?= (int)$i ?>"<?= sie_form_selected_col($autoMap, 'username_col', (int)$i) ?>><?= sie_h(($h !== '' ? $h : 'عمود '.($i+1))) ?></option><?php endforeach; ?>
                </select>
              </div>
              <div class="sie-field">
                <label>طريقة الاسم الكامل</label>
                <select name="full_mode" class="sie-control" id="fullMode">
                  <option value="none"<?= sie_form_selected_value($autoMap, 'full_mode', 'none', 'none') ?>>لا تحدّث الاسم</option>
                  <option value="single"<?= sie_form_selected_value($autoMap, 'full_mode', 'single', 'none') ?>>الاسم من عمود واحد</option>
                  <option value="merge"<?= sie_form_selected_value($autoMap, 'full_mode', 'merge', 'none') ?>>دمج 3 أعمدة</option>
                </select>
              </div>
              <div class="sie-field full-single">
                <label>عمود الاسم الكامل</label>
                <select name="full_name_col" class="sie-control"><option value="">—</option><?php foreach($headers as $i=>$h): ?><option value="<?= (int)$i ?>"<?= sie_form_selected_col($autoMap, 'full_name_col', (int)$i) ?>><?= sie_h(($h !== '' ? $h : 'عمود '.($i+1))) ?></option><?php endforeach; ?></select>
              </div>
            </div>

            <div class="sie-notice sie-notice-info full-merge-note ua-u-hidden">
              <i class="fa fa-link" aria-hidden="true"></i>
              <div>عند اختيار <b>دمج 3 أعمدة</b> اختر الأعمدة من نفس القائمة بالأسفل: <b>الاسم + اسم الأب + الكنية</b>، ولن تظهر خانات مكررة.</div>
            </div>

            <div class="sie-field-grid sie-field-grid-map">
              <?php foreach(sie_field_catalog($conn) as $field=>$label): if(in_array($field,['full_name','ppp_username'],true)) continue; ?>
              <div class="sie-field">
                <label><?= sie_h($label) ?></label>
                <select name="field_col_<?= sie_h($field) ?>" class="sie-control">
                  <option value="">لا تحدّث</option>
                  <?php foreach($headers as $i=>$h): ?><option value="<?= (int)$i ?>"<?= sie_form_selected_col($autoMap, 'field_col_'.$field, (int)$i) ?>><?= sie_h(($h !== '' ? $h : 'عمود '.($i+1))) ?></option><?php endforeach; ?>
                </select>
              </div>
              <?php endforeach; ?>
              <div class="sie-field sie-field-with-check">
                <label>الرقم المعروض #</label>
                <select name="display_id_col" class="sie-control"><option value="">لا تحدّث</option><?php foreach($headers as $i=>$h): ?><option value="<?= (int)$i ?>"<?= sie_form_selected_col($autoMap, 'display_id_col', (int)$i) ?>><?= sie_h(($h !== '' ? $h : 'عمود '.($i+1))) ?></option><?php endforeach; ?></select>
                <label class="sie-check-line" for="updateDisplayId">
                  <input class="form-check-input" type="checkbox" name="update_display_id" value="1" id="updateDisplayId">
                  <span>تفعيل تحديث # من Excel</span>
                </label>
              </div>
            </div>

            <label class="sie-check-line sie-check-line-wide" for="ignoreEmpty">
              <input class="form-check-input" type="checkbox" name="ignore_empty" value="1" id="ignoreEmpty" checked>
              <span>تجاهل الخانات الفارغة في Excel ولا تمسح القيمة القديمة</span>
            </label>

            <div class="sie-action-row">
              <button class="sie-btn sie-btn-primary" type="submit" onclick="document.getElementById('importMode').value='normal';"><i class="fa fa-random"></i> تنفيذ طبقة المطابقة والمعاينة</button>
              <button class="sie-btn sie-btn-danger" type="submit" onclick="document.getElementById('importMode').value='master';"><i class="fa fa-database"></i> اعتماد Excel كمرجع رئيسي</button>
            </div>
          </form>
        </div>
      </section>
      <?php endif; ?>

      <?php if ($preview): ?>
      <section class="sie-stat-grid" aria-label="ملخص المعاينة">
        <div class="sie-stat-card is-success"><span>سيتم تعديلهم</span><strong><?= (int)$preview['counts']['will_update'] ?></strong></div>
        <div class="sie-stat-card is-info"><span>مطابقين</span><strong><?= (int)$preview['counts']['matched'] ?></strong></div>
        <div class="sie-stat-card is-warning"><span>بالبرنامج فقط</span><strong><?= (int)$preview['counts']['program_only'] ?></strong></div>
        <div class="sie-stat-card is-danger"><span>مكرر في Excel</span><strong><?= (int)$preview['counts']['duplicates'] ?></strong></div>
      </section>

      <?php if (($preview['import_mode'] ?? 'normal') === 'master' && !empty($preview['program_only'])): ?>
      <div class="sie-notice sie-notice-warning">
        <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
        <div><b>تنبيه المرجع الرئيسي:</b> يوجد <?= (int)$preview['counts']['program_only'] ?> حساب في البرنامج غير موجود في ملف Excel أو مكرر داخله. يمكن تفريغ الهاتف والعنوان لهذه الحسابات، بينما يبقى اسم المشترك محفوظاً ولا يُستبدل بحساب PPPoE.</div>
      </div>
      <?php endif; ?>

      <section class="sie-card sie-preview-card">
        <div class="sie-card-head sie-card-head-actions">
          <h2>3) معاينة المطابقين</h2>
          <form method="post" id="sieCommitForm" class="sie-commit-form js-import-commit-form">
            <input type="hidden" name="action" value="commit"><input type="hidden" name="token" value="<?= sie_h($preview['token']) ?>">
            <?php if (($preview['import_mode'] ?? 'normal') === 'master' && !empty($preview['program_only'])): ?>
              <label class="sie-check-line sie-check-line-inline sie-reset-missing" for="sieResetMissing">
                <input class="form-check-input" type="checkbox" name="reset_missing" value="1" id="sieResetMissing">
                <span>تنظيف بيانات الحسابات غير الموجودة مع حفظ الاسم</span>
              </label>
            <?php endif; ?>
            <button type="submit" id="sieCommitBtn" class="sie-btn sie-btn-primary"><i class="fa fa-save"></i> تنفيذ الاستيراد</button>
            <span id="sieCommitStatus" class="sie-commit-status ua-u-hidden">جاري تنفيذ الاستيراد...</span>
          </form>
        </div>
        <div class="sie-card-body sie-table-wrap">
          <table class="table table-bordered table-sm align-middle sie-table">
            <thead><tr><th>PPPoE</th><th>سطر Excel</th><th>التغييرات</th></tr></thead>
            <tbody>
            <?php foreach(array_slice($preview['matched'],0,300) as $m): ?>
              <tr>
                <td><?= sie_h($m['ppp_username']) ?></td>
                <td><?= (int)$m['excel_row'] ?></td>
                <td>
                  <?php if(empty($m['changes'])): ?><span class="sie-muted">لا يوجد تغيير</span><?php else: ?>
                    <?php foreach($m['changes'] as $field=>$ch): ?>
                      <div class="sie-change-line"><b><?= sie_h(sie_field_label($conn, $field)) ?>:</b>
                      <span class="sie-old-value"><?= sie_h($ch['old']) ?></span> ← <span class="sie-new-value"><?= sie_h($ch['new']) ?></span></div>
                    <?php endforeach; ?>
                  <?php endif; ?>
                </td>
              </tr>
            <?php endforeach; ?>
            </tbody>
          </table>
          <?php if(count($preview['matched'])>300): ?><div class="sie-notice sie-notice-soft">تم عرض أول 300 صف فقط للتخفيف، والحفظ سيطبق كل النتائج المطابقة.</div><?php endif; ?>
        </div>
      </section>

      <section class="sie-report-grid">
        <div class="sie-card sie-report-card"><div class="sie-card-head"><h2>موجود بالبرنامج وغير موجود/مكرر في Excel</h2></div><div class="sie-card-body sie-table-wrap"><table class="table table-sm sie-table"><tbody><?php foreach(array_slice($preview['program_only'],0,100) as $x): ?><tr><td><?= sie_h($x['ppp_username']) ?></td><td><?= sie_h($x['reason']) ?></td></tr><?php endforeach; ?></tbody></table></div></div>
        <div class="sie-card sie-report-card"><div class="sie-card-head"><h2>موجود في Excel وغير موجود بالبرنامج</h2></div><div class="sie-card-body sie-table-wrap"><table class="table table-sm sie-table"><tbody><?php foreach(array_slice($preview['excel_only'],0,100) as $x): ?><tr><td><?= sie_h($x['ppp_username']) ?></td><td>سطر <?= (int)$x['excel_row'] ?></td></tr><?php endforeach; ?></tbody></table></div></div>
        <div class="sie-card sie-report-card"><div class="sie-card-head"><h2>أسماء مكررة داخل Excel</h2></div><div class="sie-card-body sie-table-wrap"><table class="table table-sm sie-table"><tbody><?php foreach(array_slice($preview['duplicates'],0,100) as $x): ?><tr><td><?= sie_h($x['ppp_username']) ?></td><td><?= (int)$x['count'] ?> مرات</td></tr><?php endforeach; ?></tbody></table></div></div>
      </section>
      <?php endif; ?>

      <section class="sie-card sie-log-card">
        <div class="sie-card-head"><h2>آخر عمليات الاستيراد والتراجع</h2></div>
        <div class="sie-card-body sie-table-wrap">
          <table class="table table-bordered table-sm sie-table">
            <thead><tr><th>#</th><th>الوقت</th><th>الملف</th><th>تعديل</th><th>الحالة</th><th>تراجع</th></tr></thead>
            <tbody>
            <?php foreach($logs as $l): ?>
              <tr>
                <td><?= (int)$l['id'] ?></td><td><?= sie_h($l['created_at']) ?></td><td><?= sie_h($l['source_file']) ?></td><td><?= (int)$l['updated_count'] ?></td><td><?= sie_h($l['status']) ?></td>
                <td><?php if(($l['status'] ?? '') !== 'rolled_back'): ?><form method="post" class="js-confirm-form sie-inline-form" data-confirm-title="تأكيد التراجع" data-confirm-message="سيتم إرجاع القيم القديمة لهذه العملية. هل تريد المتابعة؟"><input type="hidden" name="action" value="rollback"><input type="hidden" name="batch_id" value="<?= (int)$l['id'] ?>"><button class="sie-btn sie-btn-danger sie-btn-compact">تراجع</button></form><?php else: ?>—<?php endif; ?></td>
              </tr>
            <?php endforeach; ?>
            </tbody>
          </table>
        </div>
      </section>
    </div>
  </section>
</div>
<?php $sieToasts = [];
if ($inlineMsg) $sieToasts[] = ['kind' => 'success', 'title' => 'تمت العملية', 'message' => $inlineMsg];
if ($msg)       $sieToasts[] = ['kind' => 'success', 'title' => 'تم بنجاح', 'message' => $msg];
if ($err)       $sieToasts[] = ['kind' => 'error',   'title' => 'تنبيه',    'message' => $err];
?>
<?php if($sieToasts): ?>
<div class="ua-feedback-stack sie-toast-stack" id="sieToastStack" aria-live="polite" aria-atomic="true">
  <?php foreach($sieToasts as $toast): ?>
    <div class="sie-toast sie-toast-<?= sie_h($toast['kind']) ?>" data-toast>
      <div class="sie-toast-icon"><i class="fa <?= $toast['kind'] === 'error' ? 'fa-exclamation-circle' : 'fa-check-circle' ?>" aria-hidden="true"></i></div>
      <div class="sie-toast-body">
        <div class="sie-toast-title"><?= sie_h($toast['title']) ?></div>
        <div class="sie-toast-message"><?= sie_h($toast['message']) ?></div>
      </div>
      <button type="button" class="sie-toast-close" data-toast-close aria-label="إغلاق">×</button>
    </div>
  <?php endforeach; ?>
</div>
<?php endif; ?>
<div class="sie-modal-backdrop" id="sieConfirmModal">
  <div class="sie-modal">
    <div class="sie-modal-head"><div class="sie-modal-title" id="sieConfirmTitle">تأكيد</div><button type="button" class="sie-modal-close" id="sieConfirmClose">×</button></div>
    <div class="sie-modal-body" id="sieConfirmMessage">هل تريد المتابعة؟</div>
    <div class="sie-modal-actions"><button type="button" class="sie-btn sie-btn-primary" id="sieConfirmOk">حسناً</button><button type="button" class="sie-btn sie-btn-secondary" id="sieConfirmCancel">إلغاء</button></div>
  </div>
</div>
<script>
(function(){
  const sieAutoMap = <?= json_encode($autoMap ?? [], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>;
  const scrollStoreKey = 'sie-import-excel-scroll';
  window.__sieSubmitting = false;
  function scrollTarget(){
    return document.scrollingElement || document.documentElement || document.body;
  }
  function addScrollCandidate(list, key, el){
    if(!el || list.some(item => item.el === el)) return;
    list.push({key, el});
  }
  function scrollCandidates(){
    const list = [];
    addScrollCandidate(list, 'page', scrollTarget());
    addScrollCandidate(list, 'html', document.documentElement);
    addScrollCandidate(list, 'body', document.body);
    [
      '.content-wrapper.ua-sub-child-import-excel',
      '.sie-import-page',
      '.sie-import-content',
      '.sie-import-shell',
      '.sie-table-wrap'
    ].forEach(selector => {
      document.querySelectorAll(selector).forEach((el, index) => addScrollCandidate(list, selector + ':' + index, el));
    });
    return list;
  }
  function currentPageTop(){
    const page = scrollTarget();
    return Math.max(
      0,
      window.scrollY || 0,
      page ? page.scrollTop : 0,
      document.documentElement ? document.documentElement.scrollTop : 0,
      document.body ? document.body.scrollTop : 0
    );
  }
  function parentScrollBox(){
    try {
      if(!window.parent || window.parent === window || !window.parent.document) return null;
      return window.parent.document.getElementById('uaFixContentBody');
    } catch(e) {
      return null;
    }
  }
  function rememberScroll(){
    try {
      const internal = {};
      scrollCandidates().forEach(item => {
        internal[item.key] = Math.max(0, item.el.scrollTop || 0);
      });
      const parentBox = parentScrollBox();
      const state = {
        pageTop: currentPageTop(),
        internal,
        parentTop: parentBox ? Math.max(0, parentBox.scrollTop || 0) : 0,
        storedAt: Date.now()
      };
      const encoded = JSON.stringify(state);
      sessionStorage.setItem(scrollStoreKey, encoded);
      try {
        if(window.parent && window.parent !== window && window.parent.sessionStorage){
          window.parent.sessionStorage.setItem(scrollStoreKey, encoded);
        }
      } catch(e) {}
    } catch(e) {}
  }
  function restoreScroll(){
    try {
      let raw = sessionStorage.getItem(scrollStoreKey);
      if(!raw){
        try {
          if(window.parent && window.parent !== window && window.parent.sessionStorage){
            raw = window.parent.sessionStorage.getItem(scrollStoreKey);
          }
        } catch(e) {}
      }
      if(!raw) return;
      const state = JSON.parse(raw);
      const page = scrollTarget();
      const pageTop = Math.max(0, parseInt(state.pageTop, 10) || 0);
      const internal = state.internal && typeof state.internal === 'object' ? state.internal : {};
      const parentTop = Math.max(0, parseInt(state.parentTop, 10) || 0);
      const apply = function(){
        if(page) page.scrollTop = pageTop;
        if(document.documentElement) document.documentElement.scrollTop = pageTop;
        if(document.body) document.body.scrollTop = pageTop;
        window.scrollTo(0, pageTop);
        scrollCandidates().forEach(item => {
          if(Object.prototype.hasOwnProperty.call(internal, item.key)){
            item.el.scrollTop = Math.max(0, parseInt(internal[item.key], 10) || 0);
          }
        });
        const parentBox = parentScrollBox();
        if(parentBox && parentTop) parentBox.scrollTop = parentTop;
      };
      [0, 30, 90, 180, 360, 700, 1200].forEach(delay => {
        setTimeout(function(){ requestAnimationFrame(apply); }, delay);
      });
      setTimeout(function(){
        try { sessionStorage.removeItem(scrollStoreKey); } catch(x) {}
        try {
          if(window.parent && window.parent !== window && window.parent.sessionStorage){
            window.parent.sessionStorage.removeItem(scrollStoreKey);
          }
        } catch(x) {}
      }, 1600);
    } catch(e) {
      try { sessionStorage.removeItem(scrollStoreKey); } catch(x) {}
    }
  }
  restoreScroll();
  document.addEventListener('click', function(e){
    const target = e.target && e.target.closest ? e.target.closest('button,input[type="submit"],a[href]') : null;
    if(target) rememberScroll();
  }, true);
  document.addEventListener('submit', function(e){
    if(e.defaultPrevented) return;
    rememberScroll();
    window.__sieSubmitting = true;
  }, false);
  window.addEventListener('beforeunload', function(){
    if (window.__sieSubmitting) return;
    try { navigator.sendBeacon('subscribers_import_excel.php?action=clear_import_silent', new Blob(['1'], {type:'text/plain'})); } catch(e) {}
  });
  const mode = document.getElementById('fullMode');
  function refresh(){
    const v = mode ? mode.value : 'none';
    document.querySelectorAll('.full-single').forEach(e=>e.style.display = v==='single' ? '' : 'none');
    document.querySelectorAll('.full-merge-note').forEach(e=>e.style.display = v==='merge' ? '' : 'none');
  }
  if(mode){ mode.addEventListener('change', refresh); refresh(); }
  function applyAutoMap(){
    if(!sieAutoMap || typeof sieAutoMap !== 'object') return;
    Object.entries(sieAutoMap).forEach(([name, value])=>{
      if(value === null || value === undefined || value === '') return;
      const el = document.getElementsByName(name)[0];
      if(!el) return;
      el.value = String(value);
      el.dispatchEvent(new Event('change', {bubbles:true}));
    });
    refresh();
  }
  const fileInput = document.getElementById('sieExcelFile');
  const fileName = document.getElementById('sieFileName');
  const fileBox = fileInput ? fileInput.closest('.sie-file-box') : null;
  if(fileInput && fileBox){
    fileBox.addEventListener('click', function(e){
      if(e.target === fileInput) return;
      fileInput.click();
    });
    fileBox.addEventListener('keydown', function(e){
      if(e.key === 'Enter' || e.key === ' '){
        e.preventDefault();
        fileInput.click();
      }
    });
  }
  if(fileInput && fileName){
    fileInput.addEventListener('change', function(){
      fileName.textContent = (fileInput.files && fileInput.files[0]) ? fileInput.files[0].name : 'لم يتم اختيار أي ملف';
    });
  }
  document.querySelectorAll('[data-toast]').forEach(toast=>{
    const closeBtn = toast.querySelector('[data-toast-close]');
    const dismiss = ()=>{ toast.classList.add('is-leaving'); setTimeout(()=>toast.remove(), 180); };
    if(closeBtn) closeBtn.addEventListener('click', dismiss);
    setTimeout(dismiss, toast.classList.contains('sie-toast-error') ? 7000 : 4500);
  });
  const autoBtn = document.getElementById('sieAutoMapBtn');
  if(autoBtn) autoBtn.addEventListener('click', applyAutoMap);
  const modal = document.getElementById('sieConfirmModal');
  const title = document.getElementById('sieConfirmTitle');
  const msg = document.getElementById('sieConfirmMessage');
  const ok = document.getElementById('sieConfirmOk');
  const cancel = document.getElementById('sieConfirmCancel');
  const close = document.getElementById('sieConfirmClose');
  let pendingForm = null, pendingButton = null;
  function openConfirm(t, m, form, button){
    pendingForm = form; pendingButton = button || null;
    title.textContent = t || 'تأكيد'; msg.textContent = m || 'هل تريد المتابعة؟';
    modal.style.display = 'flex';
  }
  function closeConfirm(){ modal.style.display='none'; pendingForm=null; pendingButton=null; }
  [cancel, close].forEach(b=>b && b.addEventListener('click', closeConfirm));
  if(modal) modal.addEventListener('click', e=>{ if(e.target===modal) closeConfirm(); });
  if(ok) ok.addEventListener('click', ()=>{
    const form = pendingForm;
    const button = pendingButton;
    if(!form) return closeConfirm();
    if(form.reportValidity && !form.reportValidity()) return;
    form.dataset.confirmed = '1';
    form.dataset.sieConfirmed = '1';
    if(button && button.name){
      let h = form.querySelector('input[type="hidden"][name="'+button.name+'"]');
      if(!h){ h=document.createElement('input'); h.type='hidden'; h.name=button.name; form.appendChild(h); }
      h.value = button.value || '1';
    }
    closeConfirm(); window.__sieSubmitting = true;
    rememberScroll();
    if(form.id === 'sieCommitForm'){
      const btn = document.getElementById('sieCommitBtn');
      const status = document.getElementById('sieCommitStatus');
      if(btn){ btn.disabled = true; btn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> جاري التنفيذ'; }
      if(status) status.style.display = '';
    }
    HTMLFormElement.prototype.submit.call(form);
  });
  const commitForm = document.getElementById('sieCommitForm');
  const commitBtn = document.getElementById('sieCommitBtn');
  const commitStatus = document.getElementById('sieCommitStatus');
  if(commitForm){
    commitForm.addEventListener('submit', function(e){
      if(commitForm.dataset.sieConfirmed === '1'){
        window.__sieSubmitting = true;
        if(commitBtn){ commitBtn.disabled = true; commitBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> جاري التنفيذ'; }
        if(commitStatus) commitStatus.style.display = '';
        return true;
      }
      e.preventDefault();
      openConfirm('تنفيذ الاستيراد', 'سيتم حفظ التحديثات المطابقة الآن. هل تريد المتابعة؟', commitForm, commitBtn);
    }, true);
  }

  document.querySelectorAll('.js-confirm-form').forEach(form=>{
    form.addEventListener('submit', function(e){
      if(form.dataset.confirmed === '1'){ delete form.dataset.confirmed; return; }
      e.preventDefault();
      openConfirm(form.dataset.confirmTitle, form.dataset.confirmMessage, form, document.activeElement && form.contains(document.activeElement) ? document.activeElement : null);
    });
  });
  document.querySelectorAll('.js-confirm-submit').forEach(btn=>{
    btn.addEventListener('click', function(e){
      const form = btn.closest('form'); if(!form) return;
      e.preventDefault();
      openConfirm(btn.dataset.confirmTitle || form.dataset.confirmTitle, btn.dataset.confirmMessage || form.dataset.confirmMessage, form, btn);
    });
  });
})();
</script>
<?php include __DIR__ . '/footer.php'; ?>
