<?php
// ws-live-server.php (Ratchet)
// ✅ توثيق بالـ token من query: ?token=...
// ✅ يرسل تحديثات أسعار بصيغة: {symbol, price, change}

require __DIR__ . '/vendor/autoload.php';

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\Server\IoServer;

class LiveServer implements MessageComponentInterface {
  private \SplObjectStorage $clients;
  private PDO $conn;

  public function __construct(PDO $conn) {
    $this->clients = new \SplObjectStorage();
    $this->conn = $conn;
  }

  private function resolveUserIdByToken(string $token): int {
    $token = trim($token);
    if ($token === '') return 0;

    $st = $this->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'=>$token]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    return $row ? (int)$row['user_id'] : 0;
  }

  public function onOpen(ConnectionInterface $conn) {
    // token من query string
    $query = $conn->httpRequest->getUri()->getQuery(); // token=...
    parse_str($query, $q);

    $token = (string)($q['token'] ?? '');
    $uid = $this->resolveUserIdByToken($token);

    if ($uid <= 0) {
      $conn->send(json_encode(['type'=>'error','message'=>'unauthorized']));
      $conn->close();
      return;
    }

    // خزّن بيانات العميل
    $conn->uid = $uid;
    $conn->subs = []; // رموز مشترك بها
    $this->clients->attach($conn);

    $conn->send(json_encode(['type'=>'hello','user_id'=>$uid]));
  }

  public function onMessage(ConnectionInterface $from, $msg) {
    $data = json_decode($msg, true);
    if (!is_array($data)) return;

    $type = (string)($data['type'] ?? '');

    if ($type === 'subscribe') {
      $symbols = $data['symbols'] ?? [];
      if (is_array($symbols)) {
        $from->subs = array_values(array_unique(array_map('strtoupper', $symbols)));
        $from->send(json_encode(['type'=>'subscribed','count'=>count($from->subs)]));
      }
      return;
    }

    if ($type === 'ping') {
      $from->send(json_encode(['type'=>'pong','ts'=>time()]));
      return;
    }
  }

  public function onClose(ConnectionInterface $conn) {
    if ($this->clients->contains($conn)) $this->clients->detach($conn);
  }

  public function onError(ConnectionInterface $conn, \Exception $e) {
    $conn->close();
  }

  // بث تحديث سعري (تستدعيها من loop خارجي)
  public function broadcastTick(array $tick): void {
    $sym = strtoupper((string)($tick['symbol'] ?? ''));
    if ($sym === '') return;

    foreach ($this->clients as $client) {
      $subs = $client->subs ?? [];
      if (empty($subs) || in_array($sym, $subs, true)) {
        $client->send(json_encode($tick, JSON_UNESCAPED_SLASHES));
      }
    }
  }
}

/* ===== DB (PDO) ===== */
require_once __DIR__ . '/../config.php'; // عدّل المسار
if (!isset($conn) || !($conn instanceof PDO)) {
  echo "DB missing\n";
  exit(1);
}

$live = new LiveServer($conn);

/* ===== Server ===== */
$server = IoServer::factory(
  new HttpServer(new WsServer($live)),
  8080 // غيّر البورت
);

/* ===== مثال Loop لإرسال أسعار (استبدله بمصدر أسعار حقيقي) ===== */
$loop = $server->loop;
$loop->addPeriodicTimer(1.0, function() use ($live) {
  // مثال: tick تجريبي
  $live->broadcastTick([
    'symbol' => 'BTCUSDT',
    'price'  => 43000.12,
    'change' => 0.42
  ]);
});

$server->run();
