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

/**
 * Admin Dashboard and Management System
 */
class VAdmin
{
    private $logger;
    private $db;
    private static $instance = null;
    
    public function __construct()
    {
        $this->logger = VLogger::getInstance();
        $this->db = VDatabase::getInstance();
    }
    
    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Get platform analytics dashboard data
     * @param string $period Time period (today, week, month, year)
     * @return array Dashboard data
     */
    public function getDashboardAnalytics($period = 'week')
    {
        try {
            $timeFilter = $this->getTimeFilter($period);
            
            $analytics = [
                'overview' => $this->getOverviewStats($timeFilter),
                'users' => $this->getUserStats($timeFilter),
                'content' => $this->getContentStats($timeFilter),
                'engagement' => $this->getEngagementStats($timeFilter),
                'system' => $this->getSystemStats(),
                'recent_activity' => $this->getRecentActivity(20)
            ];
            
            return [
                'success' => true,
                'period' => $period,
                'analytics' => $analytics,
                'generated_at' => date('Y-m-d H:i:s')
            ];
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get dashboard analytics', [
                'period' => $period,
                'error' => $e->getMessage()
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Get user management data
     * @param array $filters Filters
     * @param int $limit Limit
     * @param int $offset Offset
     * @return array User data
     */
    public function getUserManagement($filters = [], $limit = 50, $offset = 0)
    {
        try {
            $whereClause = "WHERE 1=1";
            $params = [];
            
            if (isset($filters['role'])) {
                $whereClause .= " AND usr_role = ?";
                $params[] = $filters['role'];
            }
            
            if (isset($filters['status'])) {
                if ($filters['status'] === 'active') {
                    $whereClause .= " AND usr_active = 1 AND usr_deleted = 0";
                } elseif ($filters['status'] === 'suspended') {
                    $whereClause .= " AND usr_active = 0 AND usr_deleted = 0";
                } elseif ($filters['status'] === 'deleted') {
                    $whereClause .= " AND usr_deleted = 1";
                }
            }
            
            if (isset($filters['search'])) {
                $whereClause .= " AND (usr_user LIKE ? OR usr_email LIKE ?)";
                $searchTerm = '%' . $filters['search'] . '%';
                $params[] = $searchTerm;
                $params[] = $searchTerm;
            }
            
            $query = "SELECT usr_id, usr_user, usr_email, usr_role, usr_active, usr_deleted, 
                             usr_verified, usr_joindate, usr_lastlogin, usr_logins,
                             usr_v_count, usr_i_count, usr_a_count, usr_d_count
                      FROM db_accountuser 
                      {$whereClause}
                      ORDER BY usr_joindate DESC
                      LIMIT ? OFFSET ?";
            
            $params[] = $limit;
            $params[] = $offset;
            
            $result = $this->db->doQuery($query, $params);
            
            $users = [];
            while ($row = $this->db->doFetch($result)) {
                $users[] = $this->formatUserData($row);
            }
            
            // Get total count
            $countQuery = "SELECT COUNT(*) as total FROM db_accountuser {$whereClause}";
            $countParams = array_slice($params, 0, -2); // Remove limit and offset
            $countResult = $this->db->doQuery($countQuery, $countParams);
            $totalCount = $this->db->doFetch($countResult)['total'];
            
            return [
                'success' => true,
                'users' => $users,
                'pagination' => [
                    'total' => $totalCount,
                    'limit' => $limit,
                    'offset' => $offset,
                    'pages' => ceil($totalCount / $limit)
                ]
            ];
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get user management data', [
                'filters' => $filters,
                'error' => $e->getMessage()
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Update user status
     * @param int $userId User ID
     * @param string $action Action (activate, suspend, delete, restore)
     * @param string $reason Reason for action
     * @return array Result
     */
    public function updateUserStatus($userId, $action, $reason = '')
    {
        try {
            $user = $this->getUserById($userId);
            
            if (!$user) {
                return [
                    'success' => false,
                    'error' => 'User not found'
                ];
            }
            
            $updateData = ['updated_at' => date('Y-m-d H:i:s')];
            
            switch ($action) {
                case 'activate':
                    $updateData['usr_active'] = 1;
                    $updateData['usr_deleted'] = 0;
                    break;
                    
                case 'suspend':
                    $updateData['usr_active'] = 0;
                    break;
                    
                case 'delete':
                    $updateData['usr_deleted'] = 1;
                    $updateData['usr_active'] = 0;
                    break;
                    
                case 'restore':
                    $updateData['usr_deleted'] = 0;
                    $updateData['usr_active'] = 1;
                    break;
                    
                default:
                    return [
                        'success' => false,
                        'error' => 'Invalid action'
                    ];
            }
            
            $this->db->doUpdate('db_accountuser', 'usr_id', $updateData, $userId);
            
            // Log admin action
            $this->logAdminAction('user_status_update', [
                'target_user_id' => $userId,
                'target_username' => $user['usr_user'],
                'action' => $action,
                'reason' => $reason
            ]);
            
            $this->logger->info('User status updated', [
                'user_id' => $userId,
                'action' => $action,
                'reason' => $reason
            ]);
            
            return [
                'success' => true,
                'message' => "User {$action}d successfully"
            ];
            
        } catch (Exception $e) {
            $this->logger->error('Failed to update user status', [
                'user_id' => $userId,
                'action' => $action,
                'error' => $e->getMessage()
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Get content moderation queue
     * @param string $contentType Content type filter
     * @param int $limit Limit
     * @param int $offset Offset
     * @return array Moderation queue
     */
    public function getModerationQueue($contentType = 'all', $limit = 50, $offset = 0)
    {
        try {
            $tables = [
                'video' => 'db_videofiles',
                'image' => 'db_imagefiles',
                'audio' => 'db_audiofiles',
                'document' => 'db_documentfiles'
            ];
            
            $items = [];
            
            if ($contentType === 'all') {
                foreach ($tables as $type => $table) {
                    $typeItems = $this->getModerationItemsByType($type, $table, $limit / 4, $offset);
                    $items = array_merge($items, $typeItems);
                }
            } else {
                if (isset($tables[$contentType])) {
                    $items = $this->getModerationItemsByType($contentType, $tables[$contentType], $limit, $offset);
                }
            }
            
            // Sort by upload date
            usort($items, function($a, $b) {
                return strtotime($b['uploaded_at']) - strtotime($a['uploaded_at']);
            });
            
            return [
                'success' => true,
                'items' => array_slice($items, 0, $limit),
                'total' => count($items)
            ];
            
        } catch (Exception $e) {
            $this->logger->error('Failed to get moderation queue', [
                'content_type' => $contentType,
                'error' => $e->getMessage()
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Moderate content
     * @param string $contentType Content type
     * @param string $contentId Content ID
     * @param string $action Action (approve, reject, delete)
     * @param string $reason Reason
     * @return array Result
     */
    public function moderateContent($contentType, $contentId, $action, $reason = '')
    {
        try {
            $tables = [
                'video' => 'db_videofiles',
                'image' => 'db_imagefiles',
                'audio' => 'db_audiofiles',
                'document' => 'db_documentfiles'
            ];
            
            if (!isset($tables[$contentType])) {
                return [
                    'success' => false,
                    'error' => 'Invalid content type'
                ];
            }
            
            $table = $tables[$contentType];
            $updateData = ['moderated_at' => date('Y-m-d H:i:s')];
            
            switch ($action) {
                case 'approve':
                    $updateData['file_active'] = 1;
                    $updateData['moderation_status'] = 'approved';
                    break;
                    
                case 'reject':
                    $updateData['file_active'] = 0;
                    $updateData['moderation_status'] = 'rejected';
                    $updateData['moderation_reason'] = $reason;
                    break;
                    
                case 'delete':
                    $updateData['file_active'] = 0;
                    $updateData['moderation_status'] = 'deleted';
                    $updateData['moderation_reason'] = $reason;
                    break;
                    
                default:
                    return [
                        'success' => false,
                        'error' => 'Invalid action'
                    ];
            }
            
            $this->db->doUpdate($table, 'file_key', $updateData, $contentId);
            
            // Log admin action
            $this->logAdminAction('content_moderation', [
                'content_type' => $contentType,
                'content_id' => $contentId,
                'action' => $action,
                'reason' => $reason
            ]);
            
            return [
                'success' => true,
                'message' => "Content {$action}d successfully"
            ];
            
        } catch (Exception $e) {
            $this->logger->error('Failed to moderate content', [
                'content_type' => $contentType,
                'content_id' => $contentId,
                'action' => $action,
                'error' => $e->getMessage()
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Get system health status
     * @return array System health
     */
    public function getSystemHealth()
    {
        try {
            $health = [
                'overall_status' => 'healthy',
                'components' => [],
                'issues' => []
            ];
            
            // Check database
            $dbHealth = $this->checkDatabaseHealth();
            $health['components']['database'] = $dbHealth;
            
            // Check queue system
            $queueManager = new VQueueManager();
            $queueHealth = $queueManager->healthCheck();
            $health['components']['queue'] = $queueHealth;
            
            // Check file system
            $fsHealth = $this->checkFileSystemHealth();
            $health['components']['filesystem'] = $fsHealth;
            
            // Check external services
            $extHealth = $this->checkExternalServices();
            $health['components']['external'] = $extHealth;
            
            // Determine overall status
            foreach ($health['components'] as $component => $status) {
                if ($status['status'] === 'unhealthy') {
                    $health['overall_status'] = 'unhealthy';
                    $health['issues'][] = "{$component}: " . implode(', ', $status['issues'] ?? []);
                } elseif ($status['status'] === 'warning' && $health['overall_status'] === 'healthy') {
                    $health['overall_status'] = 'warning';
                }
            }
            
            return [
                'success' => true,
                'health' => $health,
                'checked_at' => date('Y-m-d H:i:s')
            ];
            
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Private helper methods
     */
    
    private function getTimeFilter($period)
    {
        switch ($period) {
            case 'today':
                return "DATE(created_at) = CURDATE()";
            case 'week':
                return "created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)";
            case 'month':
                return "created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)";
            case 'year':
                return "created_at >= DATE_SUB(NOW(), INTERVAL 365 DAY)";
            default:
                return "created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)";
        }
    }
    
    private function getOverviewStats($timeFilter)
    {
        $stats = [];
        
        // Total users
        $query = "SELECT COUNT(*) as count FROM db_accountuser WHERE usr_deleted = 0";
        $result = $this->db->doQuery($query);
        $stats['total_users'] = $this->db->doFetch($result)['count'];
        
        // New users
        $query = "SELECT COUNT(*) as count FROM db_accountuser WHERE {$timeFilter}";
        $result = $this->db->doQuery($query);
        $stats['new_users'] = $this->db->doFetch($result)['count'];
        
        // Total videos
        $query = "SELECT COUNT(*) as count FROM db_videofiles WHERE file_active = 1";
        $result = $this->db->doQuery($query);
        $stats['total_videos'] = $this->db->doFetch($result)['count'];
        
        // New videos
        $query = "SELECT COUNT(*) as count FROM db_videofiles WHERE {$timeFilter}";
        $result = $this->db->doQuery($query);
        $stats['new_videos'] = $this->db->doFetch($result)['count'];
        
        return $stats;
    }
    
    private function getUserStats($timeFilter)
    {
        $stats = [];
        
        // User registrations by day
        $query = "SELECT DATE(usr_joindate) as date, COUNT(*) as count 
                  FROM db_accountuser 
                  WHERE {$timeFilter}
                  GROUP BY DATE(usr_joindate)
                  ORDER BY date DESC";
        $result = $this->db->doQuery($query);
        
        $registrations = [];
        while ($row = $this->db->doFetch($result)) {
            $registrations[] = $row;
        }
        $stats['registrations_by_day'] = $registrations;
        
        // User roles distribution
        $query = "SELECT usr_role, COUNT(*) as count 
                  FROM db_accountuser 
                  WHERE usr_deleted = 0
                  GROUP BY usr_role";
        $result = $this->db->doQuery($query);
        
        $roles = [];
        while ($row = $this->db->doFetch($result)) {
            $roles[] = $row;
        }
        $stats['roles_distribution'] = $roles;
        
        return $stats;
    }
    
    private function getContentStats($timeFilter)
    {
        $stats = [];
        
        // Content uploads by type
        $contentTypes = [
            'videos' => 'db_videofiles',
            'images' => 'db_imagefiles',
            'audio' => 'db_audiofiles',
            'documents' => 'db_documentfiles'
        ];
        
        foreach ($contentTypes as $type => $table) {
            $query = "SELECT COUNT(*) as count FROM {$table} WHERE {$timeFilter}";
            $result = $this->db->doQuery($query);
            $stats["new_{$type}"] = $this->db->doFetch($result)['count'];
        }
        
        return $stats;
    }
    
    private function getEngagementStats($timeFilter)
    {
        $stats = [];
        
        // Video views
        $query = "SELECT COUNT(*) as count FROM db_video_views WHERE {$timeFilter}";
        $result = $this->db->doQuery($query);
        $stats['video_views'] = $this->db->doFetch($result)['count'];
        
        // Comments
        $query = "SELECT COUNT(*) as count FROM db_comments WHERE {$timeFilter}";
        $result = $this->db->doQuery($query);
        $stats['comments'] = $this->db->doFetch($result)['count'];
        
        // Likes
        $query = "SELECT COUNT(*) as count FROM db_votes WHERE vote_type = 'like' AND {$timeFilter}";
        $result = $this->db->doQuery($query);
        $stats['likes'] = $this->db->doFetch($result)['count'];
        
        return $stats;
    }
    
    private function getSystemStats()
    {
        $stats = [];
        
        // Queue statistics
        $queueManager = new VQueueManager();
        $stats['queue'] = $queueManager->getQueueStatistics();
        
        // Disk usage
        $stats['disk_usage'] = [
            'total' => disk_total_space('.'),
            'free' => disk_free_space('.'),
            'used' => disk_total_space('.') - disk_free_space('.')
        ];
        
        // Memory usage
        $stats['memory_usage'] = [
            'current' => memory_get_usage(true),
            'peak' => memory_get_peak_usage(true)
        ];
        
        return $stats;
    }
    
    private function getRecentActivity($limit)
    {
        $activities = [];
        
        // Recent user registrations
        $query = "SELECT 'user_registration' as type, usr_user as title, usr_joindate as created_at
                  FROM db_accountuser 
                  ORDER BY usr_joindate DESC 
                  LIMIT ?";
        $result = $this->db->doQuery($query, [$limit / 4]);
        
        while ($row = $this->db->doFetch($result)) {
            $activities[] = $row;
        }
        
        // Recent video uploads
        $query = "SELECT 'video_upload' as type, file_title as title, file_date as created_at
                  FROM db_videofiles 
                  ORDER BY file_date DESC 
                  LIMIT ?";
        $result = $this->db->doQuery($query, [$limit / 4]);
        
        while ($row = $this->db->doFetch($result)) {
            $activities[] = $row;
        }
        
        // Sort by date
        usort($activities, function($a, $b) {
            return strtotime($b['created_at']) - strtotime($a['created_at']);
        });
        
        return array_slice($activities, 0, $limit);
    }
    
    private function formatUserData($row)
    {
        return [
            'id' => $row['usr_id'],
            'username' => $row['usr_user'],
            'email' => $row['usr_email'],
            'role' => $row['usr_role'],
            'active' => (bool)$row['usr_active'],
            'deleted' => (bool)$row['usr_deleted'],
            'verified' => (bool)$row['usr_verified'],
            'joined_at' => $row['usr_joindate'],
            'last_login' => $row['usr_lastlogin'],
            'login_count' => $row['usr_logins'],
            'content_counts' => [
                'videos' => $row['usr_v_count'],
                'images' => $row['usr_i_count'],
                'audio' => $row['usr_a_count'],
                'documents' => $row['usr_d_count']
            ]
        ];
    }
    
    private function getUserById($userId)
    {
        $query = "SELECT * FROM db_accountuser WHERE usr_id = ?";
        $result = $this->db->doQuery($query, [$userId]);
        
        return $this->db->doFetch($result);
    }
    
    private function logAdminAction($action, $data)
    {
        $logData = [
            'admin_id' => $_SESSION['user_id'] ?? null,
            'action' => $action,
            'data' => json_encode($data),
            'ip_address' => $this->getRealIpAddress(),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'created_at' => date('Y-m-d H:i:s')
        ];
        
        $this->db->doInsert('db_admin_logs', $logData);
    }
    
    private function getRealIpAddress()
    {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            return $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
            return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
        }
    }
    
    private function getModerationItemsByType($type, $table, $limit, $offset)
    {
        $query = "SELECT f.*, u.usr_user 
                  FROM {$table} f
                  JOIN db_accountuser u ON f.usr_id = u.usr_id
                  WHERE f.moderation_status IS NULL OR f.moderation_status = 'pending'
                  ORDER BY f.file_date DESC
                  LIMIT ? OFFSET ?";
        
        $result = $this->db->doQuery($query, [$limit, $offset]);
        
        $items = [];
        while ($row = $this->db->doFetch($result)) {
            $items[] = [
                'type' => $type,
                'id' => $row['file_key'],
                'title' => $row['file_title'],
                'description' => $row['file_description'] ?? '',
                'uploader' => $row['usr_user'],
                'uploaded_at' => $row['file_date'],
                'file_size' => $row['file_size'] ?? 0,
                'status' => $row['moderation_status'] ?? 'pending'
            ];
        }
        
        return $items;
    }
    
    private function checkDatabaseHealth()
    {
        try {
            $result = $this->db->doQuery("SELECT 1");
            
            if ($result) {
                return [
                    'status' => 'healthy',
                    'message' => 'Database connection working'
                ];
            } else {
                return [
                    'status' => 'unhealthy',
                    'issues' => ['Database query failed']
                ];
            }
        } catch (Exception $e) {
            return [
                'status' => 'unhealthy',
                'issues' => ['Database connection failed: ' . $e->getMessage()]
            ];
        }
    }
    
    private function checkFileSystemHealth()
    {
        $issues = [];
        
        $directories = [
            'f_data/temp',
            'f_data/processed',
            'f_data/media',
            'logs'
        ];
        
        foreach ($directories as $dir) {
            $fullPath = _FPATH . $dir;
            
            if (!is_dir($fullPath)) {
                $issues[] = "Directory missing: {$dir}";
            } elseif (!is_writable($fullPath)) {
                $issues[] = "Directory not writable: {$dir}";
            }
        }
        
        // Check disk space
        $freeSpace = disk_free_space('.');
        $totalSpace = disk_total_space('.');
        $usagePercent = (($totalSpace - $freeSpace) / $totalSpace) * 100;
        
        if ($usagePercent > 90) {
            $issues[] = "Disk usage critical: {$usagePercent}%";
        } elseif ($usagePercent > 80) {
            $issues[] = "Disk usage high: {$usagePercent}%";
        }
        
        if (empty($issues)) {
            return [
                'status' => 'healthy',
                'message' => 'File system healthy'
            ];
        } else {
            return [
                'status' => count($issues) > 2 ? 'unhealthy' : 'warning',
                'issues' => $issues
            ];
        }
    }
    
    private function checkExternalServices()
    {
        $issues = [];
        
        // Check FFmpeg
        $ffmpegOutput = shell_exec('ffmpeg -version 2>&1');
        if (strpos($ffmpegOutput, 'ffmpeg version') === false) {
            $issues[] = 'FFmpeg not available';
        }
        
        // Check Redis (optional)
        try {
            $redis = VRedis::getInstance();
            if (!$redis->isConnected()) {
                $issues[] = 'Redis not connected (using database fallback)';
            }
        } catch (Exception $e) {
            // Redis is optional, so this is just a warning
        }
        
        if (empty($issues)) {
            return [
                'status' => 'healthy',
                'message' => 'External services healthy'
            ];
        } else {
            return [
                'status' => 'warning',
                'issues' => $issues
            ];
        }
    }
}