<?php
// Root service for creating subscribers from the agent portal.

require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/subscribers_lib.php';
require_once __DIR__ . '/subscriber_plan_schema.php';
require_once __DIR__ . '/subscriber_reference_data_lib.php';
require_once __DIR__ . '/subscriber_upload_lib.php';
require_once __DIR__ . '/finance_payment_lib.php';
require_once __DIR__ . '/agent_service.php';
require_once __DIR__ . '/agent_portal_lib.php';
require_once __DIR__ . '/subscriber_id_sequence_lib.php';
if (is_file(__DIR__ . '/mikrotik_lib.php')) require_once __DIR__ . '/mikrotik_lib.php';

if (!function_exists('agent_subscriber_prepare_schema')) {
  function agent_subscriber_prepare_schema(mysqli $conn): void {
    if (function_exists('subscriber_plan_ensure_schema')) @subscriber_plan_ensure_schema($conn);
    if (function_exists('subs_ensure_pppoe_cols')) @subs_ensure_pppoe_cols($conn);
    agent_portal_ensure_schema($conn);
  }
}

if (!function_exists('agent_subscriber_digits')) {
  function agent_subscriber_digits(string $v): string {
    return function_exists('subs_policy_digits') ? subs_policy_digits($v) : (preg_replace('/\D+/', '', $v) ?? '');
  }
}

if (!function_exists('agent_subscriber_slug')) {
  function agent_subscriber_slug(string $firstName, string $lastName): string {
    if (function_exists('subs_policy_slug_local')) {
      $slug = subs_policy_slug_local($firstName, $lastName);
    } else {
      $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '.', trim($firstName . '.' . $lastName)) ?? '', '.'));
    }
    return $slug !== '' ? $slug : 'subscriber';
  }
}

if (!function_exists('agent_subscriber_unique_pppoe')) {
  function agent_subscriber_unique_pppoe(mysqli $conn, string $local, string $domain = ''): string {
    if ($domain === '') $domain = subs_policy_pppoe_domain($conn);
    return subs_policy_unique_pppoe($conn, $local, $domain, 0, '');
  }
}

if (!function_exists('agent_subscriber_password')) {
  function agent_subscriber_password(string $motherName, string $phone): string {
    if (function_exists('subs_policy_password')) return subs_policy_password($motherName, $phone);
    $digits = agent_subscriber_digits($phone);
    return 'X' . substr(str_pad($digits, 5, '0', STR_PAD_LEFT), -5);
  }
}

if (!function_exists('agent_subscriber_sql_value')) {
  function agent_subscriber_sql_value(mysqli $conn, $value, bool $numeric = false): string {
    if ($value === null || $value === '') return $numeric ? 'NULL' : "''";
    if ($numeric) return is_float($value) ? (string)(float)$value : (string)(int)$value;
    return "'" . $conn->real_escape_string((string)$value) . "'";
  }
}

if (!function_exists('agent_subscriber_insert_row')) {
  function agent_subscriber_insert_row(mysqli $conn, array $values, array $numeric = []): int {
    $cols = [];
    $vals = [];
    foreach ($values as $col => $value) {
      if (!col_exists($conn, 'subscribers', $col)) continue;
      $cols[] = '`' . str_replace('`', '', $col) . '`';
      $vals[] = agent_subscriber_sql_value($conn, $value, in_array($col, $numeric, true));
    }
    if (!$cols) throw new RuntimeException('لا توجد أعمدة مشتركة صالحة للحفظ.');
    ua_subscriber_ensure_id_sequence($conn);
    $sql = "INSERT INTO subscribers (" . implode(',', $cols) . ") VALUES (" . implode(',', $vals) . ")";
    if (!$conn->query($sql)) throw new RuntimeException('فشل حفظ المشترك: ' . $conn->error);
    return (int)$conn->insert_id;
  }
}

if (!function_exists('agent_subscriber_create_invoice')) {
  function agent_subscriber_create_invoice(mysqli $conn, int $subscriberId, float $amount, bool $isPaid, string $note, int $agentId): int {
    if (!table_exists($conn, 'invoices')) return 0;
    $values = [
      'subscriber_id'=>$subscriberId,
      'amount'=>$amount,
      'status'=>$isPaid ? 'مدفوع' : 'غير مدفوع',
      'cycle_month'=>date('Y-m'),
      'invoice_type'=>'NEW_SUB',
      'notes'=>$note,
      'paid_at'=>$isPaid ? date('Y-m-d H:i:s') : null,
      'created_at'=>date('Y-m-d H:i:s'),
      'paid_amount'=>$isPaid ? $amount : 0,
      'remaining_amount'=>$isPaid ? 0 : $amount,
      'payment_status'=>$isPaid ? 'paid' : 'unpaid',
      'paid_by_type'=>$isPaid ? 'agent' : null,
      'paid_by_id'=>$isPaid ? $agentId : null,
      'updated_at'=>date('Y-m-d H:i:s'),
    ];
    $numeric = ['subscriber_id','amount','paid_amount','remaining_amount','paid_by_id'];
    $cols = [];
    $vals = [];
    foreach ($values as $col => $value) {
      if (!col_exists($conn, 'invoices', $col)) continue;
      $cols[] = '`' . str_replace('`', '', $col) . '`';
      $vals[] = agent_subscriber_sql_value($conn, $value, in_array($col, $numeric, true));
    }
    if (!$cols) return 0;
    $sql = "INSERT INTO invoices (" . implode(',', $cols) . ") VALUES (" . implode(',', $vals) . ")";
    if (!$conn->query($sql)) throw new RuntimeException('فشل إنشاء الفاتورة الأولية: ' . $conn->error);
    return (int)$conn->insert_id;
  }
}

if (!function_exists('agent_subscriber_create')) {
  function agent_subscriber_create(mysqli $conn, array $agent, array $data): array {
    agent_subscriber_prepare_schema($conn);
    $agentId = (int)($agent['id'] ?? 0);
    if ($agentId <= 0) return ['ok'=>false,'error'=>'المعتمد غير صالح.'];

    $firstName = trim((string)($data['first_name'] ?? ''));
    $fatherName = trim((string)($data['father_name'] ?? ''));
    $lastName = trim((string)($data['last_name'] ?? ''));
    $motherName = trim((string)($data['mother_name'] ?? ''));
    $phone = trim((string)($data['phone'] ?? ''));
    $address = trim((string)($data['address_area'] ?? ''));
    $nationalId = trim((string)($data['national_id'] ?? ''));
    $recordNumber = trim((string)($data['record_number'] ?? ''));
    $documentTypeRaw = trim((string)($data['document_type'] ?? 'هوية شخصية'));
    $documentType = function_exists('subscriber_document_type_normalize')
      ? subscriber_document_type_normalize($documentTypeRaw)
      : ($documentTypeRaw ?: 'هوية شخصية');
    $documentNumber = trim((string)($data['document_number'] ?? ''));
    $birthDate = trim((string)($data['birth_date'] ?? ''));
    $notes = trim((string)($data['notes'] ?? ''));
    $speedId = (int)($data['speed_id'] ?? 0);
    $packageId = (int)($data['package_id'] ?? 0);
    $sectorId = (int)($data['sector_id'] ?? 0);
    $isPaid = !empty($data['is_paid']);
    $staticIp = function_exists('subs_static_ip_normalize') ? subs_static_ip_normalize((string)($data['ip_address'] ?? '')) : trim((string)($data['ip_address'] ?? ''));

    if ($firstName === '' || $fatherName === '' || $lastName === '' || $motherName === '' || $phone === '') {
      return ['ok'=>false,'error'=>'الاسم واسم الأب والكنية واسم الأم والهاتف مطلوبة.'];
    }
    if (strlen(agent_subscriber_digits($phone)) < 5) return ['ok'=>false,'error'=>'رقم الهاتف يجب أن يحتوي 5 أرقام على الأقل.'];
    if ($speedId <= 0 || $packageId <= 0 || $sectorId <= 0) return ['ok'=>false,'error'=>'اختر السرعة والباقة والقطاع.'];
    if ($documentType === '') return ['ok'=>false,'error'=>'نوع الوثيقة غير صالح.'];
    if ($staticIp !== '' && function_exists('subs_static_ip_validate')) {
      $ipErr = subs_static_ip_validate($staticIp);
      if ($ipErr !== '') return ['ok'=>false,'error'=>$ipErr];
    }

    $speeds = function_exists('subscriber_ref_fetch_speeds') ? subscriber_ref_fetch_speeds($conn) : [];
    $packages = function_exists('subscriber_ref_fetch_packages') ? subscriber_ref_fetch_packages($conn) : [];
    $sectors = function_exists('subscriber_ref_fetch_sectors') ? subscriber_ref_fetch_sectors($conn, true) : [];
    $speedRow = [];
    $packageRow = [];
    $sectorRow = [];
    foreach ($speeds as $s) if ((int)($s['id'] ?? 0) === $speedId) { $speedRow = $s; break; }
    foreach ($packages as $p) if ((int)($p['id'] ?? 0) === $packageId) { $packageRow = $p; break; }
    foreach ($sectors as $s) if ((int)($s['id'] ?? 0) === $sectorId) { $sectorRow = $s; break; }
    if (!$speedRow || !$packageRow || !$sectorRow) return ['ok'=>false,'error'=>'السرعة أو الباقة أو القطاع غير موجودة.'];

    $fullName = trim($firstName . ' ' . $fatherName . ' ' . $lastName);
    $pppUsername = agent_subscriber_unique_pppoe($conn, agent_subscriber_slug($firstName, $lastName));
    $pppPassword = agent_subscriber_password($motherName, $phone);
    $speedName = trim((string)($speedRow['speed_name'] ?? ''));
    $packageName = trim((string)($packageRow['package_name'] ?? ''));
    $speedPrice = (float)($speedRow['price'] ?? 0);
    $packagePrice = (float)($packageRow['price'] ?? 0);
    $subscriptionFee = (float)($packageRow['subscription_fee'] ?? 0);
    $invoiceAmount = round($speedPrice + $packagePrice + $subscriptionFee, 2);
    $invoiceNote = 'السرعة: ' . $speedName . ' = ' . number_format($speedPrice, 2) . ' | الباقة: ' . $packageName . ' = ' . number_format($packagePrice, 2) . ' | رسوم الاشتراك = ' . number_format($subscriptionFee, 2);
    $quotaGb = isset($packageRow['quota_gb']) && $packageRow['quota_gb'] !== '' ? (int)$packageRow['quota_gb'] : null;
    $mtProfile = trim((string)($speedRow['mikrotik_profile'] ?? ''));
    if ($mtProfile === '') $mtProfile = trim((string)($packageRow['mikrotik_profile'] ?? ''));
    if ($mtProfile === '') $mtProfile = trim((string)($sectorRow['pppoe_profile'] ?? ''));
    if ($mtProfile === '' && function_exists('ppp_profile_from_speed')) $mtProfile = ppp_profile_from_speed($speedName, $packageName, 'pppoe-prof');
    if ($mtProfile === '') $mtProfile = 'pppoe-prof';
    $rateLimit = trim((string)($speedRow['rate_limit'] ?? ''));
    if ($rateLimit === '' && $speedName !== '') $rateLimit = $speedName . '/' . $speedName;
    $sourceInstanceId = trim((string)($agent['linked_instance_id'] ?? ''));
    if ($sourceInstanceId === '') {
      $link = ua_install_link_config();
      $sourceInstanceId = trim((string)($link['instance_id'] ?? ''));
    }

    foreach ([['phone',$phone,'رقم الهاتف مستخدم مسبقاً.'], ['national_id',$nationalId,'الرقم الوطني مستخدم مسبقاً.']] as $check) {
      [$col,$value,$message] = $check;
      if ($value === '' || !col_exists($conn, 'subscribers', $col)) continue;
      $esc = $conn->real_escape_string($value);
      $activeSql = col_exists($conn, 'subscribers', 'is_deleted') ? 'AND COALESCE(is_deleted,0)=0' : '';
      $rs = @$conn->query("SELECT id FROM subscribers WHERE `{$col}`='{$esc}' {$activeSql} LIMIT 1");
      if ($rs && $rs->num_rows) return ['ok'=>false,'error'=>$message];
    }

    try {
      $conn->begin_transaction();
      $frontPath = function_exists('subscriber_identity_upload') ? subscriber_identity_upload('id_card_front', 'front') : null;
      $backPath = function_exists('subscriber_identity_upload') ? subscriber_identity_upload('id_card_back', 'back') : null;
      $pdfPath = function_exists('subscriber_identity_upload') ? subscriber_identity_upload('id_card_pdf', 'pdf') : null;

      $subscriberId = agent_subscriber_insert_row($conn, [
        'username'=>$pppUsername,
        'password_plain'=>$pppPassword,
        'full_name'=>$fullName,
        'first_name'=>$firstName,
        'father_name'=>$fatherName,
        'last_name'=>$lastName,
        'mother_name'=>$motherName,
        'birth_date'=>$birthDate !== '' ? $birthDate : null,
        'phone'=>$phone,
        'address_area'=>$address,
        'document_type'=>$documentType,
        'document_number'=>$documentNumber,
        'national_id'=>$nationalId,
        'record_number'=>$recordNumber,
        'id_card_front'=>$frontPath,
        'id_card_back'=>$backPath,
        'id_front'=>$frontPath,
        'id_back'=>$backPath,
        'id_pdf'=>$pdfPath,
        'speed'=>$speedName,
        'package'=>$packageName,
        'status'=>$isPaid ? 'نشط' : 'متوقف',
        'notes'=>$notes,
        'speed_state'=>'ORIGINAL',
        'base_speed'=>$speedName,
        'current_speed'=>$speedName,
        'package_name'=>$packageName,
        'speed_name'=>$speedName,
        'is_deleted'=>0,
        'ppp_username'=>$pppUsername,
        'ppp_password'=>$pppPassword,
        'ppp_profile'=>$mtProfile,
        'ppp_rate_limit'=>$rateLimit,
        'pppoe_profile'=>$mtProfile,
        'quota_gb'=>$quotaGb,
        'used_gb'=>0,
        'sector_id'=>$sectorId,
        'vlan_id'=>(int)($sectorRow['vlan_id'] ?? 0),
        'provision_status'=>$isPaid ? 'active' : 'pending_payment',
        'mt_disabled'=>$isPaid ? 0 : 1,
        'ppp_is_disabled'=>$isPaid ? 0 : 1,
        'ip_address'=>$staticIp,
        'created_by_type'=>'agent',
        'created_by_id'=>$agentId,
        'source_instance_id'=>$sourceInstanceId,
        'registered_at'=>date('Y-m-d H:i:s'),
      ], ['is_deleted','quota_gb','used_gb','sector_id','vlan_id','mt_disabled','ppp_is_disabled','created_by_id']);

      $invoiceId = agent_subscriber_create_invoice($conn, $subscriberId, $invoiceAmount, $isPaid, $invoiceNote, $agentId);
      if ($invoiceId <= 0) throw new RuntimeException('فشل إنشاء الفاتورة الأولية.');
      if ($isPaid && function_exists('finance_record_payment_row')) {
        $pay = finance_record_payment_row($conn, $invoiceId, $subscriberId, $invoiceAmount, 'نقدي', 'تسديد مباشر عبر واجهة المعتمد', 'AGENT: ' . (string)($agent['name'] ?? ''), date('Y-m-d H:i:s'), 'AGENT_NEW_SUB#' . $subscriberId, $agentId, [
          'idempotency_key'=>'AGENT_NEW_SUB_PAYMENT:' . $agentId . ':' . $subscriberId,
          'source_type'=>'agent',
          'source_ref'=>(string)$agentId,
          'source_name'=>(string)($agent['name'] ?? ('معتمد #' . $agentId)),
          'source_instance_id'=>$sourceInstanceId,
          'channel'=>'agent_portal',
        ]);
        if (empty($pay['ok'])) throw new RuntimeException((string)($pay['error'] ?? 'فشل تسجيل الدفعة.'));
      }
      $charge = ua_agent_service_charge_subscriber($conn, $agentId, $subscriberId, $invoiceId, $invoiceAmount, [
        'type'=>'agent',
        'id'=>$agentId,
        'source_instance_id'=>$sourceInstanceId,
        'manage_transaction'=>false,
      ]);
      if (empty($charge['ok'])) throw new RuntimeException((string)($charge['error'] ?? 'فشل ترحيل رصيد المعتمد.'));

      ua_agent_activity_add($conn, [
        'agent_id'=>$agentId,
        'event_type'=>'SUBSCRIBER_CREATED',
        'direction'=>'TO_MAIN',
        'source_instance_id'=>$sourceInstanceId,
        'entity_type'=>'subscriber',
        'entity_id'=>(string)$subscriberId,
        'summary'=>'أضاف المعتمد مشتركاً جديداً من واجهته.',
        'payload'=>['subscriber_id'=>$subscriberId,'invoice_id'=>$invoiceId,'amount'=>$invoiceAmount,'name'=>$fullName],
        'actor_type'=>'agent',
        'actor_id'=>$agentId,
      ]);

      if ($sourceInstanceId !== '') {
        ua_agent_sync_enqueue($conn, [
          'agent_id'=>$agentId,
          'instance_id'=>$sourceInstanceId,
          'direction'=>'OUTBOUND',
          'event_type'=>'SUBSCRIBER_CREATED',
          'entity_type'=>'subscriber',
          'entity_id'=>(string)$subscriberId,
          'idempotency_key'=>'OUTBOUND:SUBSCRIBER_CREATED:' . $sourceInstanceId . ':' . $subscriberId,
          'payload'=>['subscriber_id'=>$subscriberId,'invoice_id'=>$invoiceId,'amount'=>$invoiceAmount,'full_name'=>$fullName],
        ]);
      }

      $conn->commit();
    } catch (Throwable $e) {
      try { $conn->rollback(); } catch (Throwable $ignore) {}
      return ['ok'=>false,'error'=>$e->getMessage()];
    }

    $mtWarning = '';
    if ($isPaid && function_exists('mt_ppp_secret_upsert')) {
      try {
        $serial = 'AGENT-SUB-' . $subscriberId;
        if (function_exists('mt_ppp_profile_ensure')) @mt_ppp_profile_ensure($conn, $mtProfile, $rateLimit);
        $mtOk = mt_ppp_secret_upsert($conn, $pppUsername, $pppPassword, $mtProfile, $staticIp, $serial, $rateLimit);
        if ($mtOk && function_exists('mt_ppp_secret_set_disabled')) {
          @mt_ppp_secret_set_disabled($conn, $pppUsername, false);
        }
        if (!$mtOk) $mtWarning = (string)($GLOBALS['mt_last_error'] ?? 'تم الحفظ محلياً لكن فشلت مزامنة MikroTik.');
      } catch (Throwable $e) {
        $mtWarning = $e->getMessage();
      }
    }

    return [
      'ok'=>true,
      'subscriber_id'=>$subscriberId,
      'invoice_id'=>$invoiceId,
      'amount'=>$invoiceAmount,
      'ppp_username'=>$pppUsername,
      'ppp_password'=>$pppPassword,
      'warning'=>$mtWarning,
      'error'=>'',
    ];
  }
}
