<?php

declare(strict_types=1);

class DashboardManager
{
    

    private static array $widgets = [
        'stats_overview' => [
            'title' => 'Statistics Overview',
            'icon' => 'fa-chart-simple',
            'size' => 'full',
            'category' => 'stats',
            'description' => 'Key metrics at a glance: videos, categories, tags, performers, channels, pages, users, comments.',
            'removable' => false,
        ],
        'views_chart' => [
            'title' => 'Views Trend',
            'icon' => 'fa-chart-line',
            'size' => 'large',
            'category' => 'charts',
            'description' => 'Daily video views over the last 30 days.',
        ],
        'content_distribution' => [
            'title' => 'Content by Type',
            'icon' => 'fa-chart-pie',
            'size' => 'medium',
            'category' => 'charts',
            'description' => 'Distribution of videos by type (hetero, gay, hentai).',
        ],
        'video_status' => [
            'title' => 'Video Status',
            'icon' => 'fa-circle-dot',
            'size' => 'medium',
            'category' => 'charts',
            'description' => 'Breakdown of videos by status (published, draft, private).',
        ],
        'top_categories' => [
            'title' => 'Top Categories',
            'icon' => 'fa-ranking-star',
            'size' => 'medium',
            'category' => 'charts',
            'description' => 'Top 10 categories by video count.',
        ],
        'recent_videos' => [
            'title' => 'Recent Videos',
            'icon' => 'fa-film',
            'size' => 'large',
            'category' => 'content',
            'description' => 'The 10 most recently added videos.',
        ],
        'recent_comments' => [
            'title' => 'Recent Comments',
            'icon' => 'fa-comments',
            'size' => 'medium',
            'category' => 'content',
            'description' => 'The 10 most recent comments.',
        ],
        'top_videos' => [
            'title' => 'Top Videos',
            'icon' => 'fa-fire',
            'size' => 'large',
            'category' => 'content',
            'description' => 'Top 10 most viewed videos.',
        ],
        'recent_albums' => [
            'title' => 'Recent Albums',
            'icon' => 'fa-images',
            'size' => 'large',
            'category' => 'content',
            'description' => 'The 10 most recently added albums (galleries).',
        ],
        'top_albums' => [
            'title' => 'Top Albums',
            'icon' => 'fa-fire-flame-curved',
            'size' => 'large',
            'category' => 'content',
            'description' => 'Top 10 most viewed albums (galleries).',
        ],
        'pending_moderation' => [
            'title' => 'Pending Moderation',
            'icon' => 'fa-shield-halved',
            'size' => 'medium',
            'category' => 'content',
            'description' => 'Comments and reports awaiting moderation.',
        ],
        'quick_actions' => [
            'title' => 'Quick Actions',
            'icon' => 'fa-bolt',
            'size' => 'medium',
            'category' => 'tools',
            'description' => 'Shortcuts to frequent admin tasks.',
        ],
        'system_info' => [
            'title' => 'System Info',
            'icon' => 'fa-server',
            'size' => 'medium',
            'category' => 'system',
            'description' => 'PHP version, CMS version, disk space, database size.',
        ],
        'storage_overview' => [
            'title' => 'Storage Servers',
            'icon' => 'fa-hard-drive',
            'size' => 'medium',
            'category' => 'system',
            'description' => 'Storage server status and disk usage.',
        ],
        'user_activity' => [
            'title' => 'Recent Users',
            'icon' => 'fa-user-plus',
            'size' => 'medium',
            'category' => 'content',
            'description' => 'Recently registered users.',
        ],
        'inbox_summary' => [
            'title' => 'Inbox Summary',
            'icon' => 'fa-inbox',
            'size' => 'medium',
            'category' => 'content',
            'description' => 'Unread messages and pending reports.',
        ],
        'top_performers' => [
            'title' => 'Top Performers',
            'icon' => 'fa-star',
            'size' => 'medium',
            'category' => 'content',
            'description' => 'Top 10 performers by video count.',
        ],
        'transcode_overview' => [
            'title' => 'Transcode Servers',
            'icon' => 'fa-microchip',
            'size' => 'medium',
            'category' => 'system',
            'description' => 'Transcode server status, load and queue.',
        ],
    ];

    

    private static function defaultLayout(): array
    {
        return [
             
            ['id' => 'stats_overview', 'visible' => true],
             
            ['id' => 'views_chart', 'visible' => true],
            ['id' => 'quick_actions', 'visible' => true],
             
            ['id' => 'recent_videos', 'visible' => true],
            ['id' => 'pending_moderation', 'visible' => true],
             
            ['id' => 'system_info', 'visible' => true],
             
            ['id' => 'video_status', 'visible' => false],
            ['id' => 'content_distribution', 'visible' => false],
            ['id' => 'top_categories', 'visible' => false],
            ['id' => 'recent_comments', 'visible' => false],
            ['id' => 'top_videos', 'visible' => false],
            ['id' => 'recent_albums', 'visible' => true],
            ['id' => 'top_albums', 'visible' => false],
            ['id' => 'top_performers', 'visible' => false],
            ['id' => 'user_activity', 'visible' => false],
            ['id' => 'inbox_summary', 'visible' => false],
            ['id' => 'storage_overview', 'visible' => false],
            ['id' => 'transcode_overview', 'visible' => false],
        ];
    }

    

    public static function allWidgets(): array
    {
        return self::$widgets;
    }

    

    public static function getLayout(int $userId): array
    {
        $json = Setting::get("dashboard_layout_{$userId}");
        if ($json !== null) {
            $layout = json_decode($json, true);
            if (is_array($layout) && !empty($layout)) {
                 
                $existingIds = array_column($layout, 'id');
                foreach (self::$widgets as $id => $def) {
                    if (!in_array($id, $existingIds, true)) {
                        $layout[] = ['id' => $id, 'visible' => false];
                    }
                }
                 
                $layout = array_values(array_filter($layout, fn($w) => isset(self::$widgets[$w['id']])));
                return $layout;
            }
        }
        return self::defaultLayout();
    }

    

    public static function saveLayout(int $userId, array $layout): void
    {
         
        $clean = [];
        foreach ($layout as $item) {
            if (is_array($item) && isset($item['id']) && isset(self::$widgets[$item['id']])) {
                $clean[] = [
                    'id' => $item['id'],
                    'visible' => (bool) ($item['visible'] ?? true),
                ];
            }
        }
         
        foreach ($clean as &$w) {
            $def = self::$widgets[$w['id']] ?? [];
            if (isset($def['removable']) && $def['removable'] === false) {
                $w['visible'] = true;
            }
        }
        unset($w);

        Setting::set("dashboard_layout_{$userId}", json_encode($clean));
    }

    

    public static function resetLayout(int $userId): void
    {
        Setting::delete("dashboard_layout_{$userId}");
    }

    

    public static function getWidget(string $id): ?array
    {
        return self::$widgets[$id] ?? null;
    }

    

    public static function fetchData(array $layout): array
    {
        $data = [];
        $visibleIds = [];
        foreach ($layout as $item) {
            if (!empty($item['visible'])) {
                $visibleIds[] = $item['id'];
            }
        }

        foreach ($visibleIds as $id) {
            $method = 'data_' . $id;
            if (method_exists(self::class, $method)) {
                try {
                    $data[$id] = self::$method();
                } catch (\Throwable $e) {
                    $data[$id] = ['_error' => $e->getMessage()];
                }
            }
        }

        return $data;
    }

     

    private static function data_stats_overview(): array
    {
        $videoCount = Database::count('videos');
        $albumCount = Database::count('albums');
        $categoryCount = Database::count('categories');
        $tagCount = Database::count('tags');
        $performerCount = Database::count('performers');
        $channelCount = Database::count('channels');
        $pageCount = Database::count('pages');
        $userCount = Database::count('users');
        $commentCount = Database::count('comments');

        $row = Database::fetchOne(
            'SELECT COALESCE(SUM(views),0) as total_views,
                    SUM(CASE WHEN status="published" THEN 1 ELSE 0 END) as published,
                    SUM(CASE WHEN status="draft" THEN 1 ELSE 0 END) as draft
             FROM videos'
        );
        $totalViews = (int) ($row['total_views'] ?? 0);
        $publishedCount = (int) ($row['published'] ?? 0);
        $draftCount = (int) ($row['draft'] ?? 0);

        $pendingRow = Database::fetchOne('SELECT COUNT(*) as c FROM comments WHERE status="pending"');
        $pendingComments = (int) ($pendingRow['c'] ?? 0);

        return compact(
            'videoCount', 'albumCount', 'categoryCount', 'tagCount', 'performerCount',
            'channelCount', 'pageCount', 'userCount', 'commentCount',
            'totalViews', 'publishedCount', 'draftCount', 'pendingComments'
        );
    }

    private static function data_views_chart(): array
    {
         
        $hasViewLog = false;
        try {
            Database::fetchOne('SELECT 1 FROM video_view_log LIMIT 1');
            $hasViewLog = true;
        } catch (\Throwable) {}

        $days = [];
        $values = [];

        if ($hasViewLog) {
            $rows = Database::fetchAll(
                'SELECT DATE(viewed_at) as day, COUNT(*) as cnt
                 FROM video_view_log
                 WHERE viewed_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
                 GROUP BY DATE(viewed_at)
                 ORDER BY day ASC'
            );
            $mapped = [];
            foreach ($rows as $r) {
                $mapped[$r['day']] = (int) $r['cnt'];
            }
            for ($i = 29; $i >= 0; $i--) {
                $d = date('Y-m-d', strtotime("-{$i} days"));
                $days[] = date('M d', strtotime($d));
                $values[] = $mapped[$d] ?? 0;
            }
        } else {
             
            $rows = Database::fetchAll(
                'SELECT DATE(created_at) as day, COUNT(*) as cnt
                 FROM videos
                 WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
                 GROUP BY DATE(created_at)
                 ORDER BY day ASC'
            );
            $mapped = [];
            foreach ($rows as $r) {
                $mapped[$r['day']] = (int) $r['cnt'];
            }
            for ($i = 29; $i >= 0; $i--) {
                $d = date('Y-m-d', strtotime("-{$i} days"));
                $days[] = date('M d', strtotime($d));
                $values[] = $mapped[$d] ?? 0;
            }
        }

        return ['labels' => $days, 'values' => $values, 'source' => $hasViewLog ? 'views' : 'uploads'];
    }

    private static function data_content_distribution(): array
    {
        $rows = Database::fetchAll(
            'SELECT video_type, COUNT(*) as cnt FROM videos GROUP BY video_type ORDER BY cnt DESC'
        );
        $labels = [];
        $values = [];
        $typeLabels = ['hetero' => 'Straight', 'gay' => 'Gay', 'hentai' => 'Hentai'];
        foreach ($rows as $r) {
            $labels[] = $typeLabels[$r['video_type']] ?? ucfirst($r['video_type']);
            $values[] = (int) $r['cnt'];
        }
        return ['labels' => $labels, 'values' => $values];
    }

    private static function data_video_status(): array
    {
        $rows = Database::fetchAll(
            'SELECT status, COUNT(*) as cnt FROM videos GROUP BY status ORDER BY cnt DESC'
        );
        $labels = [];
        $values = [];
        $statusLabels = ['published' => 'Published', 'draft' => 'Draft', 'private' => 'Private'];
        foreach ($rows as $r) {
            $labels[] = $statusLabels[$r['status']] ?? ucfirst($r['status']);
            $values[] = (int) $r['cnt'];
        }
        return ['labels' => $labels, 'values' => $values];
    }

    private static function data_top_categories(): array
    {
        $rows = Database::fetchAll(
            'SELECT name, video_count FROM categories ORDER BY video_count DESC LIMIT 10'
        );
        $labels = [];
        $values = [];
        foreach ($rows as $r) {
            $labels[] = $r['name'];
            $values[] = (int) $r['video_count'];
        }
        return ['labels' => $labels, 'values' => $values];
    }

    private static function data_recent_videos(): array
    {
        return Database::fetchAll(
            'SELECT id, title, slug, status, views, likes, duration, thumbnail, video_folder, storage_id, created_at
             FROM videos ORDER BY created_at DESC LIMIT 10'
        );
    }

    private static function data_recent_comments(): array
    {
        return Database::fetchAll(
            'SELECT c.id, c.body, c.status, c.created_at, c.video_id,
                    COALESCE(u.username, c.guest_name, "Anonymous") as username,
                    v.title as video_title
             FROM comments c
             LEFT JOIN users u ON c.user_id = u.id
             LEFT JOIN videos v ON c.video_id = v.id
             ORDER BY c.created_at DESC LIMIT 10'
        );
    }

    private static function data_top_videos(): array
    {
        return Database::fetchAll(
            'SELECT id, title, slug, status, views, likes, duration, thumbnail, video_folder, storage_id, created_at
             FROM videos WHERE status = "published" ORDER BY views DESC LIMIT 10'
        );
    }

    private static function data_recent_albums(): array
    {
        return Database::fetchAll(
            'SELECT id, title, slug, status, views, likes, image_count, cover_file, album_folder, storage_id, images, created_at
             FROM albums ORDER BY created_at DESC LIMIT 10'
        );
    }

    private static function data_top_albums(): array
    {
        return Database::fetchAll(
            'SELECT id, title, slug, status, views, likes, image_count, cover_file, album_folder, storage_id, images, created_at
             FROM albums WHERE status = "published" ORDER BY views DESC LIMIT 10'
        );
    }

    private static function data_pending_moderation(): array
    {
        $pendingComments = Database::fetchAll(
            'SELECT c.id, c.body, c.created_at, c.video_id,
                    COALESCE(u.username, c.guest_name, "Anonymous") as username,
                    v.title as video_title
             FROM comments c
             LEFT JOIN users u ON c.user_id = u.id
             LEFT JOIN videos v ON c.video_id = v.id
             WHERE c.status = "pending"
             ORDER BY c.created_at DESC LIMIT 10'
        );
        $pendingReports = Database::fetchAll(
            'SELECT r.id, r.reason, r.details, r.created_at, r.video_id,
                    v.title as video_title
             FROM reports r
             LEFT JOIN videos v ON r.video_id = v.id
             WHERE r.status = "pending"
             ORDER BY r.created_at DESC LIMIT 10'
        );
        $pendingCommentCount = (int) (Database::fetchOne('SELECT COUNT(*) as c FROM comments WHERE status="pending"')['c'] ?? 0);
        $pendingReportCount = (int) (Database::fetchOne('SELECT COUNT(*) as c FROM reports WHERE status="pending"')['c'] ?? 0);

        return [
            'comments' => $pendingComments,
            'reports' => $pendingReports,
            'commentCount' => $pendingCommentCount,
            'reportCount' => $pendingReportCount,
        ];
    }

    private static function data_quick_actions(): array
    {
         
        $actions = [
            ['label' => 'Add Video', 'url' => '/admin/videos/create', 'icon' => 'fa-plus', 'color' => 'blue'],
            ['label' => 'Add Album', 'url' => '/admin/albums/create', 'icon' => 'fa-images', 'color' => 'indigo'],
            ['label' => 'Add Category', 'url' => '/admin/categories/create', 'icon' => 'fa-folder-plus', 'color' => 'amber'],
            ['label' => 'Add Performer', 'url' => '/admin/performers/create', 'icon' => 'fa-user-plus', 'color' => 'pink'],
            ['label' => 'Add Page', 'url' => '/admin/pages/create', 'icon' => 'fa-file-circle-plus', 'color' => 'cyan'],
            ['label' => 'Import Videos', 'url' => '/admin/import', 'icon' => 'fa-file-import', 'color' => 'green'],
            ['label' => 'Settings', 'url' => '/admin/settings', 'icon' => 'fa-gear', 'color' => 'gray'],
        ];
        return $actions;
    }

    private static function data_system_info(): array
    {
        $dbSize = Database::fetchOne(
            "SELECT ROUND(SUM(data_length + index_length) / 1048576, 2) as size_mb
             FROM information_schema.tables WHERE table_schema = DATABASE()"
        );

        $diskFree = @disk_free_space(APP_ROOT);
        $diskTotal = @disk_total_space(APP_ROOT);

        return [
            'php_version' => PHP_VERSION,
            'cms_version' => defined('APP_VERSION') ? APP_VERSION : '1.0.0',
            'db_size_mb' => (float) ($dbSize['size_mb'] ?? 0),
            'disk_free' => $diskFree !== false ? $diskFree : 0,
            'disk_total' => $diskTotal !== false ? $diskTotal : 0,
            'os' => PHP_OS,
            'server' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'mysql_version' => Database::fetchOne('SELECT VERSION() as v')['v'] ?? 'Unknown',
        ];
    }

    private static function data_storage_overview(): array
    {
        try {
            $storages = Database::fetchAll(
                'SELECT id, name, driver, health_status, health_message, status, disk_total, disk_used, max_usage_pct, file_count
                 FROM media_storages ORDER BY sort_order ASC, id ASC'
            );
        } catch (\Throwable) {
            $storages = [];
        }
        return $storages;
    }

    private static function data_user_activity(): array
    {
        return Database::fetchAll(
            'SELECT id, username, email, role, is_active, created_at
             FROM users ORDER BY created_at DESC LIMIT 10'
        );
    }

    private static function data_inbox_summary(): array
    {
        $unreadMessages = (int) (Database::fetchOne('SELECT COUNT(*) as c FROM contact_messages WHERE is_read = 0')['c'] ?? 0);
        $totalMessages = Database::count('contact_messages');
        $pendingReports = (int) (Database::fetchOne('SELECT COUNT(*) as c FROM reports WHERE status="pending"')['c'] ?? 0);
        $totalReports = Database::count('reports');

        return [
            'unreadMessages' => $unreadMessages,
            'totalMessages' => $totalMessages,
            'pendingReports' => $pendingReports,
            'totalReports' => $totalReports,
        ];
    }

    private static function data_top_performers(): array
    {
        $rows = Database::fetchAll(
            'SELECT id, name, slug, photo, video_count, total_views
             FROM performers ORDER BY video_count DESC LIMIT 10'
        );
         
        VideoAsset::assignUniqueThumbFolders($rows, 'video_performers', 'performer_id', 'photo');
        return $rows;
    }

    private static function data_transcode_overview(): array
    {
        $servers = [];
        try {
            $servers = Database::fetchAll(
                'SELECT id, name, url, max_jobs, active_jobs, is_active, status, last_check, last_error
                 FROM transcode_servers ORDER BY id ASC'
            );
        } catch (\Throwable) {}

        $queue = ['pending' => 0, 'processing' => 0, 'completed' => 0, 'failed' => 0];
        try {
            $rows = Database::fetchAll(
                "SELECT status, COUNT(DISTINCT video_id) as cnt FROM transcode_jobs GROUP BY status"
            );
            foreach ($rows as $r) {
                $key = $r['status'];
                if (isset($queue[$key])) {
                    $queue[$key] = (int) $r['cnt'];
                }
            }
        } catch (\Throwable) {}

         
        $paidAtRisk = ['failed' => 0, 'refunded' => 0, 'refund_pending' => 0, 'owed_credits' => 0.0];
        try {
            $row = Database::fetchOne(
                "SELECT COUNT(*) AS failed,
                        SUM(cd.refunded_at IS NOT NULL) AS refunded,
                        SUM(cd.refund_amount > 0 AND cd.refunded_at IS NULL) AS refund_pending,
                        COALESCE(SUM(CASE WHEN cd.refunded_at IS NULL THEN cd.refund_amount ELSE 0 END), 0) AS owed_credits
                 FROM videos v JOIN catalogue_downloads cd ON cd.video_id = v.id
                 WHERE v.status = 'error' AND cd.cost_credits > 0"
            ) ?: [];
            $paidAtRisk['failed']         = (int)($row['failed'] ?? 0);
            $paidAtRisk['refunded']       = (int)($row['refunded'] ?? 0);
            $paidAtRisk['refund_pending'] = (int)($row['refund_pending'] ?? 0);
            $paidAtRisk['owed_credits']   = (float)($row['owed_credits'] ?? 0);
        } catch (\Throwable) {}

         
        $allOffline = false;
        $active = array_filter($servers, fn($s) => (int)($s['is_active'] ?? 0) === 1);
        $online = array_filter($active, fn($s) => ($s['status'] ?? '') === 'online');
        if (!empty($active) && empty($online) && (int)($queue['pending'] ?? 0) > 0) $allOffline = true;

        return ['servers' => $servers, 'queue' => $queue, 'paid_at_risk' => $paidAtRisk, 'all_offline' => $allOffline];
    }
}
