<?php

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

error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING);

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

class Chat implements MessageComponentInterface {

    /**
     * @var SplObjectStorage
     */
    protected $clients;

    /**
     * @var array
     */
    protected $users;

    /**
     * @var Medoo
     */
    protected $db;

    protected $dispatcher;
    protected $groupChatClients;
    protected $globalLang = [];
    protected $ws_config = [];


    public function __construct($ws_config) {
        error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);

        $this->ws_config = $ws_config;
        $this->db = new Medoo($ws_config["db_config"]);
        $this->clients = new \SplObjectStorage;
        $this->users = [];

        require_once('./engine/data/config.php');
        require_once('./engine/eventSubscribers/Events/EventDispatcher.php');

        define('ENGINE_DIR', './engine');

        // Создаем подписчик событий
        $this->dispatcher = new EventDispatcher($config, $this->db);
        $dispatcher = $this->dispatcher;
        require_once('./engine/mods/event_subscribers.php');

    }



    public function onOpen(ConnectionInterface $conn) {
        $this->db = new Medoo($this->ws_config["db_config"]);
        parse_str($conn->httpRequest->getUri()->getQuery(), $query);
        $token = $query['usr_token'] ?? null;
        if (empty($token)) {
            $this->log_message("Подключение... токен отсутсвует\n");
        } else {
            $this->log_message("Подключение... токен $token \n");


            $userId = $this->authenticateUser($token);

            if ($userId) {
                $this->updateUserStatus($userId, "online");

                $conn->userId = $userId;
                $this->users[$userId] = $conn;
                $this->clients->attach($conn);

                $this->log_message("[{$userId}] Подключен\n");

            } else {
                $conn->close();
            }
        }

    }

    private function updateUserStatus($user_id, $status) {
        // Обновление статуса в базе данных
        $this->db->update("users", ["status" => $status, "lastdate" => date("Y-m-d H:i:s")], ["id" => $user_id]);
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        date_default_timezone_set('UTC');
        $this->db = new Medoo($this->ws_config["db_config"]);


        if (!empty($from->userId)) {

            $messageData = json_decode($msg, true);
            $string = $messageData['message'] ?? null;

            if ($messageData["type"] == "register-group-chat" && !empty($messageData["group_id"])) {
                $connectionUserId = $this->db->get("tokens", "user_id", ["token" => $messageData["usr_token"]]) ?? null;
                $this->groupChatClients[$messageData["group_id"]][$connectionUserId] = $connectionUserId;
                $this->users[$from->userId . "_group_chat"] = $from;

                $response = [
                    "type" => "live-chat",
                    "action" => "online-count",
                    "count" => count($this->groupChatClients[$messageData["group_id"]])
                ];

                foreach ($this->groupChatClients as $groupId => $chatClients) {
                    if ($groupId == $messageData["group_id"]) {
                        foreach ($chatClients as $chatClientID) {
                            $recipientConn = $this->users[$chatClientID . "_group_chat"];

                            $recipientConn->send(json_encode($response));

                        }
                    }
                }

            } else if ($messageData["type"] === "register") {
                $this->users[$from->userId . "_pm"] = $from;
            }

            $message = [];
            $insertPath = "";
            if (!empty($messageData["from_user_token"])) {
                $response = [];
                $senderId = $this->db->get("tokens", "user_id", ["token" => $messageData["from_user_token"]]) ?? null;

                if ($messageData["type"] == "chat") {

                    if ($messageData["action"] == "message") {

                        $folder = "";
                        $savePath = "";
                        if (!empty($messageData['file'])) {
                            echo "FILE YEST";
                            $file = $messageData['file'];
                            $folder = $file['is_image'] ? 'images' : 'files';
                            $ext = pathinfo($file['filename'], PATHINFO_EXTENSION);
                            $savePath = __DIR__ . "/uploads/$folder/" . uniqid() . '.' . $ext;

                            $insertPath = "engine/websockets/uploads/$folder/" . basename($savePath);
                            file_put_contents($savePath, base64_decode($file['content']));
                        }

                        $insertData = [
                            "sender_id" => $senderId,
                            "receiver_id" => $messageData['to_user_id'],
                            "message" => $string,
                        ];

                        if ($folder === "images") {
                            $insertData["img_path"] = $insertPath;
                        } else if ($folder === "files") {
                            $insertData["file_path"] = $insertPath;
                        }


                        $this->db->insert("messages", $insertData);
                        echo "MESSAGE: $string : SUCCESS INSERT \n";


                        $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? [];

                        if (empty($message)) {
                            echo "ERROR: message data empty\n";
                        }

                        $response = [
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'my_message' => true,
                            'messageData' => $message,
                        ];

                        if ($savePath && $folder && !empty($file)) {
                            $response['file_url'] = "engine/websockets/uploads/$folder/" . basename($savePath);
                            $response["file_type"] = $folder;
                            $response["file_name"] = $file["filename"];
                            $response["text"] = "Sent file {$file['filename']}";
                        }

                        $this->sendNotification(
                            $from,
                            $messageData["to_user_id"],
                            "/pm&uid={$from->userId}",
                            "%%you_receive_message_from%% {$response['sender_name']}: " . $messageData["message"],
                            "_pm",
                            "pm",
                            'message-receive.svg',
                        );

                        if (!empty($this->users[$from->userId . "_pm"])) {
                            $recipientConn = $this->users[$from->userId . "_pm"];

                            $recipientConn->send(json_encode($response));
                        }

                        $this->log_message("MESSAGE: $string : SUCCESS INSERT \n");
                    } else if ($messageData["action"] == "messageEdit") {

                        if (!empty($messageData["messageId"])) {
                            $this->db->update("messages", [
                                "message" => $messageData["message"],
                                "updated_at" => date("Y-m-d H:i:s"),
                            ], ["id" => $messageData["messageId"]]);
                        }

                        $message = $this->db->get("messages", "*", ["id" => $messageData["messageId"]]) ?? [];

                        $recipientConn = $this->users[$from->userId . "_pm"];

                        $recipientConn->send(json_encode([
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'my_message' => true,
                            'messageData' => $message,
                        ]));

                        echo "MESSAGE: {$messageData["message"]} : SUCCESS UPDATED \n";

                    } else if ($messageData["action"] == "messageDelete") {
                        // $this->db->update("messages", ["del_for" => $from->userId] ,["id" => $messageData["messageId"]]);

                        $this->db->insert("chat_deletions", ["user_id" => $from->userId, "chat_id" => $messageData["messageId"], "deleted_at" => date("Y-m-d H:i:s")]);
                        echo "MESSAGE: {$messageData["messageId"]} : SUCCESS DELETED \n";

                        $recipientConn = $this->users[$messageData["to_user_id"] . "_pm"];
                        $message = $this->db->get("messages", "*", ["id" => $messageData["messageId"]]) ?? [];

                        $recipientConn->send(json_encode([
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'my_message' => false,
                            'messageData' => $message,
                        ]));
                    } else if ($messageData["action"] == "messageReply") {

                        $this->db->insert("messages", [
                            "sender_id" => $senderId,
                            "receiver_id" => $messageData['to_user_id'],
                            "message" => $string,
                            "reply_to_id" => $messageData['messageId'],
                        ]);

                        echo "MESSAGE: $string : SUCCESS REPLIED \n";

                        $recipientConn = $this->users[$from->userId . "_pm"];
                        $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? [];
                        $message["repliedMessage"] = $this->db->get("messages", "*", ["id" => $message["reply_to_id"]]) ?? [];

                        $recipientConn->send(json_encode([
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'my_message' => true,
                            'messageData' => $message,
                        ]));

                    } else if ($messageData["action"] == "removeChatHistory") {


                        // $allMessages = $this->db->select("messages", "*", ["sender_id" => $messageData["messageId"]]) ?? [];

                        $allMessages = $this->db->select("messages",
                            "*",
                            [
                                "AND" => [
                                    "OR" => [
                                        "AND" => [
                                            "sender_id" => $from->userId,
                                            "receiver_id" => $messageData["to_user_id"],
                                        ],
                                        "AND #2" => [
                                            "sender_id" => $messageData["to_user_id"],
                                            "receiver_id" => $from->userId,
                                        ],
                                    ]
                                ]
                            ]);

                        foreach ($allMessages as $messageAssoc) {
                            $existsDeletion = $this->db->get("chat_deletions", "*", ["user_id" => $from->userId, "chat_id" => $messageAssoc["id"]]);

                            if (empty($existsDeletion)) {
                                $this->db->insert("chat_deletions", ["user_id" => $from->userId, "chat_id" => $messageAssoc["id"], "deleted_at" => date("Y-m-d H:i:s")]);
                            }
                        }


                        echo "MESSAGE: : SUCCESS HISTORY REMOVED \n";
                    }


                } else if ($messageData["type"] == "live-chat") {

                    if ($messageData["action"] === "message") {

                        $folder = "";
                        $savePath = "";
                        if (!empty($messageData['file'])) {
                            echo "FILE YEST";
                            $file = $messageData['file'];
                            $folder = $file['is_image'] ? 'images' : 'files';
                            $ext = pathinfo($file['filename'], PATHINFO_EXTENSION);
                            $savePath = __DIR__ . "/uploads/$folder/" . uniqid() . '.' . $ext;

                            $insertPath = "engine/websockets/uploads/$folder/" . basename($savePath);
                            file_put_contents($savePath, base64_decode($file['content']));
                        }

                        $insertData = [
                            "group_id" => $messageData["to_group_id"],
                            "sender_id" => $from->userId,
                            "content" => $messageData["message"],
                            "message_type" => $messageData["action"],
                            "created_at" => date("Y-m-d H:i:s")
                        ];

                        if ($folder === "images") {
                            $insertData["img_path"] = $insertPath;
                        } else if ($folder === "files") {
                            $insertData["file_path"] = $insertPath;
                        }


                        $this->db->insert("group_messages", $insertData);

                        $message = $this->db->get("group_messages", "*", ["id" => $this->db->id()]) ?? [];

                        $response = [
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'group_id' => $messageData["to_group_id"],
                            'messageData' => $message,
                        ];

                        if ($savePath && $folder && !empty($file)) {
                            $response['file_url'] = "engine/websockets/uploads/$folder/" . basename($savePath);
                            $response["file_type"] = $folder;
                            $response["file_name"] = $file["filename"];
                            $response["text"] = "Sent file {$file['filename']}";
                        }

                        $this->sendToGroupChat($messageData, $response);

                    } else if ($messageData["action"] === "messageEdit") {

                        if (!empty($messageData["messageId"])) {

                            $this->db->update("group_messages",
                                ["content" => $messageData["message"], "updated_at" => date("Y-m-d H:i:s")],
                                ["id" => $messageData["messageId"]]
                            );

                            $message = $this->db->get("group_messages", "*", ["id" => $messageData["messageId"]]) ?? [];

                            $response = [
                                'type' => $messageData["type"],
                                'sender_id' => $from->userId,
                                'sender_name' => $this->getUserName($from->userId),
                                'sender_avatar' => $this->getUserAvatar($from->userId),
                                'text' => $messageData['message'],
                                'time' => date("Y-m-d H:i:s"),
                                'action' => $messageData["action"],
                                'group_id' => $messageData["to_group_id"],
                                'messageData' => $message,
                            ];

                            $this->sendToGroupChat($messageData, $response);

                        }

                    } else if ($messageData["action"] === "messageReply") {


                        if (!empty($messageData["reply_to_id"])) {

                            $this->db->insert("group_messages", [
                                "group_id" => $messageData["to_group_id"],
                                "sender_id" => $from->userId,
                                "content" => $messageData["message"],
                                "message_type" => $messageData["action"],
                                "created_at" => date("Y-m-d H:i:s"),
                                "reply_to_id" => $messageData["reply_to_id"],
                            ]);

                            $message = $this->db->get("group_messages", "*", ["id" => $this->db->id()]) ?? [];
                            $message["repliedMessage"] = $this->db->get("group_messages", "*", ["id" => $message["reply_to_id"]]) ?? [];

                            $response = [
                                'type' => $messageData["type"],
                                'sender_id' => $from->userId,
                                'sender_name' => $this->getUserName($from->userId),
                                'sender_avatar' => $this->getUserAvatar($from->userId),
                                'text' => $messageData['message'],
                                'time' => date("Y-m-d H:i:s"),
                                'action' => $messageData["action"],
                                'group_id' => $messageData["to_group_id"],
                                'messageData' => $message,
                            ];


                            $this->sendToGroupChat($messageData, $response);

                            $this->sendNotification(
                                $from,
                                $message["repliedMessage"]["sender_id"],
                                "/chat#m-" . $message["id"],
                                "%%your_message_replied%% {$response['sender_name']}: " . $messageData["message"],
                                "_group_chat",
                                "group_chat_reply",
                                'reply-receive.svg',
                            );


                        }


                    } else if ($messageData["action"] === "messageDelete") {

                        if (!empty($messageData["messageId"])) {
                            $deletedMessage = $this->db->get("group_messages", "*", ["id" => $messageData["messageId"]]) ?? [];

                            if ($messageData["deleteType"] === "delete_everyone") {

                                $this->db->delete("group_messages", ["id" => $messageData["messageId"]]);

                                if (!empty($deletedMessage["file_path"])) {
                                    unlink($deletedMessage["file_path"]);
                                } else if (!empty($deletedMessage["img_path"])) {
                                    unlink($deletedMessage["img_path"]);
                                }

                                $response = [
                                    'type' => $messageData["type"],
                                    'sender_id' => $from->userId,
                                    'sender_name' => $this->getUserName($from->userId),
                                    'sender_avatar' => $this->getUserAvatar($from->userId),
                                    'text' => $messageData['message'],
                                    'time' => date("Y-m-d H:i:s"),
                                    'action' => $messageData["action"] . "Everyone",
                                    'group_id' => $messageData["to_group_id"],
                                    'messageData' => $deletedMessage,
                                ];


                                $this->sendToGroupChat($messageData, $response);

                            } else if ($messageData["deleteType"] === "delete") {

                                $this->db->insert("chat_deletions", [
                                    "chat_id" => $messageData["messageId"],
                                    "user_id" => $from->userId,
                                    "deleted_at" => date("Y-m-d H:i:s"),
                                    "chat_type" => "live-chat"
                                ]);


                                $response = [
                                    'type' => $messageData["type"],
                                    'sender_id' => $from->userId,
                                    'sender_name' => $this->getUserName($from->userId),
                                    'sender_avatar' => $this->getUserAvatar($from->userId),
                                    'text' => $messageData['message'],
                                    'time' => date("Y-m-d H:i:s"),
                                    'action' => $messageData["action"],
                                    'group_id' => $messageData["to_group_id"],
                                    'messageData' => $deletedMessage,
                                ];


                                $this->sendToGroupChat($messageData, $response);


                            }

                        }

                    } else if ($messageData["action"] === "typing") {


                        $response = [
                            'type' => $messageData["type"],
                            'sender_id' => $from->userId,
                            'sender_name' => $this->getUserName($from->userId),
                            'sender_avatar' => $this->getUserAvatar($from->userId),
                            'text' => $messageData['message'],
                            'time' => date("Y-m-d H:i:s"),
                            'action' => $messageData["action"],
                            'group_id' => $messageData["to_group_id"],
                            'messageData' => [],
                        ];


                        foreach ($this->groupChatClients as $groupId => $chatClients) {
                            if ($groupId == $messageData["to_group_id"]) {
                                foreach ($chatClients as $chatClientID) {
                                    $recipientConn = $this->users[$chatClientID . "_group_chat"];
                                    $response["receiver_id"] = $chatClientID;

                                    $recipientConn->send(json_encode($response));

                                }
                            }
                        }

                    }

                } else if ($messageData["type"] === "notification") {
                    if ($messageData["action"] === "connect") {
                        $this->globalLang = $messageData["globalLang"];
                        $this->users[$from->userId . "_notification"] = $from;
                        $recipientConn = $this->users[$from->userId . "_notification"];
                        $notifications = $this->db->select("notifications", "*", ["user_id" => $from->userId]) ?? null;

                        $notifications = array_reverse($notifications);

                        foreach ($notifications as &$notification) {
                            $notification["content"] = preg_replace_callback('/%%(.*?)%%/', function ($matches) {
                                $map = $this->globalLang;
                                return $map[$matches[1]] ?? $matches[0]; // если не найдено — оставить как есть
                            }, $notification["content"]);


                            $notification["senderData"] = $this->db->get("users", "*", ["id" => $notification["sender_id"] ?? 0]) ?? null;


                        }
                        unset($notification);

                        $recipientConn->send(json_encode([
                            'type' => $messageData["type"],
                            'action' => $messageData["action"],
                            'notifications' => $notifications,
                        ]));

                    } else if ($messageData["action"] === "send") {

                        if (!empty($messageData["user_id"])) {

                            $this->db->insert("notifications", [
                                "user_id" => $messageData["user_id"],
                                "sender_id" => $from->userId,
                                "module_id" => 0,
                                "module_type" => $messageData["module_type"],
                                "language" => "RU",
                                "created_at" => date("Y-m-d H:i:s"),
                                "content" => $messageData["content"],
                                "status" => 0,
                            ]);

                            $recipientConn = $this->users[$messageData["user_id"] . "_notification"];
                            $notifications = $this->db->select("notifications", "*", ["user_id" => $messageData["user_id"]]) ?? null;

                            $notifications = array_reverse($notifications);

                            foreach ($notifications as &$notification) {
                                $notification["content"] = preg_replace_callback('/%%(.*?)%%/', function ($matches) {
                                    $map = $this->globalLang;
                                    return $map[$matches[1]] ?? $matches[0]; // если не найдено — оставить как есть
                                }, $notification["content"]);

                            }
                            unset($notification);

                            $recipientConn->send(json_encode([
                                'type' => $messageData["type"],
                                'action' => $messageData["action"],
                                'notifications' => $notifications,
                            ]));

                        }

                    }
                } else if ($messageData["type"] === "support") {

                    if ($messageData["action"] === "connect") {
                        // $this->globalLang = $messageData["globalLang"];
                        $supportList = [];
                        $supportOnlineCount = 0;
                        $groupId = $this->db->get("roles", "id", ["name" => "Support"]) ?? null;

                        $connectedUser = $this->db->get("users", "*", ["id" => $from->userId]) ?? null;

                        if ($connectedUser) {
                            $recipientConn = null;
                            $this->users[$from->userId . "_support"]["conn"] = $from;

                            if ($connectedUser["group"] != $groupId) {
                                $this->users[$from->userId . "_support"]["type"] = "user";
                            } else {
                                $this->users[$from->userId . "_support"]["type"] = "support";
                            }

                            $recipientConn = $this->users[$from->userId . "_support"]["conn"];

                            if ($this->users[$from->userId . "_support"]["type"] === "support") {

                                if (!empty($messageData["subAction"]) && $messageData["subAction"] === "acceptUserRequest") {
                                    $this->db->update("user_requests", [
                                        "request_owner_user_id" => $from->userId,
                                    ], ["id" => $messageData["requestId"]]);

                                    $userRequest = $this->db->get("user_requests", "*", ["id" => $messageData["requestId"]]) ?? null;

                                    $this->db->insert("user_relationships", [
                                        "user_id_from" => $from->userId,
                                        "user_id_to" => $userRequest["request_sender_user_id"],
                                        "is_support" => 1,
                                        "can_message" => 1,
                                    ]);

                                    $this->db->insert("user_relationships", [
                                        "user_id_from" => $userRequest["request_sender_user_id"],
                                        "user_id_to" => $from->userId,
                                        "is_support" => 1,
                                        "can_message" => 1,
                                    ]);

                                    $savedMessagesIds = json_decode($userRequest["request_options"], true);
                                    if (!empty($savedMessagesIds)) {
                                        $this->db->update("messages", [
                                            "receiver_id" => $from->userId,
                                        ], ["id" => $savedMessagesIds["messages_id"]]);
                                    }

                                }

                                $this->getUserRelationShipChat($chatsDataList, $chatUsers, $from);
                                $userRequests = $this->db->select("user_requests", "*", [
                                    "request_type" => "support_message",
                                    "request_owner_user_id" => 0,
                                ]);

                                foreach ($userRequests as &$userRequest) {
                                    $userRequest["user"] = $this->db->get("users", "*", ["id" => $userRequest["request_sender_user_id"]]) ?? null;
                                }

                                $recipientConn->send(json_encode([
                                    'type' => $messageData["type"],
                                    'action' => $messageData["action"],
                                    'supportList' => $supportList,
                                    'countOnlineSupport' => $supportOnlineCount,
                                    'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                    'chatDataList' => $chatsDataList,
                                    'userRequests' => $userRequests,
                                    'chatUsers' => $chatUsers ?? [],
                                ]));

                            } else {
                                if ($recipientConn) {
                                    if ($groupId) {
                                        $supportList = $this->db->select("users", "*", ["group" => $groupId]) ?? null;

                                        $supportOnlineCount = $this->db->count("users", ["group" => $groupId, "status" => "online"]) ?? 0;

                                    }

                                    $supportMessages = $this->db->select("messages", "*", [
                                        "AND" => [
                                            "OR" => [
                                                "AND" => [
                                                    "sender_id" => $from->userId,
                                                    "is_support" => 1,
                                                    "ticket_id" => null,
                                                ],
                                                "AND #2" => [
                                                    "is_support" => 1,
                                                    "receiver_id" => $from->userId,
                                                    "ticket_id" => null,
                                                ],
                                            ]
                                        ]]) ?? null;


                                    foreach ($supportMessages as &$supportMessage) {
                                        $senderName = $this->db->get("users", "name", ["id" => $supportMessage["sender_id"]]) ?? "USER";
                                        $senderNameShort = $this->getInitials($senderName);

                                        if ($supportMessage["sender_id"] == $from->userId) {
                                            $supportMessage["type"] = "me";
                                        } else {
                                            $supportMessage["type"] = "from";
                                            $supportMessage["sender_name_short"] = $senderNameShort;
                                            $supportMessage["sender_name"] = $senderName;
                                        }
                                    }


                                    $recipientConn->send(json_encode([
                                        'type' => $messageData["type"],
                                        'action' => $messageData["action"],
                                        'supportList' => $supportList,
                                        'countOnlineSupport' => $supportOnlineCount,
                                        'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                        'supportMessages' => $supportMessages,
                                    ]));
                                }
                            }

                        }

                    } else if ($messageData["action"] === "getUserChat") {

                        $this->getUserRelationShipChat($chatsDataList, $chatUsers, $from, $messageData["userId"]);
                        $recipientConn = $this->users[$from->userId . "_support"]["conn"];

                        $recipientConn->send(json_encode([
                            'type' => $messageData["type"],
                            'action' => $messageData["action"],
                            'chatDataList' => $chatsDataList,
                            'toUserId' => $messageData["userId"],
                        ]));

                    } else if ($messageData["action"] === "createTicket") {

                        if (!empty($messageData["data"])) {

                            $groupId = $this->db->get("roles", "id", ["name" => "Support"]) ?? null;

                            $supportList = $this->db->select("users", "*", ["group" => $groupId]) ?? null;


                            $this->db->insert("tickets", [
                                "title" => $messageData["data"]["title"],
                                "subject" => $messageData["data"]["subject"],
                                "priority" => $messageData["data"]["priority"],
                                "created_at" => date("Y-m-d H:i:s"),
                                "status" => "open",
                                "support_u_id" => $randomSupport["id"] ?? null,
                                "user_id" => $from->userId
                            ]);

                            $ticketId = $this->db->id();

                            $this->db->insert("user_requests", [
                                "request_sender_user_id" => $from->userId,
                                "request_type" => "ticket",
                                "request_id" => $ticketId,
                                "request_owner_user_id" => 0,
                                "request_options" => json_encode([])
                            ]);

                            $this->db->insert("messages", [
                                "sender_id" => $from->userId,
                                "receiver_id" => null,
                                "message" => $messageData["data"]["subject"],
                                "created_at" => date("Y-m-d H:i:s"),
                                "ticket_id" => $ticketId,
                                "is_support" => 1
                            ]);

                            foreach ($supportList as $support) {
                                $this->sendNotification(
                                    $from, $support["id"], "/admin?action=tickets#ticket-" . $ticketId, "%%user_create_ticket_text%% " . $this->getUserName($from->userId) . " ({$messageData["data"]["title"]})",
                                    "_notification", "user_create_ticket",
                                    'user_create_ticket.svg'
                                );

                            }

                            $this->sendNotification(
                                $from, $from->userId, "", "%%you_create_ticket_successfully%%",
                                "_notification", "system",
                                'user_create_ticket.svg'
                            );

                        }

                    } else if ($messageData["action"] === "sendMessage") {

                        $connectedUserType = $this->users[$from->userId . "_support"]["type"];

                        if ($connectedUserType === "user") {

                            $groupId = $this->db->get("groups", "id", ["name" => "Support"]) ?? null;
                            $supportList = $this->db->select("users", "*", ["group" => $groupId]) ?? null;

                            $relationshipsExists = $this->db->get("user_relationships", "*", [
                                "user_id_from" => $from->userId,
                                "is_support" => 1,
                                "can_message" => 1,
                            ]);

                            $selectedSupport = [];

                            if (!empty($relationshipsExists)) {

                                $selectedSupport = $this->db->get("users", "*", ["id" => $relationshipsExists["user_id_to"]]) ?? null;

                            }

                            if ($selectedSupport) {
                                $this->db->insert("messages", [
                                    "sender_id" => $from->userId,
                                    "receiver_id" => $selectedSupport["id"],
                                    "message" => $messageData["message"],
                                    "created_at" => date("Y-m-d H:i:s"),
                                    "is_support" => 1
                                ]);
                                $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? null;

                                if ($message["sender_id"] == $from->userId) {
                                    $message["type"] = "me";
                                } else {
                                    $message["type"] = "from";
                                }

                                $message["sender_name"] = $this->db->get("users", "name", ["id" => $message["sender_id"] ?? 0]) ?? null;

                                if (empty($this->users[$selectedSupport["id"] . "_support"])) {
                                    $this->sendNotification(
                                        $from, $selectedSupport["id"], "/admin?action=support-online-chat", "%%user_send_s_chat_message%% " . $this->getUserName($from->userId) . " ({$messageData["message"]})",
                                        "_support", "user_send_s_chat_message",
                                        'info-receive.svg'
                                    );
                                }


                                $recipientConnections = [$this->users[$from->userId . "_support"]["conn"], $this->users[$selectedSupport["id"] . "_support"]["conn"]];

                                foreach ($recipientConnections as $recipientConn) {
                                    if ($recipientConn) {
                                        $recipientConn->send(json_encode([
                                            'type' => $messageData["type"],
                                            'action' => $messageData["action"],
                                            'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                            'message' => $message,
                                            'selectedSupport' => $selectedSupport,
                                            'supportNameShort' => $this->getInitials($selectedSupport["name"] ?? "ADMIN"),
                                            'supportName' => $selectedSupport["name"] ?? "ADMIN",
                                            "toUserId" => $from->userId,
                                        ]));
                                    }
                                }


                            } else {
                                $this->db->insert("messages", [
                                    "sender_id" => $from->userId,
                                    "receiver_id" => null,
                                    "message" => $messageData["message"],
                                    "created_at" => date("Y-m-d H:i:s"),
                                    "is_support" => 1
                                ]);
                                $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? null;

                                if ($message["sender_id"] == $from->userId) {
                                    $message["type"] = "me";
                                } else {
                                    $message["type"] = "from";
                                }

                                $message["sender_name"] = $this->db->get("users", "name", ["id" => $message["sender_id"] ?? 0]) ?? null;

                                $existsRequest = $this->db->get("user_requests", "*", [
                                    "request_sender_user_id" => $from->userId,
                                    "request_type" => "support_message"
                                ]) ?? null;

                                if (!$existsRequest) {
                                    $this->db->insert("user_requests", [
                                        "request_sender_user_id" => $from->userId,
                                        "request_type" => "support_message",
                                        "request_id" => $this->db->id(),
                                        "request_owner_user_id" => 0,

                                        "request_options" => json_encode([
                                            "messages_id" => [$message["id"]],
                                        ])
                                    ]);


                                } else {
                                    $messagesId = json_decode($existsRequest["request_options"], true);
                                    $messagesId["messages_id"][] = $message["id"];
                                    $messagesId = json_encode($messagesId);

                                    $this->db->update("user_requests", [
                                        "request_options" => $messagesId
                                    ], [
                                        "request_sender_user_id" => $from->userId,
                                        "request_type" => "support_message"
                                    ]);
                                }

                                $recipientConn = $this->users[$from->userId . "_support"]["conn"];
                                if ($recipientConn) {
                                    $recipientConn->send(json_encode([
                                        'type' => $messageData["type"],
                                        'action' => $messageData["action"],
                                        'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                        'message' => $message,
                                        "toUserId" => $from->userId,
                                    ]));

                                    if (!$existsRequest) {
                                        $this->db->insert("messages", [
                                            "sender_id" => null,
                                            "receiver_id" => $from->userId,
                                            "message" => $this->globalLang["first_message_auto_answer"],
                                            "created_at" => date("Y-m-d H:i:s"),
                                            "is_support" => 1
                                        ]);
                                        $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? null;

                                        $recipientConn->send(json_encode([
                                            'type' => $messageData["type"],
                                            'action' => $messageData["action"],
                                            'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                            'message' => $message,
                                            "toUserId" => $from->userId,
                                        ]));
                                    }
                                }
                            }


                        } else {
                            $this->db->insert("messages", [
                                "sender_id" => $from->userId,
                                "receiver_id" => $messageData["to_user_id_sup"],
                                "message" => $messageData["message"],
                                "created_at" => date("Y-m-d H:i:s"),
                                "is_support" => 1
                            ]);
                            $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? null;

                            $recipientConnections = [$this->users[$from->userId . "_support"]["conn"] ?? null, $this->users[$messageData["to_user_id_sup"] . "_support"]["conn"] ?? null];
                            $selectedSupport = $this->db->get("users", "*", ["id" => $from->userId]) ?? [];
                            foreach ($recipientConnections as $recipientConn) {
                                if ($recipientConn) {
                                    $recipientConn->send(json_encode([
                                        'type' => $messageData["type"],
                                        'action' => $messageData["action"],
                                        'toUserId' => $messageData["to_user_id"] ?? null,
                                        'supportNameShort' => $this->getInitials($selectedSupport["name"] ?? "ADMIN"),
                                        'supportName' => $selectedSupport["name"] ?? "ADMIN",
                                        'connectedUserType' => $this->users[$from->userId . "_support"]["type"],
                                        'message' => $message,
                                    ]));
                                }
                            }

                        }

                    }

                } else if ($messageData["type"] === "ticket") {

                    if ($messageData["action"] === "connect") {

                        $this->users[$from->userId . "_ticket_conn"] = $from;

                    } else if ($messageData["action"] === "sendTicketMessage") {

                        if (!empty($messageData["ticketId"]) && !empty($messageData["message"])) {

                            $ticket = $this->db->get("tickets", "*", ["id" => $messageData["ticketId"]]) ?? null;
                            $group = $this->db->get("users", "group", ["id" => $from->userId]) ?? null;
                            $groupName = $this->db->get("groups", "name", ["id" => $group]) ?? null;

                            if ($ticket) {

                                $existsRequest = $this->db->get("user_requests", "*", [
                                    "request_sender_user_id" => $ticket["user_id"],
                                    "request_type" => "ticket",
                                    "request_id" => $ticket["id"],
                                ]);


                                if ($groupName === "Support" && $existsRequest || $groupName !== "Support" && $existsRequest["request_owner_user_id"] !== 0) {

                                    if ($groupName === "Support" && $existsRequest["request_owner_user_id"] === 0) {
                                        $this->db->update("user_requests", [
                                            "request_owner_user_id" => $from->userId,
                                        ], ["id" => $existsRequest["id"]]);


                                        $this->db->update("tickets", ["support_u_id" => $from->userId], ["id" => $ticket["id"]]);
                                        $ticket["support_u_id"] = $from->userId;
                                    }

                                    $this->db->insert("messages", [
                                        "sender_id" => $from->userId,
                                        "receiver_id" => $groupName === "Support" ? $ticket["user_id"] : $ticket["support_u_id"],
                                        "message" => $messageData["message"],
                                        "created_at" => date("Y-m-d H:i:s"),
                                        "ticket_id" => $ticket["id"],
                                        "is_support" => 1
                                    ]);

                                    $message = $this->db->get("messages", "*", ["id" => $this->db->id()]) ?? null;

                                    $recipientConnections = [
                                        $this->users[$ticket["user_id"] . "_ticket_conn"] ?? null,
                                        $this->users[$ticket["support_u_id"] . "_ticket_conn"] ?? null,
                                    ];

                                    foreach ($recipientConnections as $recipientConn) {
                                        if ($recipientConn) {
                                            $recipientConn->send(json_encode([
                                                'type' => $messageData["type"],
                                                'action' => $messageData["action"],
                                                'message' => $message,
                                                'ticketId' => $messageData["ticketId"],
                                                'senderId' => $from->userId,
                                                'from' => $groupName === "Support" ? "support" : "user",
                                            ]));
                                        } else {
                                            if ($groupName === "Support") {
                                                $this->sendNotification(
                                                    $from, $ticket["user_id"], "/myTickets#ticket-" . $messageData["ticketId"], "%%support_send_message_in_ticket%% " . $this->getUserName($from->userId) . " ({$messageData["message"]})",
                                                    "_notification", "support_send_message_in_ticket",
                                                    'user_create_ticket.svg'
                                                );
                                            } else {
                                                $this->sendNotification(
                                                    $from, $ticket["support_u_id"], "/admin?action=tickets#ticket-" . $messageData["ticketId"], "%%user_send_message_in_ticket%% " . $this->getUserName($from->userId) . " ({$messageData["message"]})",
                                                    "_notification", "user_send_message_in_ticket",
                                                    'user_create_ticket.svg'
                                                );
                                            }
                                        }
                                    }

                                }


                            }


                        }


                    } else if ($messageData["action"] === "closeTicket") {

                        if (!empty($messageData["ticketId"])) {

                            $this->db->update("tickets", [
                                "status" => "close"
                            ], ["id" => $messageData["ticketId"]]);

                            $ticket = $this->db->get("tickets", "*", ["id" => $messageData["ticketId"]]) ?? null;

                            $recipientConnections = [
                                $this->users[$ticket["user_id"] . "_ticket_conn"] ?? null,
                                $this->users[$ticket["support_u_id"] . "_ticket_conn"] ?? null,
                            ];

                            foreach ($recipientConnections as $recipientConn) {
                                if ($recipientConn) {
                                    $recipientConn->send(json_encode([
                                        'type' => $messageData["type"],
                                        'action' => $messageData["action"],
                                        'ticketId' => $messageData["ticketId"],
                                    ]));
                                } else {
                                    $this->sendNotification(
                                        $from, $ticket["user_id"], "/myTickets#ticket-" . $messageData["ticketId"], "%%ticket_closed%% " . $this->getUserName($from->userId) . " ({$ticket["title"]})",
                                        "_notification", "ticket_closed",
                                        'user_create_ticket.svg'
                                    );
                                }
                            }


                        }

                    }

                }


            }


            if (isset($messageData['to_user_id']) && isset($this->users[$messageData['to_user_id'] . "_pm"])) {
                $recipientConn = $this->users[$messageData['to_user_id'] . "_pm"];

                $recipientConn->send(json_encode([
                    'type' => $messageData["type"],
                    'sender_id' => $from->userId,
                    'sender_name' => $this->getUserName($from->userId),
                    'sender_avatar' => $this->getUserAvatar($from->userId),
                    'text' => $messageData['message'],
                    'time' => date("Y-m-d H:i:s"),
                    'action' => $messageData["action"],
                    'my_message' => false,
                    'messageData' => $message,
                    "file_url" => $insertPath,
                    "file_type" => $folder ?? null,
                    "file_name" => $file["filename"] ?? null,
                ]));
                $this->log_message("MESSAGE: $string : SUCCESS SENT WEBSOCKET \n");

            }
        }
    }

    function sendToGroupChat($messageData, &$response)
    {
        foreach ($this->groupChatClients as $groupId => $chatClients) {
            if ($groupId == $messageData["to_group_id"]) {
                foreach ($chatClients as $chatClientID) {
                    $recipientConn = $this->users[$chatClientID."_group_chat"];
                    $response["receiver_id"] = $chatClientID;

                    $recipientConn->send(json_encode($response));

                }
            }
        }
    }

    function getInitials($string) {
        // Находим первые буквы всех слов
        preg_match_all('/\b\p{L}/u', $string, $matches);

        // Объединяем и переводим в верхний регистр
        return mb_strtoupper(implode('', $matches[0]));
    }

    function sendNotification($from, $toUserId, $moduleUrl, $content, $prefix, $type ,$svg)
    {
        $this->db->insert("notifications", [
            "user_id" => $toUserId,
            "sender_id" => $from->userId,
            "module_id" => 0,
            "module_type" => $type,
            "language" => "RU",
            "created_at" => date("Y-m-d H:i:s"),
            "module_url" => $moduleUrl,
            "content" => $content,
            "status" => 0,
            "svg_ico" => $svg
        ]);

        if (!empty($this->users[$toUserId."_notification"])) {
            $recipientConn = $this->users[$toUserId."_notification"];
            $notifications = $this->db->select("notifications", "*", ["user_id" => $toUserId]) ?? null;

            $notifications = array_reverse($notifications);

            foreach ($notifications as &$notification) {
                $notification["content"] = preg_replace_callback('/%%(.*?)%%/', function ($matches) {
                    $map = $this->globalLang;
                    return $map[$matches[1]] ?? $matches[0]; // если не найдено — оставить как есть
                }, $notification["content"]);

            }
            unset($notification);

            $recipientConn->send(json_encode([
                'type' => "notification",
                'action' => "send",
                'notifications' => $notifications,
            ]));
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $user_id = $conn->userId;

        $this->updateUserStatus($user_id, "offline");

        unset($this->users[$user_id."_pm"]);
        unset($this->users[$user_id."_ticket_conn"]);

        if (!empty($this->groupChatClients)) {
            unset($this->groupChatClients[1][$user_id]);
            unset($this->users[$user_id."_group_chat"]);

            $response = [
                "type" => "live-chat",
                "action" => "online-count",
                "count" => count($this->groupChatClients[1])
            ];
            foreach ($this->groupChatClients as $groupId => $chatClients) {
                if ($groupId == 1) {
                    foreach ($chatClients as $chatClientID) {
                        $recipientConn = $this->users[$chatClientID."_group_chat"];

                        $recipientConn->send(json_encode($response));

                    }
                }
            }
        }


        $this->clients->detach($conn);
        $this->log_message("Подключение закрыто ({$conn->resourceId})\n");
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "Ошибка: {$e->getMessage()}\n";
        $conn->close();
    }

    private function canCommunicate($user1, $user2) {
        // Проверка в БД, например, что они друзья
        $stmt = $this->db->prepare("
        SELECT COUNT(*) 
        FROM friendships 
        WHERE (user_id = ? AND friend_id = ?)
           OR (user_id = ? AND friend_id = ?)
    ");
        $stmt->execute([$user1, $user2, $user2, $user1]);
        return $stmt->fetchColumn() > 0;
    }


    private function authenticateUser($token) {

        $userId = $this->db->get("tokens", "user_id", ["token" => $token]);

        if ($userId) {
            $validTokens = [];
            $validTokens[$token] = $userId;
        }

        return $validTokens[$token] ?? null;
    }

    private function getUserName($userId) {
        return $this->db->get("users", "name", ["id" => $userId]);
    }

    function log_message($message, $level = 'INFO') {
        $timestamp = date("Y-m-d H:i:s");
        $formatted_message = "[$timestamp] [$level] $message\n";

        file_put_contents('main.log', $formatted_message, FILE_APPEND);
    }

    private function getUserAvatar($userId) {
        return $this->db->get("users", "avatar", ["id" => $userId]);
    }

    private function getUserRelationShipChat(&$chatsDataList, &$chatUsers, $from, $userIdTo = null) {

        $chatsDataList = [];

        $selectCond = [
            "is_support" => 1,
            "can_message" => 1,
            "user_id_from" => $from->userId,
        ];

        if ($userIdTo) {
            $selectCond["user_id_to"] = $userIdTo;
        }

        $userRelationships = $this->db->select("user_relationships", "*", $selectCond);
        if ($userRelationships) {

            $userToIds = array_column($userRelationships, 'user_id_to');
            $chatUsers = $this->db->select("users", "*", ["id" => $userToIds]);

            foreach ($userRelationships as $key => $userRelationship) {
                $supportMessages = $this->db->select("messages", "*", [
                    "AND" => [
                        "OR" => [
                            "AND" => [
                                "sender_id" => $userRelationship["user_id_from"],
                                "receiver_id" => $userRelationship["user_id_to"],
                                "is_support" => 1,
                                "ticket_id" => null,
                            ],
                            "AND #2" => [
                                "is_support" => 1,
                                "sender_id" => $userRelationship["user_id_to"],
                                "receiver_id" => $userRelationship["user_id_from"],
                                "ticket_id" => null,
                            ],
                        ]
                    ],
                    "ORDER" => ["created_at" => "ASC"]
                ]) ?? null;

                $chatsDataList[$userRelationship["user_id_to"]] = [];

                // $supportMessages = array_reverse($supportMessages);

                foreach ($supportMessages as $mKey => $supportMessage) {


                    $chatsDataList[$userRelationship["user_id_to"]][$mKey]["from"] = $from->userId == $supportMessage["sender_id"] ? "user" : "them";
                    $chatsDataList[$userRelationship["user_id_to"]][$mKey]["name"] = $this->db->get("users", "name", ["id" => $supportMessage["sender_id"]]) ?? null;
                    $chatsDataList[$userRelationship["user_id_to"]][$mKey]["text"] = $supportMessage["message"];
                    $chatsDataList[$userRelationship["user_id_to"]][$mKey]["date"] = $supportMessage["created_at"];
                    $chatsDataList[$userRelationship["user_id_to"]][$mKey]["key"] = $userRelationship["user_id_to"];

                }

            }
        }




    }
}

require_once "./engine/data/ws_config.php";

// Запуск сервера
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat($ws_config)
        )
    ),
    8080,
    $ws_config["ip_address"],
);

echo "Сервер запущен на: ws://" . $ws_config["ip_address"] . ":8080\n";
$server->run();
?>

