<?php
require_once 'db.php';
require 'vendor/autoload.php';

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
use React\Socket\SocketServer;
use React\Http\HttpServer as ReactHttpServer;
use React\Http\Message\Response;
use Psr\Http\Message\ServerRequestInterface;

class BillboardSocket implements \Ratchet\MessageComponentInterface {
    protected $clients;
    protected $billboards;
    protected $pdo;
    
    public function __construct() {
        $this->clients = new \SplObjectStorage;
        $this->billboards = [];
        
        global $pdo;
        $this->pdo = $pdo;
    }
    
    public function onOpen(\Ratchet\ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }
    
    public function onMessage(\Ratchet\ConnectionInterface $from, $msg) {
        $data = json_decode($msg, true);
        
        if (isset($data['type'])) {
            switch ($data['type']) {
                case 'register':
                    if (isset($data['serial'])) {
                        $this->billboards[$from->resourceId] = $data['serial'];
                        echo "Billboard registered: {$data['serial']} ({$from->resourceId})\n";
                        
                        $stmt = $this->pdo->prepare("UPDATE `imators-systems-billboard` SET last_seen = NOW() WHERE serial = ?");
                        $stmt->execute([$data['serial']]);
                        
                        $stmt = $this->pdo->prepare("SELECT status, stop_message FROM `imators-systems-billboard` WHERE serial = ?");
                        $stmt->execute([$data['serial']]);
                        $billboard = $stmt->fetch();
                        
                        if ($billboard && $billboard['status'] === 'stopped') {
                            $from->send(json_encode([
                                'type' => 'status_update',
                                'serial' => $data['serial'],
                                'status' => 'stopped',
                                'message' => $billboard['stop_message']
                            ]));
                        }
                    }
                    break;
                
                case 'heartbeat':
                    if (isset($data['serial'])) {
                        $stmt = $this->pdo->prepare("UPDATE `imators-systems-billboard` SET last_seen = NOW() WHERE serial = ?");
                        $stmt->execute([$data['serial']]);
                    }
                    break;
                    
                case 'admin_command':
                    if (isset($data['serial']) && isset($data['action'])) {
                        if ($data['action'] === 'stop' && isset($data['message'])) {
                            $stmt = $this->pdo->prepare("UPDATE `imators-systems-billboard` SET status = 'stopped', stop_message = ? WHERE serial = ?");
                            $stmt->execute([$data['message'], $data['serial']]);
                            $this->broadcastStatus($data['serial'], 'stopped', $data['message']);
                        } else if ($data['action'] === 'restart') {
                            $stmt = $this->pdo->prepare("UPDATE `imators-systems-billboard` SET status = 'active', stop_message = NULL WHERE serial = ?");
                            $stmt->execute([$data['serial']]);
                            $this->broadcastStatus($data['serial'], 'active');
                        }
                    }
                    break;
            }
        }
    }
    
    public function onClose(\Ratchet\ConnectionInterface $conn) {
        $this->clients->detach($conn);
        if (isset($this->billboards[$conn->resourceId])) {
            echo "Billboard disconnected: {$this->billboards[$conn->resourceId]} ({$conn->resourceId})\n";
            unset($this->billboards[$conn->resourceId]);
        }
    }
    
    public function onError(\Ratchet\ConnectionInterface $conn, \Exception $e) {
        echo "Error: {$e->getMessage()}\n";
        $conn->close();
    }
    
    public function broadcastStatus($serial, $status, $message = null) {
        foreach ($this->clients as $client) {
            $clientSerial = $this->billboards[$client->resourceId] ?? null;
            
            if ($clientSerial === $serial) {
                $client->send(json_encode([
                    'type' => 'status_update',
                    'serial' => $serial,
                    'status' => $status,
                    'message' => $message
                ]));
                
                echo "Status broadcast to $serial: $status\n";
            }
        }
    }
}

if (php_sapi_name() === 'cli') {
    $loop = Factory::create();
    $socket = new BillboardSocket();
    
    $server = IoServer::factory(
        new HttpServer(
            new WsServer($socket)
        ),
        8080
    );
    
    $http = new ReactHttpServer(
        $loop,
        function (ServerRequestInterface $request) use ($socket) {
            $path = $request->getUri()->getPath();
            
            if ($path === '/broadcast.php') {
                $query = $request->getQueryParams();
                
                if (isset($query['serial']) && isset($query['status'])) {
                    $socket->broadcastStatus(
                        $query['serial'],
                        $query['status'],
                        $query['message'] ?? null
                    );
                    
                    return new Response(
                        200,
                        ['Content-Type' => 'application/json'],
                        json_encode(['status' => 'success'])
                    );
                }
            }
            
            return new Response(
                404,
                ['Content-Type' => 'text/plain'],
                'Not found'
            );
        }
    );
    
    $httpSocket = new SocketServer('0.0.0.0:8081', [], $loop);
    $http->listen($httpSocket);
    
    echo "WebSocket server running on port 8080\n";
    echo "HTTP broadcast endpoint running on port 8081\n";
    
    $server->run();
} else {
    header('Content-Type: application/json');
    echo json_encode(['error' => 'This script should be run from command line']);
}