<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AdminSession;
use App\Models\User;
use Illuminate\Http\Request;

class AdminSessionController extends Controller
{
    /**
     * Display admin sessions
     */
    public function index(Request $request)
    {
        $query = AdminSession::with('user');

        // Filter by user
        if ($request->filled('user_id')) {
            $query->where('user_id', $request->user_id);
        }

        // Filter by status
        if ($request->get('status') === 'active') {
            $query->active();
        } elseif ($request->get('status') === 'inactive') {
            $query->where('is_active', false);
        }

        // Filter by login method
        if ($request->filled('login_method')) {
            $query->where('login_method', $request->login_method);
        }

        // Search by IP address or user agent
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('ip_address', 'like', "%{$search}%")
                  ->orWhere('user_agent', 'like', "%{$search}%")
                  ->orWhereHas('user', function ($u) use ($search) {
                      $u->where('email', 'like', "%{$search}%");
                  });
            });
        }

        // Sorting
        $sortBy = $request->get('sort_by', 'login_at');
        $sortOrder = $request->get('sort_order', 'desc');
        $query->orderBy($sortBy, $sortOrder);

        $sessions = $query->paginate(25);

        // Statistics
        $stats = [
            'total_active' => AdminSession::active()->count(),
            'today_logins' => AdminSession::whereDate('login_at', today())->count(),
            'this_week_logins' => AdminSession::where('login_at', '>=', now()->subWeek())->count(),
            'concurrent_sessions' => AdminSession::active()->distinct('user_id')->count('user_id'),
        ];

        $admins = User::whereHas('roles', function ($q) {
            $q->whereIn('name', ['admin', 'super_admin']);
        })->select('id', 'first_name', 'last_name', 'email')->get();

        return view('admin.sessions.index', compact('sessions', 'stats', 'admins'));
    }

    /**
     * Show session details
     */
    public function show($id)
    {
        $session = AdminSession::with('user')->findOrFail($id);

        return view('admin.sessions.show', compact('session'));
    }

    /**
     * Get user's active sessions
     */
    public function userSessions($userId)
    {
        $user = User::findOrFail($userId);
        $sessions = AdminSession::forUser($userId)->active()->get();

        return response()->json([
            'success' => true,
            'user' => $user->only('id', 'name', 'email'),
            'sessions' => $sessions,
        ]);
    }

    /**
     * Terminate a session
     */
    public function terminate($id)
    {
        $session = AdminSession::findOrFail($id);

        // Prevent terminating your own current session
        if ($session->user_id === auth()->id() && $session->is_active) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot terminate your own active session',
            ], 403);
        }

        $session->logout();

        return response()->json([
            'success' => true,
            'message' => 'Session terminated successfully',
        ]);
    }

    /**
     * Terminate all sessions for a user
     */
    public function terminateUserSessions(Request $request, $userId)
    {
        $request->validate([
            'keep_current' => 'boolean',
        ]);

        $user = User::findOrFail($userId);

        $query = AdminSession::forUser($userId)->active();

        // Optionally keep current session
        if ($request->boolean('keep_current') && auth()->user()->adminSession) {
            $query->where('id', '!=', auth()->user()->adminSession->id);
        }

        $terminatedCount = 0;
        foreach ($query->get() as $session) {
            $session->logout();
            $terminatedCount++;
        }

        return response()->json([
            'success' => true,
            'message' => "{$terminatedCount} session(s) terminated for {$user->name}",
            'terminated_count' => $terminatedCount,
        ]);
    }

    /**
     * Get session statistics
     */
    public function statistics(Request $request)
    {
        $days = $request->get('days', 30);

        // Sessions by day
        $sessionsByDay = AdminSession::selectRaw('DATE(login_at) as date, COUNT(*) as count')
            ->where('login_at', '>=', now()->subDays($days))
            ->groupBy('date')
            ->orderBy('date', 'asc')
            ->get();

        // Sessions by login method
        $sessionsByMethod = AdminSession::selectRaw('login_method, COUNT(*) as count')
            ->where('login_at', '>=', now()->subDays($days))
            ->groupBy('login_method')
            ->get();

        // Active sessions
        $activeSessions = AdminSession::active()
            ->where('login_at', '>=', now()->subDays($days))
            ->count();

        // Average session duration
        $avgDuration = AdminSession::selectRaw('AVG(TIMESTAMPDIFF(SECOND, login_at, COALESCE(logout_at, NOW()))) as avg_duration')
            ->where('login_at', '>=', now()->subDays($days))
            ->first()
            ->avg_duration ?? 0;

        // Top admin users
        $topAdmins = AdminSession::selectRaw('user_id, COUNT(*) as session_count')
            ->where('login_at', '>=', now()->subDays($days))
            ->groupBy('user_id')
            ->orderBy('session_count', 'desc')
            ->limit(10)
            ->with('user')
            ->get();

        // Failed logins / suspicious activity (logins from different IPs in short time)
        $suspiciousSessions = AdminSession::selectRaw('user_id, COUNT(DISTINCT ip_address) as unique_ips, COUNT(*) as total_sessions')
            ->where('login_at', '>=', now()->subDays($days))
            ->groupBy('user_id')
            ->having('unique_ips', '>', 5)
            ->with('user')
            ->get();

        return response()->json([
            'success' => true,
            'data' => [
                'sessions_by_day' => $sessionsByDay,
                'sessions_by_method' => $sessionsByMethod,
                'active_sessions' => $activeSessions,
                'avg_session_duration' => round($avgDuration, 2),
                'top_admins' => $topAdmins,
                'suspicious_sessions' => $suspiciousSessions,
            ],
        ]);
    }

    /**
     * Get session activity for specific user
     */
    public function userActivity($userId)
    {
        $sessions = AdminSession::with('user')
            ->where('user_id', $userId)
            ->orderBy('login_at', 'desc')
            ->limit(50)
            ->get();

        // Calculate statistics
        $stats = [
            'total_sessions' => AdminSession::where('user_id', $userId)->count(),
            'active_sessions' => AdminSession::where('user_id', $userId)->active()->count(),
            'unique_ips' => AdminSession::where('user_id', $userId)->distinct('ip_address')->count('ip_address'),
        ];

        return response()->json([
            'success' => true,
            'sessions' => $sessions,
            'statistics' => $stats,
        ]);
    }

    /**
     * Clean up old sessions (older than 90 days)
     */
    public function cleanup(Request $request)
    {
        $request->validate([
            'days' => 'integer|min:1|max:365',
        ]);

        $days = $request->get('days', 90);

        $deletedCount = AdminSession::where('created_at', '<', now()->subDays($days))
            ->orWhere(function ($q) use ($days) {
                $q->where('is_active', false)
                  ->where('logout_at', '<', now()->subDays($days));
            })
            ->delete();

        return response()->json([
            'success' => true,
            'message' => "{$deletedCount} old sessions deleted",
            'deleted_count' => $deletedCount,
        ]);
    }
}

