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

/**
 * Advanced Analytics System for Platform Metrics and Reporting
 */
class VAnalytics
{
    private $db;
    private $logger;
    private $cache;
    private $rbac;
    
    public function __construct()
    {
        $this->db = VDatabase::getInstance();
        $this->logger = VLogger::getInstance();
        $this->cache = VRedis::getInstance();
        $this->rbac = VRBAC::getInstance();
    }
    
    /**
     * Get platform overview statistics
     * @param array $filters Date range and other filters
     * @return array Platform statistics
     */
    public function getPlatformOverview($filters = [])
    {
        $dateRange = $this->getDateRange($filters);
        $cacheKey = "analytics_overview_" . md5(serialize($filters));
        
        // Try cache first
        if ($this->cache->isConnected()) {
            $cached = $this->cache->get($cacheKey);
            if ($cached !== false) {
                return $cached;
            }
        }
        
        try {
            $overview = [
                'users' => $this->getUserStatistics($dateRange),
                'content' => $this->getContentStatistics($dateRange),
                'engagement' => $this->getEngagementStatistics($dateRange),
                'streaming' => $this->getStreamingStatistics($dateRange),
                'revenue' => $this->getRevenueStatistics($dateRange),
                'performance' => $this->getPerformanceStatistics($dateRange),
                'growth' => $this->getGrowthStatistics($dateRange)
            ];
            
            // Cache for 15 minutes
            if ($this->cache->isConnected()) {
                $this->cache->set($cacheKey, $overview, 900);
            }
            
            return $overview;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get platform overview', [
                'error' => $e->getMessage(),
                'filters' => $filters
            ]);
            
            return [];
        }
    }
    
    /**
     * Get user analytics
     * @param int $userId User ID
     * @param array $filters Filters
     * @return array User analytics
     */
    public function getUserAnalytics($userId, $filters = [])
    {
        // Check permissions
        if (!$this->rbac->hasPermission($userId, 'analytics.view')) {
            throw new Exception('User does not have analytics permission');
        }
        
        $dateRange = $this->getDateRange($filters);
        $cacheKey = "user_analytics_{$userId}_" . md5(serialize($filters));
        
        // Try cache first
        if ($this->cache->isConnected()) {
            $cached = $this->cache->get($cacheKey);
            if ($cached !== false) {
                return $cached;
            }
        }
        
        try {
            $analytics = [
                'overview' => $this->getUserOverview($userId, $dateRange),
                'videos' => $this->getUserVideoAnalytics($userId, $dateRange),
                'audience' => $this->getUserAudienceAnalytics($userId, $dateRange),
                'engagement' => $this->getUserEngagementAnalytics($userId, $dateRange),
                'revenue' => $this->getUserRevenueAnalytics($userId, $dateRange),
                'growth' => $this->getUserGrowthAnalytics($userId, $dateRange)
            ];
            
            // Cache for 10 minutes
            if ($this->cache->isConnected()) {
                $this->cache->set($cacheKey, $analytics, 600);
            }
            
            return $analytics;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get user analytics', [
                'user_id' => $userId,
                'error' => $e->getMessage(),
                'filters' => $filters
            ]);
            
            return [];
        }
    }
    
    /**
     * Get video analytics
     * @param string $videoKey Video key
     * @param int $userId User ID (for permission check)
     * @param array $filters Filters
     * @return array Video analytics
     */
    public function getVideoAnalytics($videoKey, $userId, $filters = [])
    {
        // Check if user owns video or has permission
        if (!$this->canViewVideoAnalytics($videoKey, $userId)) {
            throw new Exception('Permission denied');
        }
        
        $dateRange = $this->getDateRange($filters);
        $cacheKey = "video_analytics_{$videoKey}_" . md5(serialize($filters));
        
        // Try cache first
        if ($this->cache->isConnected()) {
            $cached = $this->cache->get($cacheKey);
            if ($cached !== false) {
                return $cached;
            }
        }
        
        try {
            $analytics = [
                'overview' => $this->getVideoOverview($videoKey, $dateRange),
                'views' => $this->getVideoViewAnalytics($videoKey, $dateRange),
                'engagement' => $this->getVideoEngagementAnalytics($videoKey, $dateRange),
                'audience' => $this->getVideoAudienceAnalytics($videoKey, $dateRange),
                'performance' => $this->getVideoPerformanceAnalytics($videoKey, $dateRange),
                'retention' => $this->getVideoRetentionAnalytics($videoKey, $dateRange)
            ];
            
            // Cache for 5 minutes
            if ($this->cache->isConnected()) {
                $this->cache->set($cacheKey, $analytics, 300);
            }
            
            return $analytics;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get video analytics', [
                'video_key' => $videoKey,
                'user_id' => $userId,
                'error' => $e->getMessage(),
                'filters' => $filters
            ]);
            
            return [];
        }
    }
    
    /**
     * Track video view
     * @param string $videoKey Video key
     * @param array $viewData View data
     * @return bool Success status
     */
    public function trackVideoView($videoKey, $viewData)
    {
        try {
            $trackingData = [
                'video_key' => $videoKey,
                'user_id' => $viewData['user_id'] ?? null,
                'ip_address' => $viewData['ip_address'] ?? $_SERVER['REMOTE_ADDR'],
                'user_agent' => $viewData['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'],
                'referrer' => $viewData['referrer'] ?? $_SERVER['HTTP_REFERER'] ?? '',
                'country' => $viewData['country'] ?? $this->getCountryFromIP($viewData['ip_address'] ?? $_SERVER['REMOTE_ADDR']),
                'device_type' => $viewData['device_type'] ?? $this->getDeviceType($_SERVER['HTTP_USER_AGENT'] ?? ''),
                'watch_duration' => $viewData['watch_duration'] ?? 0,
                'quality' => $viewData['quality'] ?? 'auto',
                'created_at' => date('Y-m-d H:i:s')
            ];
            
            $this->db->doInsert('db_video_analytics', $trackingData);
            
            // Update video view count
            $this->db->doQuery("UPDATE db_videofiles SET file_views = file_views + 1 WHERE file_key = ?", [$videoKey]);
            
            // Queue analytics processing job
            $queue = new VQueue();
            $queue->enqueue('AnalyticsProcessingJob', [
                'type' => 'video_view',
                'video_key' => $videoKey,
                'data' => $trackingData
            ], 'analytics');
            
            return true;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to track video view', [
                'video_key' => $videoKey,
                'error' => $e->getMessage()
            ]);
            
            return false;
        }
    }
    
    /**
     * Track user engagement
     * @param string $eventType Event type (like, comment, share, etc.)
     * @param array $eventData Event data
     * @return bool Success status
     */
    public function trackEngagement($eventType, $eventData)
    {
        try {
            $trackingData = [
                'event_type' => $eventType,
                'user_id' => $eventData['user_id'] ?? null,
                'target_type' => $eventData['target_type'] ?? 'video',
                'target_id' => $eventData['target_id'] ?? '',
                'ip_address' => $eventData['ip_address'] ?? $_SERVER['REMOTE_ADDR'],
                'user_agent' => $eventData['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'],
                'data' => json_encode($eventData['additional_data'] ?? []),
                'created_at' => date('Y-m-d H:i:s')
            ];
            
            $this->db->doInsert('db_engagement_analytics', $trackingData);
            
            // Queue analytics processing job
            $queue = new VQueue();
            $queue->enqueue('AnalyticsProcessingJob', [
                'type' => 'engagement',
                'event_type' => $eventType,
                'data' => $trackingData
            ], 'analytics');
            
            return true;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to track engagement', [
                'event_type' => $eventType,
                'error' => $e->getMessage()
            ]);
            
            return false;
        }
    }
    
    /**
     * Get real-time statistics
     * @return array Real-time stats
     */
    public function getRealTimeStats()
    {
        $cacheKey = "realtime_stats";
        
        // Try cache first (very short cache)
        if ($this->cache->isConnected()) {
            $cached = $this->cache->get($cacheKey);
            if ($cached !== false) {
                return $cached;
            }
        }
        
        try {
            $stats = [
                'active_users' => $this->getActiveUsers(),
                'live_streams' => $this->getLiveStreamCount(),
                'current_viewers' => $this->getCurrentViewers(),
                'recent_uploads' => $this->getRecentUploads(),
                'server_load' => $this->getServerLoad(),
                'bandwidth_usage' => $this->getBandwidthUsage()
            ];
            
            // Cache for 30 seconds
            if ($this->cache->isConnected()) {
                $this->cache->set($cacheKey, $stats, 30);
            }
            
            return $stats;
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get real-time stats', [
                'error' => $e->getMessage()
            ]);
            
            return [];
        }
    }
    
    /**
     * Generate analytics report
     * @param string $reportType Report type
     * @param array $parameters Report parameters
     * @param int $userId User ID (for permission check)
     * @return array Report data
     */
    public function generateReport($reportType, $parameters, $userId)
    {
        // Check permissions
        if (!$this->rbac->hasPermission($userId, 'analytics.reports')) {
            throw new Exception('User does not have report generation permission');
        }
        
        try {
            switch ($reportType) {
                case 'user_growth':
                    return $this->generateUserGrowthReport($parameters);
                    
                case 'content_performance':
                    return $this->generateContentPerformanceReport($parameters);
                    
                case 'engagement_trends':
                    return $this->generateEngagementTrendsReport($parameters);
                    
                case 'revenue_analysis':
                    return $this->generateRevenueAnalysisReport($parameters);
                    
                case 'platform_health':
                    return $this->generatePlatformHealthReport($parameters);
                    
                default:
                    throw new Exception("Unknown report type: {$reportType}");
            }
            
        } catch (Exception $e) {
            $this->logger->error('Failed to generate report', [
                'report_type' => $reportType,
                'user_id' => $userId,
                'error' => $e->getMessage()
            ]);
            
            throw $e;
        }
    }
    
    /**
     * Get user statistics
     * @param array $dateRange Date range
     * @return array User statistics
     */
    private function getUserStatistics($dateRange)
    {
        $query = "SELECT 
                    COUNT(*) as total_users,
                    COUNT(CASE WHEN usr_status = 'active' THEN 1 END) as active_users,
                    COUNT(CASE WHEN DATE(usr_joindate) >= ? THEN 1 END) as new_users,
                    COUNT(CASE WHEN usr_lastlogin >= ? THEN 1 END) as recent_active
                  FROM db_accountuser 
                  WHERE usr_joindate <= ?";
        
        $result = $this->db->doQuery($query, [
            $dateRange['start'],
            $dateRange['start'],
            $dateRange['end']
        ]);
        
        return $this->db->doFetch($result) ?: [];
    }
    
    /**
     * Get content statistics
     * @param array $dateRange Date range
     * @return array Content statistics
     */
    private function getContentStatistics($dateRange)
    {
        $query = "SELECT 
                    COUNT(*) as total_videos,
                    COUNT(CASE WHEN DATE(upload_date) >= ? THEN 1 END) as new_videos,
                    SUM(file_views) as total_views,
                    SUM(CASE WHEN DATE(upload_date) >= ? THEN file_views ELSE 0 END) as period_views,
                    AVG(file_rating) as average_rating,
                    SUM(file_size) as total_storage
                  FROM db_videofiles 
                  WHERE upload_date <= ? AND file_type = 'video'";
        
        $result = $this->db->doQuery($query, [
            $dateRange['start'],
            $dateRange['start'],
            $dateRange['end']
        ]);
        
        return $this->db->doFetch($result) ?: [];
    }
    
    /**
     * Get engagement statistics
     * @param array $dateRange Date range
     * @return array Engagement statistics
     */
    private function getEngagementStatistics($dateRange)
    {
        $query = "SELECT 
                    COUNT(CASE WHEN event_type = 'like' THEN 1 END) as total_likes,
                    COUNT(CASE WHEN event_type = 'comment' THEN 1 END) as total_comments,
                    COUNT(CASE WHEN event_type = 'share' THEN 1 END) as total_shares,
                    COUNT(CASE WHEN event_type = 'subscribe' THEN 1 END) as total_subscriptions
                  FROM db_engagement_analytics 
                  WHERE created_at BETWEEN ? AND ?";
        
        $result = $this->db->doQuery($query, [
            $dateRange['start'],
            $dateRange['end']
        ]);
        
        return $this->db->doFetch($result) ?: [];
    }
    
    /**
     * Get streaming statistics
     * @param array $dateRange Date range
     * @return array Streaming statistics
     */
    private function getStreamingStatistics($dateRange)
    {
        $query = "SELECT 
                    COUNT(*) as total_streams,
                    COUNT(CASE WHEN status = 'live' THEN 1 END) as live_streams,
                    SUM(max_viewers) as total_max_viewers,
                    AVG(max_viewers) as avg_max_viewers,
                    SUM(duration) as total_duration
                  FROM db_live_streams 
                  WHERE created_at BETWEEN ? AND ?";
        
        $result = $this->db->doQuery($query, [
            $dateRange['start'],
            $dateRange['end']
        ]);
        
        return $this->db->doFetch($result) ?: [];
    }
    
    /**
     * Get revenue statistics
     * @param array $dateRange Date range
     * @return array Revenue statistics
     */
    private function getRevenueStatistics($dateRange)
    {
        // This would integrate with your monetization system
        return [
            'total_revenue' => 0,
            'period_revenue' => 0,
            'transactions' => 0,
            'average_transaction' => 0
        ];
    }
    
    /**
     * Get performance statistics
     * @param array $dateRange Date range
     * @return array Performance statistics
     */
    private function getPerformanceStatistics($dateRange)
    {
        // Get from job statistics and system metrics
        $query = "SELECT 
                    COUNT(*) as total_jobs,
                    COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_jobs,
                    COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_jobs,
                    AVG(processing_time) as avg_processing_time
                  FROM db_job_statistics 
                  WHERE created_at BETWEEN ? AND ?";
        
        $result = $this->db->doQuery($query, [
            $dateRange['start'],
            $dateRange['end']
        ]);
        
        return $this->db->doFetch($result) ?: [];
    }
    
    /**
     * Get growth statistics
     * @param array $dateRange Date range
     * @return array Growth statistics
     */
    private function getGrowthStatistics($dateRange)
    {
        // Calculate growth rates
        $currentPeriod = $this->getUserStatistics($dateRange);
        
        // Get previous period for comparison
        $previousStart = date('Y-m-d', strtotime($dateRange['start'] . ' -30 days'));
        $previousEnd = date('Y-m-d', strtotime($dateRange['end'] . ' -30 days'));
        $previousPeriod = $this->getUserStatistics(['start' => $previousStart, 'end' => $previousEnd]);
        
        $userGrowth = $this->calculateGrowthRate(
            $previousPeriod['new_users'] ?? 0,
            $currentPeriod['new_users'] ?? 0
        );
        
        return [
            'user_growth_rate' => $userGrowth,
            'content_growth_rate' => 0, // Calculate similarly
            'engagement_growth_rate' => 0 // Calculate similarly
        ];
    }
    
    /**
     * Get date range from filters
     * @param array $filters Filters
     * @return array Date range
     */
    private function getDateRange($filters)
    {
        $end = $filters['end_date'] ?? date('Y-m-d');
        $start = $filters['start_date'] ?? date('Y-m-d', strtotime('-30 days'));
        
        return [
            'start' => $start,
            'end' => $end
        ];
    }
    
    /**
     * Check if user can view video analytics
     * @param string $videoKey Video key
     * @param int $userId User ID
     * @return bool True if allowed
     */
    private function canViewVideoAnalytics($videoKey, $userId)
    {
        // Check if user owns the video
        $query = "SELECT usr_id FROM db_videofiles WHERE file_key = ?";
        $result = $this->db->doQuery($query, [$videoKey]);
        $video = $this->db->doFetch($result);
        
        if ($video && $video['usr_id'] == $userId) {
            return true;
        }
        
        // Check if user has admin permissions
        return $this->rbac->hasPermission($userId, 'admin.analytics.view');
    }
    
    /**
     * Calculate growth rate
     * @param float $previous Previous value
     * @param float $current Current value
     * @return float Growth rate percentage
     */
    private function calculateGrowthRate($previous, $current)
    {
        if ($previous == 0) {
            return $current > 0 ? 100 : 0;
        }
        
        return round((($current - $previous) / $previous) * 100, 2);
    }
    
    /**
     * Get country from IP address
     * @param string $ip IP address
     * @return string Country code
     */
    private function getCountryFromIP($ip)
    {
        // Implement IP geolocation (use service like MaxMind GeoIP)
        return 'US'; // Placeholder
    }
    
    /**
     * Get device type from user agent
     * @param string $userAgent User agent string
     * @return string Device type
     */
    private function getDeviceType($userAgent)
    {
        if (preg_match('/Mobile|Android|iPhone|iPad/', $userAgent)) {
            return 'mobile';
        } elseif (preg_match('/Tablet/', $userAgent)) {
            return 'tablet';
        } else {
            return 'desktop';
        }
    }
    
    /**
     * Get active users count
     * @return int Active users
     */
    private function getActiveUsers()
    {
        $query = "SELECT COUNT(DISTINCT user_id) as count 
                  FROM db_video_analytics 
                  WHERE created_at >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)";
        $result = $this->db->doQuery($query);
        $row = $this->db->doFetch($result);
        
        return (int)($row['count'] ?? 0);
    }
    
    /**
     * Get live stream count
     * @return int Live stream count
     */
    private function getLiveStreamCount()
    {
        $query = "SELECT COUNT(*) as count FROM db_live_streams WHERE status = 'live'";
        $result = $this->db->doQuery($query);
        $row = $this->db->doFetch($result);
        
        return (int)($row['count'] ?? 0);
    }
    
    /**
     * Get current viewers
     * @return int Current viewers
     */
    private function getCurrentViewers()
    {
        $query = "SELECT SUM(viewer_count) as count FROM db_live_streams WHERE status = 'live'";
        $result = $this->db->doQuery($query);
        $row = $this->db->doFetch($result);
        
        return (int)($row['count'] ?? 0);
    }
    
    /**
     * Get recent uploads count
     * @return int Recent uploads
     */
    private function getRecentUploads()
    {
        $query = "SELECT COUNT(*) as count 
                  FROM db_videofiles 
                  WHERE upload_date >= DATE_SUB(NOW(), INTERVAL 1 HOUR)";
        $result = $this->db->doQuery($query);
        $row = $this->db->doFetch($result);
        
        return (int)($row['count'] ?? 0);
    }
    
    /**
     * Get server load
     * @return array Server load metrics
     */
    private function getServerLoad()
    {
        return [
            'cpu_usage' => sys_getloadavg()[0] ?? 0,
            'memory_usage' => memory_get_usage(true),
            'disk_usage' => disk_free_space('.') ? (disk_total_space('.') - disk_free_space('.')) / disk_total_space('.') * 100 : 0
        ];
    }
    
    /**
     * Get bandwidth usage
     * @return array Bandwidth metrics
     */
    private function getBandwidthUsage()
    {
        // This would typically come from server monitoring tools
        return [
            'incoming' => 0,
            'outgoing' => 0,
            'total' => 0
        ];
    }
}