<?php
/**
 * /api/get_open_orders.php — FINAL (LAST)
 * ✅ يعيد الطلبات المفتوحة (pending) للمستخدم
 * ✅ NEW: قبل إرجاع النتائج يقوم بمزامنة جميع الطلبات المفتوحة عبر provider_execute()
 *    - يحدّث الحالات (FILLED => completed / canceled => canceled) ويعمل settlement/ledger داخل provider_execute
 * ✅ يدعم auth:
 *    - session user_id
 *    - (user_id + user_token)
 *    - user_token فقط
 * ✅ يدعم فلترة symbol اختياري: ?symbol=BNBUSDT
 *
 * ملاحظة مهمة:
 * - هذا الملف يفترض غالباً وجود مزود واحد فعّال (provider_execute دالة عامة).
 * - إذا عندك أكثر من مزود بملفات مختلفة وكلها تعرف provider_execute بنفس الاسم، ستحدث مشكلة تعارض.
 *   (نحن هنا نحمّل مزود واحد ونزامن أوامر هذا المزود فقط.)
 */

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

/* ================= CORS ================= */
$frontendOrigin = 'https://eazzybit.com';
$reqOrigin = $_SERVER['HTTP_ORIGIN'] ?? '';
if ($reqOrigin === $frontendOrigin) {
  header("Access-Control-Allow-Origin: {$frontendOrigin}");
  header("Vary: Origin");
  header("Access-Control-Allow-Credentials: true");
}
header("Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Max-Age: 600");
header("Content-Type: application/json; charset=UTF-8");
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') { http_response_code(204); exit; }

/* ================= DEBUG ================= */
$DEBUG_MODE = false;
if ($DEBUG_MODE) { ini_set('display_errors', '1'); error_reporting(E_ALL); }
else { ini_set('display_errors', '0'); error_reporting(0); }

/* ================= Helpers ================= */
function respond(bool $success, string $message, array $extra = [], int $status = 200): void {
  http_response_code($status);
  echo json_encode(array_merge(['success'=>$success,'message'=>$message], $extra), JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
  exit;
}

function read_input(): array {
  $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
  if ($method === 'POST') {
    $raw = file_get_contents('php://input') ?: '';
    $json = json_decode($raw, true);
    if (is_array($json)) return $json;
    return $_POST ?? [];
  }
  return $_GET ?? [];
}

function safe_upper($s): string {
  return strtoupper(preg_replace('/[^A-Z0-9_]/', '', (string)$s));
}

function table_exists(PDO $conn, string $table): bool {
  $st = $conn->prepare("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:t LIMIT 1");
  $st->execute([':t'=>$table]);
  return (bool)$st->fetchColumn();
}

function column_exists(PDO $conn, string $table, string $col): bool {
  $st = $conn->prepare("SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:t AND COLUMN_NAME=:c LIMIT 1");
  $st->execute([':t'=>$table, ':c'=>$col]);
  return (bool)$st->fetchColumn();
}

function safe_binding_file(string $f): string {
  $f = trim($f);
  $f = preg_replace('/[^A-Za-z0-9_.-]/', '', $f);
  if ($f === '') return '';
  if (stripos($f, '.php') === false) $f .= '.php';
  if (substr($f, -4) !== '.php') $f .= '.php';
  return $f;
}

/**
 * ✅ يدعم:
 * - session user_id
 * - (user_id + user_token)
 * - user_token فقط
 */
function resolveUserId(PDO $conn, array $in): int {
  $sid = isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : 0;
  if ($sid > 0) return $sid;

  $tok = trim((string)($in['user_token'] ?? ''));
  if ($tok === '') return 0;

  $uid = isset($in['user_id']) ? (int)$in['user_id'] : 0;

  if ($uid > 0) {
    $st = $conn->prepare("
      SELECT user_id
      FROM user_sessions
      WHERE user_id=:uid AND user_token=:tok AND is_online=1
      LIMIT 1
    ");
    $st->execute([':uid'=>$uid, ':tok'=>$tok]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    return $row ? (int)$row['user_id'] : 0;
  }

  $st = $conn->prepare("
    SELECT user_id
    FROM user_sessions
    WHERE user_token=:tok AND is_online=1
    ORDER BY id DESC
    LIMIT 1
  ");
  $st->execute([':tok'=>$tok]);
  $row = $st->fetch(PDO::FETCH_ASSOC);
  return $row ? (int)$row['user_id'] : 0;
}

/* ================= DB ================= */
require_once __DIR__ . '/../config.php';
if (!isset($conn) || !($conn instanceof PDO)) respond(false, 'اتصال قاعدة البيانات غير متوفر.', [], 500);

try {
  $in = read_input();

  foreach (['trade_orders','user_sessions','providers'] as $t) {
    if (!table_exists($conn, $t)) respond(false, "جدول {$t} غير موجود.", [], 500);
  }

  $userId = resolveUserId($conn, $in);
  if ($userId <= 0) respond(false, 'غير مصرح. الرجاء تسجيل الدخول.', ['unauthorized'=>true], 401);

  $symbol = safe_upper($in['symbol'] ?? ''); // اختياري

  // حد أقصى للمزامنة لتجنب timeouts إذا كان عندك عدد كبير
  $maxSync = isset($in['max_sync']) ? max(1, min(50, (int)$in['max_sync'])) : 25;

  // بناء SELECT أعمدة آمنة (بشكل ديناميكي)
  $cols = ['id','user_id'];
  $maybe = [
    'symbol','side','order_type','ui_order_mode',
    'price','client_price','qty_base','qty_quote',
    'provider_id','provider_order_id','client_order_id',
    'status','status_reason','created_at','updated_at'
  ];
  foreach ($maybe as $c) {
    if (column_exists($conn,'trade_orders',$c)) $cols[] = $c;
  }
  $selectCols = implode(',', array_unique($cols));

  /* ================= Step 1: read open orders (pending) for sync ================= */
  $where = "user_id=:uid";
  $params = [':uid'=>$userId];

  if ($symbol !== '' && column_exists($conn,'trade_orders','symbol')) {
    $where .= " AND symbol=:sym";
    $params[':sym'] = $symbol;
  }

  // status pending
  if (!column_exists($conn,'trade_orders','status')) {
    // لو جدولك لا يحتوي status لن نستطيع تحديد open orders
    respond(false, 'جدول trade_orders لا يحتوي عمود status.', [], 500);
  }
  $where .= " AND status='pending'";

  // ترتيب: الأقدم أولاً
  $orderBy = (column_exists($conn,'trade_orders','updated_at') ? "updated_at ASC" :
             (column_exists($conn,'trade_orders','created_at') ? "created_at ASC" : "id ASC"));

  $sqlOpenForSync = "SELECT {$selectCols} FROM trade_orders WHERE {$where} ORDER BY {$orderBy} LIMIT {$maxSync}";
  $st = $conn->prepare($sqlOpenForSync);
  $st->execute($params);
  $openForSync = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];

  /* ================= Step 2: load provider + sync each pending order ================= */
  $syncSummary = [
    'attempted' => count($openForSync),
    'processed' => 0,
    'completed_now' => 0,
    'canceled_now' => 0,
    'skipped' => 0,
    'errors' => []
  ];

  $loadedProviderId = 0;
  $loadedBindingFile = '';

  if (count($openForSync) > 0) {
    // نحتاج مزود فعّال واحد على الأقل
    foreach ($openForSync as $o) {
      $tradeOrderId = (int)($o['id'] ?? 0);
      if ($tradeOrderId <= 0) { $syncSummary['skipped']++; continue; }

      $pid = (int)($o['provider_id'] ?? 0);

      // إذا provider_id غير موجود نختار أول مزود فعّال (احتياطي)
      if ($pid <= 0) {
        $stP0 = $conn->query("SELECT id FROM providers WHERE is_active=1 AND binding_file IS NOT NULL AND binding_file<>'' ORDER BY id ASC LIMIT 1");
        $pid = (int)($stP0 ? $stP0->fetchColumn() : 0);
      }
      if ($pid <= 0) { $syncSummary['skipped']++; continue; }

      // تحميل ملف المزود مرة واحدة (لتجنب تعارض provider_execute)
      if ($loadedProviderId === 0) {
        $stPr = $conn->prepare("SELECT id, binding_file FROM providers WHERE id=:id AND is_active=1 LIMIT 1");
        $stPr->execute([':id'=>$pid]);
        $prow = $stPr->fetch(PDO::FETCH_ASSOC);

        $bindingFile = $prow ? safe_binding_file((string)($prow['binding_file'] ?? '')) : '';
        if ($bindingFile === '') {
          $syncSummary['skipped']++;
          continue;
        }

        $providerPath = __DIR__ . '/providers/' . $bindingFile;
        if (!is_file($providerPath)) {
          $syncSummary['skipped']++;
          continue;
        }

        define('EAZZYBIT_INTERNAL_CALL', 1);
        require_once $providerPath;

        if (!function_exists('provider_execute')) {
          respond(false, 'ملف المزود لا يحتوي الدالة provider_execute().', ['binding_file'=>$bindingFile], 500);
        }

        $loadedProviderId = $pid;
        $loadedBindingFile = $bindingFile;
      }

      // إذا ظهر provider مختلف عن الذي حمّلناه، نتجاوزه لتفادي تعارض أسماء الدوال
      if ($pid !== $loadedProviderId) {
        $syncSummary['skipped']++;
        continue;
      }

      // نفّذ مزامنة الطلب
      try {
        $uiMode = (string)($o['ui_order_mode'] ?? '');
        $res = provider_execute($conn, [
          'trade_order_id' => $tradeOrderId,
          'provider_id'    => $pid,
          'ui_order_mode'  => $uiMode
        ]);

        $syncSummary['processed']++;

        $stAfter = $conn->prepare("SELECT status FROM trade_orders WHERE id=:id LIMIT 1");
        $stAfter->execute([':id'=>$tradeOrderId]);
        $newStatus = (string)($stAfter->fetchColumn() ?: '');

        if ($newStatus === 'completed') $syncSummary['completed_now']++;
        elseif ($newStatus === 'canceled') $syncSummary['canceled_now']++;

      } catch (Throwable $e) {
        $syncSummary['errors'][] = [
          'trade_order_id' => $tradeOrderId,
          'error' => ($DEBUG_MODE ? $e->getMessage() : 'sync_failed')
        ];
      }
    }
  }

  /* ================= Step 3: fetch open orders again (after sync) ================= */
  $sqlFinal = "SELECT {$selectCols} FROM trade_orders WHERE {$where} ORDER BY {$orderBy}";
  $st2 = $conn->prepare($sqlFinal);
  $st2->execute($params);
  $openOrders = $st2->fetchAll(PDO::FETCH_ASSOC) ?: [];

  respond(true, 'ok', [
    'symbol' => $symbol,
    'provider_loaded' => [
      'provider_id' => $loadedProviderId,
      'binding_file' => $loadedBindingFile
    ],
    'sync_summary' => $syncSummary,
    'count' => count($openOrders),
    'open_orders' => $openOrders
  ]);

} catch (Throwable $e) {
  $msg = 'خطأ في الخادم';
  if (!empty($GLOBALS['DEBUG_MODE'])) $msg .= ' - ' . $e->getMessage();
  respond(false, $msg, [], 500);
}
