<?php
/*******************************************************************************************************************
| Software Name        : EasyStream
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
| Software Author      : (c) Sami Ahmed
|*******************************************************************************************************************
|
|*******************************************************************************************************************
| This source file is subject to the EasyStream Proprietary License Agreement.
|
| By using this software, you acknowledge having read this Agreement and agree to be bound thereby.
|*******************************************************************************************************************
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|*******************************************************************************************************************/

defined('_ISVALID') or header('Location: /error');

/**
 * Live Chat Management Class
 *
 * Handles live chat functionality for streams including:
 * - Message sending and retrieval
 * - Moderation actions (timeout, ban)
 * - Super chat donations
 * - Chat replay
 */
class VLiveChat
{
    /**
     * Send a chat message
     *
     * @param string $stream_key Stream file key
     * @param string $message Message content
     * @param string $type Message type (chat, super_chat, system)
     * @param float $super_chat_amount Amount if super chat
     * @return array Result
     */
    public static function sendMessage($stream_key, $message, $type = 'chat', $super_chat_amount = null)
    {
        global $class_database, $cfg;

        $usr_id = isset($_SESSION['USER_ID']) ? (int) $_SESSION['USER_ID'] : 0;

        if ($usr_id == 0) {
            return ['success' => false, 'error' => 'Must be logged in to chat'];
        }

        // Check if chat is enabled
        $settings = self::getChatSettings($stream_key);
        if (!$settings['chat_enabled']) {
            return ['success' => false, 'error' => 'Chat is disabled for this stream'];
        }

        // Check if user is banned or timed out
        if (self::isUserBanned($stream_key, $usr_id)) {
            return ['success' => false, 'error' => 'You are banned from this chat'];
        }

        if (self::isUserTimedOut($stream_key, $usr_id)) {
            return ['success' => false, 'error' => 'You are timed out from this chat'];
        }

        // Validate message length
        $max_length = (int) ($cfg['live_chat_max_length'] ?? 500);
        if (strlen($message) > $max_length) {
            return ['success' => false, 'error' => "Message too long (max {$max_length} characters)"];
        }

        // Rate limiting
        $rate_limit = self::checkRateLimit($stream_key, $usr_id, $settings['slow_mode']);
        if (!$rate_limit['allowed']) {
            return ['success' => false, 'error' => $rate_limit['message']];
        }

        // Sanitize message
        $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');

        // Insert message
        $sql = "INSERT INTO `db_live_chat_messages`
                (`stream_key`, `usr_id`, `message`, `message_type`, `super_chat_amount`)
                VALUES ('%s', %d, '%s', '%s', %s)";

        $class_database->doQuery($sql,
            $stream_key,
            $usr_id,
            $message,
            $type,
            $super_chat_amount ? (float) $super_chat_amount : 'NULL'
        );

        $msg_id = $class_database->insert_id();

        return [
            'success' => true,
            'msg_id' => $msg_id,
            'message' => $message,
            'timestamp' => date('Y-m-d H:i:s')
        ];
    }

    /**
     * Get chat messages for a stream
     *
     * @param string $stream_key Stream file key
     * @param int $limit Number of messages
     * @param int $since_id Get messages after this ID
     * @return array Messages
     */
    public static function getMessages($stream_key, $limit = 50, $since_id = 0)
    {
        global $class_database;

        $since_clause = $since_id > 0 ? "AND m.msg_id > {$since_id}" : "";

        $sql = "SELECT
                    m.msg_id, m.message, m.message_type, m.super_chat_amount, m.timestamp,
                    u.usr_id, u.usr_user, u.usr_dname, u.usr_key, u.usr_partner, u.usr_affiliate
                FROM `db_live_chat_messages` m
                JOIN `db_accountuser` u ON m.usr_id = u.usr_id
                WHERE m.stream_key = '%s'
                    AND m.deleted = 0
                    {$since_clause}
                ORDER BY m.msg_id DESC
                LIMIT %d";

        $result = $class_database->doQuery($sql, $stream_key, $limit);

        $messages = [];
        while ($row = $result->fetch_assoc()) {
            $messages[] = [
                'msg_id' => $row['msg_id'],
                'user_id' => $row['usr_id'],
                'username' => $row['usr_user'],
                'display_name' => $row['usr_dname'],
                'user_key' => $row['usr_key'],
                'is_partner' => $row['usr_partner'] == 1,
                'is_affiliate' => $row['usr_affiliate'] == 1,
                'message' => $row['message'],
                'type' => $row['message_type'],
                'super_chat_amount' => $row['super_chat_amount'],
                'timestamp' => $row['timestamp'],
                'is_moderator' => self::isModerator($stream_key, $row['usr_id'])
            ];
        }

        return array_reverse($messages); // Return in chronological order
    }

    /**
     * Delete a message (moderation)
     *
     * @param int $msg_id Message ID
     * @param int $moderator_id Moderator user ID
     * @return bool Success
     */
    public static function deleteMessage($msg_id, $moderator_id)
    {
        global $class_database;

        $sql = "UPDATE `db_live_chat_messages`
                SET `deleted` = 1, `deleted_by` = %d
                WHERE `msg_id` = %d";

        $class_database->doQuery($sql, $moderator_id, $msg_id);

        return true;
    }

    /**
     * Timeout a user
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User to timeout
     * @param int $duration Duration in seconds
     * @param string $reason Reason
     * @param int $moderator_id Moderator user ID
     * @return bool Success
     */
    public static function timeoutUser($stream_key, $usr_id, $duration, $reason, $moderator_id)
    {
        global $class_database;

        $expires_at = date('Y-m-d H:i:s', time() + $duration);

        $sql = "INSERT INTO `db_live_chat_moderation`
                (`stream_key`, `usr_id`, `action`, `duration`, `reason`, `moderator_id`, `expires_at`)
                VALUES ('%s', %d, 'timeout', %d, '%s', %d, '%s')";

        $class_database->doQuery($sql,
            $stream_key,
            $usr_id,
            $duration,
            $reason,
            $moderator_id,
            $expires_at
        );

        return true;
    }

    /**
     * Ban a user from chat
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User to ban
     * @param string $reason Reason
     * @param int $moderator_id Moderator user ID
     * @return bool Success
     */
    public static function banUser($stream_key, $usr_id, $reason, $moderator_id)
    {
        global $class_database;

        $sql = "INSERT INTO `db_live_chat_moderation`
                (`stream_key`, `usr_id`, `action`, `reason`, `moderator_id`)
                VALUES ('%s', %d, 'ban', '%s', %d)";

        $class_database->doQuery($sql, $stream_key, $usr_id, $reason, $moderator_id);

        return true;
    }

    /**
     * Check if user is banned
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User ID
     * @return bool Is banned
     */
    public static function isUserBanned($stream_key, $usr_id)
    {
        global $class_database;

        $sql = "SELECT COUNT(*) as count FROM `db_live_chat_moderation`
                WHERE `stream_key` = '%s' AND `usr_id` = %d AND `action` = 'ban'
                ORDER BY `mod_id` DESC LIMIT 1";

        $result = $class_database->doQuery($sql, $stream_key, $usr_id);
        $row = $result->fetch_assoc();

        return $row['count'] > 0;
    }

    /**
     * Check if user is timed out
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User ID
     * @return bool Is timed out
     */
    public static function isUserTimedOut($stream_key, $usr_id)
    {
        global $class_database;

        $sql = "SELECT COUNT(*) as count FROM `db_live_chat_moderation`
                WHERE `stream_key` = '%s'
                    AND `usr_id` = %d
                    AND `action` = 'timeout'
                    AND `expires_at` > NOW()";

        $result = $class_database->doQuery($sql, $stream_key, $usr_id);
        $row = $result->fetch_assoc();

        return $row['count'] > 0;
    }

    /**
     * Check if user is a moderator
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User ID
     * @return bool Is moderator
     */
    public static function isModerator($stream_key, $usr_id)
    {
        global $class_database;

        $sql = "SELECT COUNT(*) as count FROM `db_live_chat_moderators`
                WHERE `stream_key` = '%s' AND `usr_id` = %d";

        $result = $class_database->doQuery($sql, $stream_key, $usr_id);
        $row = $result->fetch_assoc();

        return $row['count'] > 0;
    }

    /**
     * Get chat settings for stream
     *
     * @param string $stream_key Stream file key
     * @return array Settings
     */
    public static function getChatSettings($stream_key)
    {
        global $class_database;

        $sql = "SELECT * FROM `db_live_chat_settings` WHERE `stream_key` = '%s' LIMIT 1";
        $result = $class_database->doQuery($sql, $stream_key);
        $row = $result->fetch_assoc();

        if (!$row) {
            // Return defaults
            return [
                'chat_enabled' => 1,
                'slow_mode' => null,
                'subscriber_only' => 0,
                'follower_only' => 0,
                'emotes_enabled' => 1,
                'links_allowed' => 0
            ];
        }

        return $row;
    }

    /**
     * Check rate limit
     *
     * @param string $stream_key Stream file key
     * @param int $usr_id User ID
     * @param int $slow_mode Slow mode seconds
     * @return array Result
     */
    private static function checkRateLimit($stream_key, $usr_id, $slow_mode)
    {
        global $class_database, $cfg;

        $rate_limit = max((int) ($cfg['live_chat_rate_limit'] ?? 2), (int) $slow_mode);

        $sql = "SELECT MAX(timestamp) as last_message FROM `db_live_chat_messages`
                WHERE `stream_key` = '%s' AND `usr_id` = %d";

        $result = $class_database->doQuery($sql, $stream_key, $usr_id);
        $row = $result->fetch_assoc();

        if ($row['last_message']) {
            $last_time = strtotime($row['last_message']);
            $now = time();
            $diff = $now - $last_time;

            if ($diff < $rate_limit) {
                $wait = $rate_limit - $diff;
                return [
                    'allowed' => false,
                    'message' => "Please wait {$wait} seconds before sending another message"
                ];
            }
        }

        return ['allowed' => true];
    }
}
