<?php
/**
 * Klasa Reports - raporty aktywności i API
 */

class Reports
{
    private Database $db;
    
    public function __construct()
    {
        $this->db = Database::getInstance();
    }
    
    /**
     * Raport aktywności użytkowników
     */
    public function getUserActivityReport(int $days = 30, ?int $userId = null): array
    {
        $params = ['days' => $days];
        $userFilter = '';
        
        if ($userId) {
            $userFilter = 'AND u.id = :user_id';
            $params['user_id'] = $userId;
        }
        
        // Statystyki per użytkownik
        $userStats = $this->db->fetchAll(
            "SELECT u.id, u.username, u.role, u.login_count, u.last_login,
                    u.api_calls_count, u.created_at,
                    (SELECT COUNT(*) FROM login_history WHERE user_id = u.id AND created_at > datetime('now', '-' || :days || ' days')) as logins_period,
                    (SELECT COUNT(*) FROM login_history WHERE user_id = u.id AND created_at > datetime('now', '-' || :days || ' days') AND success = 0) as failed_logins,
                    (SELECT COUNT(*) FROM logs WHERE user_id = u.id AND created_at > datetime('now', '-' || :days || ' days')) as actions_count,
                    (SELECT COUNT(*) FROM devices WHERE user_id = u.id) as devices_count,
                    (SELECT COUNT(*) FROM playlists p JOIN devices d ON p.device_id = d.id WHERE d.user_id = u.id) as playlists_count
             FROM users u
             WHERE u.created_at <= datetime('now') {$userFilter}
             ORDER BY logins_period DESC",
            $params
        );
        
        // Aktywność per dzień
        $dailyActivity = $this->db->fetchAll(
            "SELECT date(created_at) as date,
                    COUNT(DISTINCT user_id) as unique_users,
                    SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successful_logins,
                    SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failed_logins
             FROM login_history
             WHERE created_at > datetime('now', '-' || :days || ' days')
             GROUP BY date(created_at)
             ORDER BY date ASC",
            ['days' => $days]
        );
        
        // Top akcje
        $topActions = $this->db->fetchAll(
            "SELECT action, COUNT(*) as count
             FROM logs
             WHERE created_at > datetime('now', '-' || :days || ' days')
             GROUP BY action
             ORDER BY count DESC
             LIMIT 15",
            ['days' => $days]
        );
        
        // Nowi użytkownicy per dzień
        $newUsers = $this->db->fetchAll(
            "SELECT date(created_at) as date, COUNT(*) as count
             FROM users
             WHERE created_at > datetime('now', '-' || :days || ' days')
             GROUP BY date(created_at)
             ORDER BY date ASC",
            ['days' => $days]
        );
        
        // Podsumowanie
        $summary = $this->db->fetchOne(
            "SELECT 
                (SELECT COUNT(*) FROM users WHERE is_active = 1) as active_users,
                (SELECT COUNT(*) FROM users WHERE last_login > datetime('now', '-' || :days || ' days')) as users_logged_in,
                (SELECT COUNT(*) FROM login_history WHERE created_at > datetime('now', '-' || :days || ' days')) as total_logins,
                (SELECT COUNT(*) FROM logs WHERE created_at > datetime('now', '-' || :days || ' days')) as total_actions",
            ['days' => $days]
        );
        
        return [
            'user_stats' => $userStats,
            'daily_activity' => $dailyActivity,
            'top_actions' => $topActions,
            'new_users' => $newUsers,
            'summary' => $summary,
            'period_days' => $days
        ];
    }
    
    /**
     * Raport zużycia API
     */
    public function getApiUsageReport(int $days = 30, ?int $userId = null): array
    {
        $params = ['days' => $days];
        $userFilter = '';
        
        if ($userId) {
            $userFilter = 'AND d.user_id = :user_id';
            $params['user_id'] = $userId;
        }
        
        // Statystyki per urządzenie
        $deviceStats = $this->db->fetchAll(
            "SELECT d.id, d.mac, d.name, d.api_calls_count, d.api_last_call, d.last_ip,
                    u.username as owner,
                    (SELECT COUNT(*) FROM api_logs WHERE device_id = d.id AND created_at > datetime('now', '-' || :days || ' days')) as calls_period,
                    (SELECT COUNT(*) FROM playlists WHERE device_id = d.id) as playlists_count
             FROM devices d
             JOIN users u ON d.user_id = u.id
             WHERE 1=1 {$userFilter}
             ORDER BY calls_period DESC
             LIMIT 50",
            $params
        );
        
        // Statystyki per użytkownik
        $userStats = $this->db->fetchAll(
            "SELECT u.id, u.username, u.role, u.api_calls_count,
                    (SELECT COUNT(*) FROM api_logs al JOIN devices d ON al.device_id = d.id WHERE d.user_id = u.id AND al.created_at > datetime('now', '-' || :days || ' days')) as calls_period,
                    (SELECT COUNT(*) FROM devices WHERE user_id = u.id) as devices_count
             FROM users u
             WHERE 1=1 {$userFilter}
             ORDER BY calls_period DESC
             LIMIT 30",
            $params
        );
        
        // Wywołania per dzień
        $dailyCalls = $this->db->fetchAll(
            "SELECT date(al.created_at) as date,
                    COUNT(*) as total_calls,
                    COUNT(DISTINCT al.device_id) as unique_devices,
                    SUM(al.playlists_count) as total_playlists
             FROM api_logs al
             " . ($userId ? "JOIN devices d ON al.device_id = d.id" : "") . "
             WHERE al.created_at > datetime('now', '-' || :days || ' days')
             " . ($userId ? "AND d.user_id = :user_id" : "") . "
             GROUP BY date(al.created_at)
             ORDER BY date ASC",
            $params
        );
        
        // Wywołania per godzinę (średnio)
        $hourlyCalls = $this->db->fetchAll(
            "SELECT strftime('%H', al.created_at) as hour, COUNT(*) / :days as avg_calls
             FROM api_logs al
             " . ($userId ? "JOIN devices d ON al.device_id = d.id" : "") . "
             WHERE al.created_at > datetime('now', '-' || :days || ' days')
             " . ($userId ? "AND d.user_id = :user_id" : "") . "
             GROUP BY hour
             ORDER BY hour ASC",
            $params
        );
        
        // Top endpointy
        $topEndpoints = $this->db->fetchAll(
            "SELECT endpoint, COUNT(*) as count
             FROM api_logs
             WHERE created_at > datetime('now', '-' || :days || ' days')
             GROUP BY endpoint
             ORDER BY count DESC
             LIMIT 10",
            ['days' => $days]
        );
        
        // Top IP
        $topIps = $this->db->fetchAll(
            "SELECT ip_address, COUNT(*) as count,
                    (SELECT mac FROM devices WHERE id = (SELECT device_id FROM api_logs WHERE ip_address = al.ip_address LIMIT 1)) as sample_mac
             FROM api_logs al
             WHERE created_at > datetime('now', '-' || :days || ' days')
             GROUP BY ip_address
             ORDER BY count DESC
             LIMIT 15",
            ['days' => $days]
        );
        
        // Podsumowanie
        $summary = $this->db->fetchOne(
            "SELECT 
                (SELECT COUNT(*) FROM api_logs WHERE created_at > datetime('now', '-' || :days || ' days')) as total_calls,
                (SELECT COUNT(DISTINCT device_id) FROM api_logs WHERE created_at > datetime('now', '-' || :days || ' days')) as active_devices,
                (SELECT COUNT(DISTINCT ip_address) FROM api_logs WHERE created_at > datetime('now', '-' || :days || ' days')) as unique_ips,
                (SELECT COALESCE(AVG(playlists_count), 0) FROM api_logs WHERE created_at > datetime('now', '-' || :days || ' days')) as avg_playlists_per_call",
            ['days' => $days]
        );
        
        return [
            'device_stats' => $deviceStats,
            'user_stats' => $userStats,
            'daily_calls' => $dailyCalls,
            'hourly_calls' => $hourlyCalls,
            'top_endpoints' => $topEndpoints,
            'top_ips' => $topIps,
            'summary' => $summary,
            'period_days' => $days
        ];
    }
    
    /**
     * Alias dla getApiUsageReport (dla kompatybilności)
     */
    public function getApiReport(int $days = 30, ?int $deviceId = null): array
    {
        return $this->getApiUsageReport($days, $deviceId);
    }
    
    /**
     * Szybki podgląd statystyk (dla dashboardu)
     */
    public function getQuickStats(): array
    {
        return $this->db->fetchOne(
            "SELECT 
                (SELECT COUNT(*) FROM users WHERE is_active = 1) as active_users,
                (SELECT COUNT(*) FROM devices WHERE is_blocked = 0) as active_devices,
                (SELECT COUNT(*) FROM playlists WHERE is_active = 1) as active_playlists,
                (SELECT COUNT(*) FROM login_history WHERE created_at > datetime('now', '-24 hours')) as logins_24h,
                (SELECT COUNT(*) FROM api_logs WHERE created_at > datetime('now', '-24 hours')) as api_calls_24h,
                (SELECT COUNT(*) FROM logs WHERE created_at > datetime('now', '-24 hours')) as actions_24h"
        );
    }
    
    /**
     * Trend statystyk (porównanie z poprzednim okresem)
     */
    public function getTrends(int $days = 7): array
    {
        $current = $this->db->fetchOne(
            "SELECT 
                (SELECT COUNT(*) FROM login_history WHERE created_at > datetime('now', '-' || :days || ' days')) as logins,
                (SELECT COUNT(*) FROM api_logs WHERE created_at > datetime('now', '-' || :days || ' days')) as api_calls,
                (SELECT COUNT(*) FROM users WHERE created_at > datetime('now', '-' || :days || ' days')) as new_users,
                (SELECT COUNT(*) FROM devices WHERE created_at > datetime('now', '-' || :days || ' days')) as new_devices",
            ['days' => $days]
        );
        
        $previous = $this->db->fetchOne(
            "SELECT 
                (SELECT COUNT(*) FROM login_history WHERE created_at BETWEEN datetime('now', '-' || :days2 || ' days') AND datetime('now', '-' || :days || ' days')) as logins,
                (SELECT COUNT(*) FROM api_logs WHERE created_at BETWEEN datetime('now', '-' || :days2 || ' days') AND datetime('now', '-' || :days || ' days')) as api_calls,
                (SELECT COUNT(*) FROM users WHERE created_at BETWEEN datetime('now', '-' || :days2 || ' days') AND datetime('now', '-' || :days || ' days')) as new_users,
                (SELECT COUNT(*) FROM devices WHERE created_at BETWEEN datetime('now', '-' || :days2 || ' days') AND datetime('now', '-' || :days || ' days')) as new_devices",
            ['days' => $days, 'days2' => $days * 2]
        );
        
        // Oblicz procentowe zmiany
        $trends = [];
        foreach (['logins', 'api_calls', 'new_users', 'new_devices'] as $metric) {
            $curr = (int)($current[$metric] ?? 0);
            $prev = (int)($previous[$metric] ?? 0);
            
            if ($prev > 0) {
                $change = round((($curr - $prev) / $prev) * 100, 1);
            } elseif ($curr > 0) {
                $change = 100;
            } else {
                $change = 0;
            }
            
            $trends[$metric] = [
                'current' => $curr,
                'previous' => $prev,
                'change' => $change,
                'direction' => $change > 0 ? 'up' : ($change < 0 ? 'down' : 'stable')
            ];
        }
        
        return $trends;
    }
    
    // ==================== EKSPORT CSV ====================
    
    /**
     * Eksportuj użytkowników do CSV
     */
    public function exportUsersCsv(?array $filters = null): string
    {
        $where = [];
        $params = [];
        
        if (!empty($filters['role'])) {
            $where[] = "u.role = :role";
            $params['role'] = $filters['role'];
        }
        
        if (!empty($filters['parent_id'])) {
            $where[] = "u.parent_id = :parent_id";
            $params['parent_id'] = $filters['parent_id'];
        }
        
        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
        
        $users = $this->db->fetchAll(
            "SELECT u.id, u.username, u.role, u.is_active,
                    u.device_limit, u.playlist_limit,
                    u.max_users, u.max_devices, u.max_playlists,
                    u.created_at, u.last_login,
                    p.username as parent_username,
                    (SELECT COUNT(*) FROM devices WHERE user_id = u.id) as devices_count,
                    (SELECT COUNT(*) FROM playlists pl JOIN devices d ON pl.device_id = d.id WHERE d.user_id = u.id) as playlists_count
             FROM users u
             LEFT JOIN users p ON u.parent_id = p.id
             {$whereClause}
             ORDER BY u.id",
            $params
        );
        
        $headers = ['ID', 'Nazwa użytkownika', 'Rola', 'Aktywny', 'Limit urządzeń', 'Limit playlist', 
                    'Max users', 'Max devices', 'Max playlists', 'Reseller', 'Urządzeń', 'Playlist', 
                    'Data utworzenia', 'Ostatnie logowanie'];
        
        $rows = [];
        foreach ($users as $user) {
            $rows[] = [
                $user['id'], $user['username'], $user['role'], $user['is_active'] ? 'Tak' : 'Nie',
                $user['device_limit'], $user['playlist_limit'],
                $user['max_users'] ?? '', $user['max_devices'] ?? '', $user['max_playlists'] ?? '',
                $user['parent_username'] ?? '', $user['devices_count'], $user['playlists_count'],
                $user['created_at'], $user['last_login'] ?? 'Nigdy'
            ];
        }
        
        return $this->generateCsv($headers, $rows);
    }
    
    /**
     * Eksportuj urządzenia do CSV
     */
    public function exportDevicesCsv(?int $userId = null): string
    {
        $where = [];
        $params = [];
        
        if ($userId) {
            $where[] = "d.user_id = :user_id";
            $params['user_id'] = $userId;
        }
        
        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
        
        $devices = $this->db->fetchAll(
            "SELECT d.id, d.mac, d.code, d.name, d.is_blocked, d.created_at, d.updated_at, u.username,
                    (SELECT COUNT(*) FROM playlists WHERE device_id = d.id) as playlists_count
             FROM devices d
             JOIN users u ON d.user_id = u.id
             {$whereClause}
             ORDER BY d.id",
            $params
        );
        
        $headers = ['ID', 'MAC', 'Kod', 'Nazwa', 'Właściciel', 'Playlist', 'Zablokowane', 'Data utworzenia', 'Ostatnia aktualizacja'];
        
        $rows = [];
        foreach ($devices as $device) {
            $rows[] = [
                $device['id'], $device['mac'], $device['code'], $device['name'], $device['username'],
                $device['playlists_count'], $device['is_blocked'] ? 'Tak' : 'Nie',
                $device['created_at'], $device['updated_at']
            ];
        }
        
        return $this->generateCsv($headers, $rows);
    }
    
    /**
     * Eksportuj playlisty do CSV
     */
    public function exportPlaylistsCsv(?int $userId = null, ?int $deviceId = null): string
    {
        $where = [];
        $params = [];
        
        if ($userId) {
            $where[] = "d.user_id = :user_id";
            $params['user_id'] = $userId;
        }
        
        if ($deviceId) {
            $where[] = "p.device_id = :device_id";
            $params['device_id'] = $deviceId;
        }
        
        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
        
        $playlists = $this->db->fetchAll(
            "SELECT p.id, p.name, p.type, p.is_active, p.sort_order, p.config_json, p.update_date, p.created_at,
                    d.mac, d.name as device_name, u.username
             FROM playlists p
             JOIN devices d ON p.device_id = d.id
             JOIN users u ON d.user_id = u.id
             {$whereClause}
             ORDER BY p.id",
            $params
        );
        
        $headers = ['ID', 'Nazwa', 'Typ', 'Aktywna', 'Kolejność', 'Urządzenie', 'MAC', 'Właściciel', 'Host/URL', 'Użytkownik', 'Hasło', 'Port', 'Data aktualizacji', 'Data utworzenia'];
        
        $rows = [];
        foreach ($playlists as $playlist) {
            $config = json_decode($playlist['config_json'], true) ?: [];
            
            // Wyciągnij dane w zależności od typu playlisty
            $hostUrl = '';
            $username = '';
            $password = '';
            $port = '';
            
            switch ($playlist['type']) {
                case 'xtream':
                    $hostUrl = $config['host'] ?? '';
                    $username = $config['username'] ?? '';
                    $password = $config['password'] ?? '';
                    $port = $config['port'] ?? '';
                    break;
                case 'm3u':
                    $hostUrl = $config['url'] ?? '';
                    break;
                case 'stalker':
                    $hostUrl = $config['server_url'] ?? $config['url'] ?? '';
                    $username = $config['mac_address'] ?? $config['mac'] ?? '';
                    $password = $config['serial_number'] ?? $config['token'] ?? '';
                    break;
            }
            
            $rows[] = [
                $playlist['id'],
                $playlist['name'],
                $playlist['type'],
                $playlist['is_active'] ? 'Tak' : 'Nie',
                $playlist['sort_order'],
                $playlist['device_name'] ?: $playlist['mac'],
                $playlist['mac'],
                $playlist['username'],
                $hostUrl,
                $username,
                $password,
                $port,
                $playlist['update_date'] ? date('Y-m-d H:i', $playlist['update_date']) : '',
                $playlist['created_at']
            ];
        }
        
        return $this->generateCsv($headers, $rows);
    }
    
    /**
     * Eksportuj historię logowań do CSV
     */
    public function exportLoginHistoryCsv(?int $days = 30): string
    {
        $logins = $this->db->fetchAll(
            "SELECT lh.*, u.username
             FROM login_history lh
             LEFT JOIN users u ON lh.user_id = u.id
             WHERE lh.created_at > datetime('now', '-' || :days || ' days')
             ORDER BY lh.created_at DESC",
            ['days' => $days]
        );
        
        $headers = ['ID', 'Użytkownik', 'IP', 'Przeglądarka', 'System', 'Typ urządzenia', 'Kraj', 'Miasto', 'Sukces', 'Powód błędu', 'Data'];
        
        $rows = [];
        foreach ($logins as $login) {
            $rows[] = [
                $login['id'], $login['username'], $login['ip_address'], $login['browser'], $login['os'],
                $login['device_type'], $login['country'], $login['city'],
                $login['success'] ? 'Tak' : 'Nie', $login['failure_reason'] ?? '', $login['created_at']
            ];
        }
        
        return $this->generateCsv($headers, $rows);
    }
    
    /**
     * Generuj CSV
     */
    private function generateCsv(array $headers, array $rows): string
    {
        $output = fopen('php://temp', 'r+');
        
        // BOM dla UTF-8 w Excel
        fputs($output, "\xEF\xBB\xBF");
        
        // Nagłówki - pełna sygnatura fputcsv dla PHP 8.1+
        fputcsv($output, $headers, ';', '"', '\\');
        
        // Wiersze
        foreach ($rows as $row) {
            fputcsv($output, $row, ';', '"', '\\');
        }
        
        rewind($output);
        $csv = stream_get_contents($output);
        fclose($output);
        
        return $csv;
    }
    
    /**
     * Wyślij CSV jako download
     */
    public function sendCsvDownload(string $csv, string $filename): void
    {
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . strlen($csv));
        header('Cache-Control: no-cache, no-store, must-revalidate');
        echo $csv;
        exit;
    }
}
