<?php

namespace App\Http\Middleware;

use App\Models\UserActivity;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class LogUserActivity
{
    /**
     * Routes to exclude from logging
     */
    protected array $excludedRoutes = [
        'superadmin.activity.*',
        'manager.activity.*',
        'admin.activity.*',
        '*.list', // DataTable AJAX calls
        'debugbar.*',
        'ignition.*',
    ];

    /**
     * URL patterns to exclude
     */
    protected array $excludedPatterns = [
        '/livewire/*',
        '/_debugbar/*',
        '/broadcasting/*',
        '*.js',
        '*.css',
        '*.map',
        '*.ico',
        '*.png',
        '*.jpg',
        '*.gif',
        '*.svg',
        '*.woff',
        '*.woff2',
        '*.ttf',
    ];

    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        $startTime = microtime(true);

        $response = $next($request);

        // Only log for authenticated users
        if (Auth::check() && $this->shouldLog($request)) {
            $this->logActivity($request, $response, $startTime);
        }

        return $response;
    }

    /**
     * Determine if the request should be logged
     */
    protected function shouldLog(Request $request): bool
    {
        // Don't log AJAX DataTable requests
        if ($request->ajax() && $request->isMethod('GET')) {
            return false;
        }

        // Check excluded routes
        $routeName = $request->route()?->getName();
        if ($routeName) {
            foreach ($this->excludedRoutes as $pattern) {
                if (fnmatch($pattern, $routeName)) {
                    return false;
                }
            }
        }

        // Check excluded URL patterns
        $path = $request->path();
        foreach ($this->excludedPatterns as $pattern) {
            if (fnmatch($pattern, $path)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Log the user activity
     */
    protected function logActivity(Request $request, Response $response, float $startTime): void
    {
        try {
            $user = Auth::user();
            $userAgent = $request->userAgent();

            UserActivity::create([
                'user_id' => $user->id,
                'activity_type' => $this->determineActivityType($request),
                'page_title' => $this->extractPageTitle($request),
                'url' => $request->fullUrl(),
                'route_name' => $request->route()?->getName(),
                'method' => $request->method(),
                'ip_address' => $request->ip(),
                'user_agent' => $userAgent,
                'browser' => $this->parseBrowser($userAgent),
                'platform' => $this->parsePlatform($userAgent),
                'device' => $this->parseDevice($userAgent),
                'request_data' => $this->getSafeRequestData($request),
                'response_status' => $response->getStatusCode(),
                'response_time' => round((microtime(true) - $startTime) * 1000, 2),
            ]);
        } catch (\Exception $e) {
            // Silently fail - don't break the application if logging fails
            \Log::error('Failed to log user activity: ' . $e->getMessage());
        }
    }

    /**
     * Determine the activity type based on request method and route
     */
    protected function determineActivityType(Request $request): string
    {
        $method = $request->method();
        $routeName = $request->route()?->getName() ?? '';

        // Check for login/logout
        if (str_contains($routeName, 'login')) {
            return UserActivity::TYPE_LOGIN;
        }
        if (str_contains($routeName, 'logout')) {
            return UserActivity::TYPE_LOGOUT;
        }

        // Check by HTTP method
        return match($method) {
            'POST' => UserActivity::TYPE_CREATE,
            'PUT', 'PATCH' => UserActivity::TYPE_UPDATE,
            'DELETE' => UserActivity::TYPE_DELETE,
            default => UserActivity::TYPE_PAGE_VISIT,
        };
    }

    /**
     * Extract page title from route name
     */
    protected function extractPageTitle(Request $request): ?string
    {
        $routeName = $request->route()?->getName();

        if (!$routeName) {
            return null;
        }

        // Convert route name to readable title
        // e.g., 'superadmin.dashboard.dashboard' => 'Dashboard'
        $parts = explode('.', $routeName);
        $lastPart = end($parts);

        return ucwords(str_replace(['_', '-'], ' ', $lastPart));
    }

    /**
     * Get safe request data (excluding sensitive fields)
     */
    protected function getSafeRequestData(Request $request): ?array
    {
        if ($request->isMethod('GET')) {
            return null;
        }

        $data = $request->except([
            'password',
            'password_confirmation',
            'current_password',
            'new_password',
            '_token',
            'credit_card',
            'card_number',
            'cvv',
            'secret',
            'api_key',
        ]);

        // Limit data size
        if (count($data) > 20) {
            $data = array_slice($data, 0, 20);
            $data['_truncated'] = true;
        }

        return empty($data) ? null : $data;
    }

    /**
     * Parse browser from user agent
     */
    protected function parseBrowser(?string $userAgent): ?string
    {
        if (!$userAgent) {
            return null;
        }

        $browsers = [
            'Edge' => '/Edge\/([0-9.]+)/',
            'Chrome' => '/Chrome\/([0-9.]+)/',
            'Firefox' => '/Firefox\/([0-9.]+)/',
            'Safari' => '/Safari\/([0-9.]+)/',
            'Opera' => '/Opera\/([0-9.]+)/',
            'IE' => '/MSIE ([0-9.]+)/',
        ];

        foreach ($browsers as $browser => $pattern) {
            if (preg_match($pattern, $userAgent, $matches)) {
                return $browser . ' ' . ($matches[1] ?? '');
            }
        }

        return 'Unknown';
    }

    /**
     * Parse platform from user agent
     */
    protected function parsePlatform(?string $userAgent): ?string
    {
        if (!$userAgent) {
            return null;
        }

        $platforms = [
            'Windows 11' => '/Windows NT 10.0.*Win64/',
            'Windows 10' => '/Windows NT 10.0/',
            'Windows 8.1' => '/Windows NT 6.3/',
            'Windows 8' => '/Windows NT 6.2/',
            'Windows 7' => '/Windows NT 6.1/',
            'macOS' => '/Macintosh/',
            'Linux' => '/Linux/',
            'Ubuntu' => '/Ubuntu/',
            'Android' => '/Android/',
            'iOS' => '/iPhone|iPad/',
        ];

        foreach ($platforms as $platform => $pattern) {
            if (preg_match($pattern, $userAgent)) {
                return $platform;
            }
        }

        return 'Unknown';
    }

    /**
     * Parse device type from user agent
     */
    protected function parseDevice(?string $userAgent): ?string
    {
        if (!$userAgent) {
            return null;
        }

        if (preg_match('/Mobile|Android|iPhone|iPad/', $userAgent)) {
            if (preg_match('/iPad|Tablet/', $userAgent)) {
                return 'Tablet';
            }
            return 'Mobile';
        }

        return 'Desktop';
    }
}
