<?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');

/**
 * Stream Key Manager
 * Handles user-level stream key generation, activation, and revocation.
 */
class VStreamKeyManager
{
    private static $instance = null;
    
    private $db;
    private $logger;
    
    private function __construct()
    {
        $this->db = VDatabase::getInstance();
        $this->logger = VLogger::getInstance();
    }
    
    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    /**
     * Ensure the user has streaming enabled and a stream key assigned.
     * @param int $userId
     * @return string Stream key
     * @throws Exception when streaming is disabled or user not found
     */
    public function ensureActiveStreamKey($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        
        if (!$record) {
            throw new Exception('User not found');
        }
        
        if ((int)$record['streaming_enabled'] !== 1) {
            throw new Exception('Streaming is disabled for this user');
        }
        
        if (empty($record['live_key'])) {
            return $this->generateAndPersistKey($userId, $record);
        }
        
        return $record['live_key'];
    }
    
    /**
     * Activate streaming for a user and ensure a stream key exists.
     * @param int $userId
     * @return string Stream key
     * @throws Exception
     */
    public function activateStreaming($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        if (!$record) {
            throw new Exception('User not found');
        }
        
        $updates = [
            'streaming_enabled' => 1
        ];
        
        $createdNewKey = false;
        if (empty($record['live_key'])) {
            $updates['live_key'] = $this->generateStreamKeyValue($userId);
            $updates['stream_key_regenerated_at'] = date('Y-m-d H:i:s');
            $createdNewKey = true;
        }
        
        // Only perform update if necessary
        if ((int)$record['streaming_enabled'] !== 1 || $createdNewKey) {
            $this->db->doUpdate('db_accountuser', 'usr_id', $updates, $userId);
            
            $this->logger->info('Streaming enabled for user', [
                'user_id' => $userId,
                'key_generated' => $createdNewKey
            ]);
        }
        
        return $createdNewKey ? $updates['live_key'] : $record['live_key'];
    }
    
    /**
     * Regenerate and persist a new stream key for the user.
     * @param int $userId
     * @return string New stream key
     * @throws Exception
     */
    public function regenerateStreamKey($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        if (!$record) {
            throw new Exception('User not found');
        }
        
        if ((int)$record['streaming_enabled'] !== 1) {
            throw new Exception('Streaming is disabled for this user');
        }
        
        $newKey = $this->generateStreamKeyValue($userId);
        $this->db->doUpdate('db_accountuser', 'usr_id', [
            'live_key' => $newKey,
            'stream_key_regenerated_at' => date('Y-m-d H:i:s')
        ], $userId);
        
        $this->logger->info('Stream key regenerated', [
            'user_id' => $userId
        ]);
        
        return $newKey;
    }
    
    /**
     * Deactivate streaming for user and clear stream key.
     * @param int $userId
     */
    public function deactivateStreaming($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        if (!$record) {
            return;
        }
        
        $updates = [
            'streaming_enabled' => 0,
            'live_key' => '',
            'stream_key_regenerated_at' => date('Y-m-d H:i:s')
        ];
        
        $this->db->doUpdate('db_accountuser', 'usr_id', $updates, $userId);
        
        $this->logger->info('Streaming disabled for user', [
            'user_id' => $userId
        ]);
    }
    
    /**
     * Determine if streaming is currently enabled for a user.
     * @param int $userId
     * @return bool
     */
    public function isStreamingEnabled($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        return $record ? (int)$record['streaming_enabled'] === 1 : false;
    }
    
    /**
     * Retrieve current stream key without side effects.
     * @param int $userId
     * @return string|null
     */
    public function getCurrentStreamKey($userId)
    {
        $record = $this->getUserStreamingRecord($userId);
        if (!$record) {
            return null;
        }
        
        return $record['live_key'] ?: null;
    }
    
    private function generateAndPersistKey($userId, array $record)
    {
        $newKey = $this->generateStreamKeyValue($userId);
        
        $this->db->doUpdate('db_accountuser', 'usr_id', [
            'live_key' => $newKey,
            'stream_key_regenerated_at' => date('Y-m-d H:i:s')
        ], $userId);
        
        $this->logger->info('Stream key generated for user', [
            'user_id' => $userId
        ]);
        
        return $newKey;
    }
    
    private function generateStreamKeyValue($userId)
    {
        // Ensure high-entropy stream keys using hex encoding
        $random = bin2hex(random_bytes(16));
        return 'es_' . $userId . '_' . $random;
    }
    
    private function getUserStreamingRecord($userId)
    {
        $query = "SELECT usr_id, live_key, streaming_enabled FROM db_accountuser WHERE usr_id = ? LIMIT 1";
        $result = $this->db->doQuery($query, [$userId]);
        return $this->db->doFetch($result);
    }
}
