<?php

declare(strict_types=1);

/**
 * UserManager
 * 
 * Manages users from super admin perspective
 */
class UserManager
{
    /**
     * Get all users with pagination
     */
    public static function getUsers(int $page = 1, int $perPage = 20, array $filters = []): array
    {
        $pdo = getPDO();
        $offset = ($page - 1) * $perPage;
        
        $where = ['1=1'];
        $params = [];

        if (!empty($filters['search'])) {
            $where[] = '(u.name LIKE ? OR u.email LIKE ?)';
            $params[] = '%' . $filters['search'] . '%';
            $params[] = '%' . $filters['search'] . '%';
        }

        if (isset($filters['is_active'])) {
            $where[] = 'u.is_active = ?';
            $params[] = $filters['is_active'];
        }

        if (isset($filters['is_banned'])) {
            $where[] = 'u.is_banned = ?';
            $params[] = $filters['is_banned'];
        }

        $whereClause = implode(' AND ', $where);

        // Get total count
        $countStmt = $pdo->prepare("SELECT COUNT(*) FROM users u WHERE $whereClause");
        $countStmt->execute($params);
        $total = (int)$countStmt->fetchColumn();

        // Get users
        $sql = "
            SELECT u.*, 
                   c.name as company_name, 
                   c.username as company_username,
                   (SELECT COUNT(*) FROM user_company_access WHERE user_id = u.id) as workspace_count
            FROM users u
            LEFT JOIN companies c ON u.company_id = c.id
            WHERE $whereClause
            ORDER BY u.created_at DESC
            LIMIT $perPage OFFSET $offset
        ";
        
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        $users = $stmt->fetchAll();

        return [
            'users' => $users,
            'total' => $total,
            'page' => $page,
            'per_page' => $perPage,
            'total_pages' => ceil($total / $perPage),
        ];
    }

    /**
     * Get a single user with details
     */
    public static function getUser(int $userId): ?array
    {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare('
            SELECT u.*, c.name as company_name, c.username as company_username
            FROM users u
            LEFT JOIN companies c ON u.company_id = c.id
            WHERE u.id = ?
        ');
        $stmt->execute([$userId]);
        $user = $stmt->fetch();

        if (!$user) {
            return null;
        }

        // Get user's workspaces
        $stmt = $pdo->prepare('
            SELECT c.*, uca.role as access_role
            FROM companies c
            JOIN user_company_access uca ON c.id = uca.company_id
            WHERE uca.user_id = ?
        ');
        $stmt->execute([$userId]);
        $user['workspaces'] = $stmt->fetchAll();

        return $user;
    }

    /**
     * Ban a user
     */
    public static function banUser(int $userId, string $reason = ''): bool
    {
        $pdo = getPDO();
        $stmt = $pdo->prepare('
            UPDATE users SET is_banned = 1, banned_at = NOW(), banned_reason = ?
            WHERE id = ?
        ');
        return $stmt->execute([$reason, $userId]);
    }

    /**
     * Unban a user
     */
    public static function unbanUser(int $userId): bool
    {
        $pdo = getPDO();
        $stmt = $pdo->prepare('
            UPDATE users SET is_banned = 0, banned_at = NULL, banned_reason = NULL
            WHERE id = ?
        ');
        return $stmt->execute([$userId]);
    }

    /**
     * Delete a user
     */
    public static function deleteUser(int $userId): bool
    {
        $pdo = getPDO();
        
        try {
            $pdo->beginTransaction();

            // Remove from workspaces
            $stmt = $pdo->prepare('DELETE FROM user_company_access WHERE user_id = ?');
            $stmt->execute([$userId]);

            // Remove from workspace members
            $stmt = $pdo->prepare('DELETE FROM workspace_members WHERE user_id = ?');
            $stmt->execute([$userId]);

            // Delete sessions
            $stmt = $pdo->prepare('DELETE FROM user_sessions WHERE user_id = ?');
            $stmt->execute([$userId]);

            // Delete user
            $stmt = $pdo->prepare('DELETE FROM users WHERE id = ?');
            $stmt->execute([$userId]);

            $pdo->commit();
            return true;
        } catch (Exception $e) {
            $pdo->rollBack();
            return false;
        }
    }

    /**
     * Get user statistics
     */
    public static function getStats(): array
    {
        $pdo = getPDO();

        $stats = [];

        // Total users
        $stmt = $pdo->query('SELECT COUNT(*) FROM users');
        $stats['total_users'] = (int)$stmt->fetchColumn();

        // Active users
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE is_active = 1 AND is_banned = 0');
        $stats['active_users'] = (int)$stmt->fetchColumn();

        // Banned users
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE is_banned = 1');
        $stats['banned_users'] = (int)$stmt->fetchColumn();

        // Users registered today
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE DATE(created_at) = CURDATE()');
        $stats['registered_today'] = (int)$stmt->fetchColumn();

        // Users registered this week
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)');
        $stats['registered_this_week'] = (int)$stmt->fetchColumn();

        // Users registered this month
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)');
        $stats['registered_this_month'] = (int)$stmt->fetchColumn();

        // Users logged in today
        $stmt = $pdo->query('SELECT COUNT(*) FROM users WHERE DATE(last_login_at) = CURDATE()');
        $stats['logged_in_today'] = (int)$stmt->fetchColumn();

        // Currently online (active in last 5 minutes)
        $stmt = $pdo->query('SELECT COUNT(*) FROM user_presence WHERE last_activity_at >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)');
        $stats['currently_online'] = (int)$stmt->fetchColumn();

        return $stats;
    }

    /**
     * Get online users
     */
    public static function getOnlineUsers(): array
    {
        $pdo = getPDO();
        $stmt = $pdo->query('
            SELECT up.*, u.name, u.email, c.name as company_name
            FROM user_presence up
            JOIN users u ON up.user_id = u.id
            LEFT JOIN companies c ON up.company_id = c.id
            WHERE up.last_activity_at >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)
            ORDER BY up.last_activity_at DESC
        ');
        return $stmt->fetchAll();
    }

    /**
     * Get a simple global activity heatmap grouped by hour of day
     * over the last N days, based on user_presence.
     *
     * Returns an array with keys:
     * - by_hour: [0..23] => count
     * - max_count: highest count across hours
     * - total_events: total presence events in range
     * - days: number of days considered
     */
    public static function getActivityHeatmap(int $days = 7): array
    {
        $pdo = getPDO();

        $days = max($days, 1);

        $end = new DateTime('today');
        $start = (clone $end)->modify('-' . ($days - 1) . ' days');

        $dateKeys = [];
        $dayLabels = [];
        $cursor = clone $start;
        while ($cursor <= $end) {
            $key = $cursor->format('Y-m-d');
            $dateKeys[] = $key;
            $dayLabels[] = $cursor->format('D');
            $cursor->modify('+1 day');
        }

        $grid = [];
        foreach ($dateKeys as $dateKey) {
            $grid[$dateKey] = [];
            for ($h = 0; $h < 24; $h++) {
                $grid[$dateKey][$h] = 0;
            }
        }

        $byHour = [];
        for ($h = 0; $h < 24; $h++) {
            $byHour[$h] = 0;
        }

        $since = $start->format('Y-m-d 00:00:00');

        $stmt = $pdo->prepare('
            SELECT DATE(last_activity_at) as activity_date,
                   HOUR(last_activity_at) as hour_bucket,
                   COUNT(*) as cnt
            FROM user_presence
            WHERE last_activity_at >= ?
            GROUP BY DATE(last_activity_at), HOUR(last_activity_at)
            ORDER BY activity_date, hour_bucket
        ');
        $stmt->execute([$since]);

        $totalEvents = 0;
        $maxCount = 0;

        foreach ($stmt->fetchAll() as $row) {
            $dateKey = $row['activity_date'] ?? null;
            $hour = (int)($row['hour_bucket'] ?? 0);
            $count = (int)($row['cnt'] ?? 0);

            if (!$dateKey || !isset($grid[$dateKey]) || $hour < 0 || $hour > 23) {
                continue;
            }

            $grid[$dateKey][$hour] = $count;
            $byHour[$hour] += $count;
            $totalEvents += $count;
            if ($count > $maxCount) {
                $maxCount = $count;
            }
        }

        return [
            'by_hour' => $byHour,
            'grid' => $grid,
            'day_keys' => $dateKeys,
            'day_labels' => $dayLabels,
            'max_count' => $maxCount,
            'total_events' => $totalEvents,
            'days' => $days,
        ];
    }

    /**
     * Login as user (for support purposes)
     */
    public static function loginAsUser(int $userId): ?string
    {
        $pdo = getPDO();
        
        $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ? AND is_active = 1 AND is_banned = 0');
        $stmt->execute([$userId]);
        $user = $stmt->fetch();

        if (!$user) {
            return null;
        }

        // Create a special session token
        $token = 'ADMIN_' . bin2hex(random_bytes(32));
        $expiresAt = date('Y-m-d H:i:s', time() + 3600); // 1 hour

        $stmt = $pdo->prepare('
            INSERT INTO user_sessions (user_id, session_token, expires_at, ip_address, user_agent)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $userId,
            $token,
            $expiresAt,
            $_SERVER['REMOTE_ADDR'] ?? null,
            'Admin Login: ' . ($_SERVER['HTTP_USER_AGENT'] ?? 'Unknown')
        ]);

        return $token;
    }
}
