<?php

/**
 * Script to manage user sessions
 * Usage:
 *   php scripts/session-manager.php list [user_id]     - List sessions for a user (or all if no user_id)
 *   php scripts/session-manager.php expire [user_id]   - Expire all sessions for a user
 */

require __DIR__.'/../vendor/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();

if ($argc < 2) {
    echo "Usage:\n";
    echo "  php session-manager.php list [user_id]     - List sessions\n";
    echo "  php session-manager.php expire [user_id]   - Expire sessions\n";
    exit(1);
}

$action = $argv[1];
$userId = isset($argv[2]) ? (int) $argv[2] : null;

$sessionDriver = config('session.driver');
echo "Session driver: {$sessionDriver}\n\n";

if ($sessionDriver === 'database') {
    // Database sessions
    $table = config('session.table', 'sessions');

    echo "Querying database sessions from table '{$table}'...\n";

    $query = DB::table($table);
    if ($userId) {
        $query->where('user_id', $userId);
    } else {
        $query->whereNotNull('user_id'); // Only show logged-in sessions
    }

    $dbSessions = $query->get();
    echo "Found " . count($dbSessions) . " session(s)\n\n";

} elseif ($sessionDriver === 'redis') {
    // Redis sessions
    $redis = \Illuminate\Support\Facades\Redis::connection(config('session.connection') ?: 'default');
    $prefix = config('database.redis.options.prefix', '');

    echo "Scanning Redis for sessions...\n";
    $cursor = '0';
    $allKeys = [];

    do {
        $result = $redis->scan($cursor, ['match' => '*laravel_session:*', 'count' => 1000]);
        $cursor = $result[0];
        $keys = $result[1] ?? [];
        $allKeys = array_merge($allKeys, $keys);
    } while ($cursor !== '0');

    echo "Found " . count($allKeys) . " total session keys\n\n";
} else {
    echo "Unsupported session driver: {$sessionDriver}\n";
    exit(1);
}

function unserializeSession($data) {
    $result = [];
    if (empty($data)) return $result;

    // Try to find user ID in serialized data
    if (preg_match('/login_web_[a-f0-9]+";i:(\d+)/', $data, $matches)) {
        $result['user_id'] = (int) $matches[1];
    }

    // Try to find last activity
    if (preg_match('/last_activity";i:(\d+)/', $data, $matches)) {
        $result['last_activity'] = $matches[1];
    }

    // Try to find activeProfileType
    if (preg_match('/activeProfileType";s:\d+:"([^"]+)"/', $data, $matches)) {
        $result['profile_type'] = $matches[1];
    }

    return $result;
}

$sessions = [];

if ($sessionDriver === 'database') {
    // Process database sessions
    foreach ($dbSessions as $session) {
        $parsed = unserializeSession($session->payload);

        // Determine guard from column (if exists) or fallback to session data
        $guard = $session->guard ?? $parsed['profile_type'] ?? 'web';

        // Map guard to friendly name
        $guardMap = [
            'web' => 'User',
            'bank' => 'Bank',
            'organization' => 'Organization',
            'admin' => 'Admin',
        ];
        $profileType = $guardMap[$guard] ?? ucfirst($guard);

        $sessions[] = [
            'id' => $session->id,
            'user_id' => $session->user_id,
            'guard' => $guard,
            'last_activity' => $session->last_activity,
            'profile_type' => $profileType,
            'ip_address' => $session->ip_address,
            'user_agent' => substr($session->user_agent, 0, 50),
        ];
    }
} elseif ($sessionDriver === 'redis') {
    // Process Redis sessions
    foreach ($allKeys as $key) {
        $sessionData = $redis->get($key);
        if ($sessionData) {
            $parsed = unserializeSession($sessionData);

            if (isset($parsed['user_id'])) {
                // Filter by user if specified
                if ($userId === null || $parsed['user_id'] === $userId) {
                    $sessions[] = [
                        'key' => $key,
                        'user_id' => $parsed['user_id'],
                        'last_activity' => $parsed['last_activity'] ?? null,
                        'profile_type' => $parsed['profile_type'] ?? 'User',
                        'ttl' => $redis->ttl($key),
                    ];
                }
            }
        }
    }
}

if ($action === 'list') {
    if (empty($sessions)) {
        echo "No active sessions found" . ($userId ? " for user {$userId}" : "") . "\n";
    } else {
        echo "Active sessions" . ($userId ? " for user {$userId}" : "") . ":\n";
        echo str_repeat("=", 130) . "\n";

        if ($sessionDriver === 'database') {
            printf("%-10s %-12s %-20s %-20s %-20s %-30s\n", "User ID", "Guard", "Last Activity", "Profile Type", "IP Address", "User Agent");
        } else {
            printf("%-10s %-30s %-20s %-15s %s\n", "User ID", "Last Activity", "Profile Type", "TTL (sec)", "Session Key");
        }

        echo str_repeat("-", 130) . "\n";

        foreach ($sessions as $session) {
            $lastActivity = $session['last_activity'] ? date('Y-m-d H:i:s', $session['last_activity']) : 'Unknown';
            $profileType = basename(str_replace('\\', '/', $session['profile_type']));

            if ($sessionDriver === 'database') {
                printf("%-10s %-12s %-20s %-20s %-20s %-30s\n",
                    $session['user_id'] ?? 'N/A',
                    $session['guard'] ?? 'web',
                    $lastActivity,
                    $profileType,
                    $session['ip_address'],
                    $session['user_agent']
                );
            } else {
                $sessionKey = substr($session['key'], -20);
                printf("%-10d %-30s %-20s %-15s ...%s\n",
                    $session['user_id'],
                    $lastActivity,
                    $profileType,
                    $session['ttl'],
                    $sessionKey
                );
            }
        }
        echo str_repeat("=", 120) . "\n";
        echo "Total: " . count($sessions) . " session(s)\n";
    }

} elseif ($action === 'expire') {
    if (!$userId) {
        echo "Error: User ID is required for expire action\n";
        exit(1);
    }

    $user = \App\Models\User::find($userId);
    if (!$user) {
        echo "User {$userId} not found\n";
        exit(1);
    }

    echo "User: {$user->name} (ID: {$user->id})\n";
    echo "Sessions to expire: " . count($sessions) . "\n\n";

    if (empty($sessions)) {
        echo "No sessions found for user {$userId}\n";
    } else {
        $deleted = 0;

        if ($sessionDriver === 'database') {
            $table = config('session.table', 'sessions');
            foreach ($sessions as $session) {
                DB::table($table)->where('id', $session['id'])->delete();
                $deleted++;
                echo "✓ Deleted session: " . substr($session['id'], 0, 40) . "\n";
            }
        } elseif ($sessionDriver === 'redis') {
            foreach ($sessions as $session) {
                $redis->del($session['key']);
                $deleted++;
                echo "✓ Deleted session: " . substr($session['key'], -40) . "\n";
            }
        }

        echo "\n";
        echo str_repeat("=", 50) . "\n";
        echo "Total sessions deleted: {$deleted}\n";
        echo "{$user->name} has been logged out from all devices\n";
        echo str_repeat("=", 50) . "\n";
    }

} else {
    echo "Unknown action: {$action}\n";
    echo "Valid actions: list, expire\n";
    exit(1);
}
