<?php

namespace App\Http\Middleware;

use App\Models\TrafficVisit;
use App\Services\GeoIpService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class TrackVisit
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        try {
            if ($this->shouldSkip($request)) {
                return $response;
            }

            $sessionId = $request->session()->getId();
            $ip = $this->clientIp($request);
            $ua = (string) $request->userAgent();
            $parsed = $this->parseUserAgent($ua);

            $geo = App::make(GeoIpService::class)->locate($ip);

            TrafficVisit::create([
                'session_id' => $sessionId,
                'user_id' => optional($request->user())->id,
                'ip' => $ip,
                'user_agent' => $ua,
                'device' => $parsed['device'] ?? null,
                'platform' => $parsed['platform'] ?? null,
                'browser' => $parsed['browser'] ?? null,
                'method' => $request->method(),
                'route_name' => optional($request->route())->getName(),
                'path' => '/'.ltrim($request->path(), '/'),
                'status_code' => method_exists($response, 'getStatusCode') ? $response->getStatusCode() : null,
                'referrer' => $request->headers->get('referer'),
                'country' => $geo['country'] ?? null,
                'city' => $geo['city'] ?? null,
                'latitude' => $geo['lat'] ?? null,
                'longitude' => $geo['lon'] ?? null,
            ]);
        } catch (\Throwable $e) {
            Log::debug('TrackVisit middleware error', ['error' => $e->getMessage()]);
        }

        return $response;
    }

    private function shouldSkip(Request $request): bool
    {
        if ($request->is('analytics/event')) return true;
        if ($request->is('telescope*') || $request->is('horizon*')) return true;
        if (in_array($request->method(), ['OPTIONS'])) return true;
        return false;
    }

    private function clientIp(Request $request): string
    {
        $xForwarded = $request->headers->get('X-Forwarded-For');
        if ($xForwarded) {
            $parts = array_map('trim', explode(',', $xForwarded));
            if (!empty($parts[0])) return $parts[0];
        }
        return (string) $request->ip();
    }

    private function parseUserAgent(string $ua): array
    {
        $uaL = strtolower($ua);
        $browser = 'Unknown';
        if (str_contains($uaL, 'edg')) $browser = 'Edge';
        elseif (str_contains($uaL, 'chrome')) $browser = 'Chrome';
        elseif (str_contains($uaL, 'safari')) $browser = 'Safari';
        elseif (str_contains($uaL, 'firefox')) $browser = 'Firefox';
        elseif (str_contains($uaL, 'opera') || str_contains($uaL, 'opr')) $browser = 'Opera';

        $platform = 'Unknown';
        if (str_contains($uaL, 'windows')) $platform = 'Windows';
        elseif (str_contains($uaL, 'mac os') || str_contains($uaL, 'macintosh')) $platform = 'macOS';
        elseif (str_contains($uaL, 'android')) $platform = 'Android';
        elseif (str_contains($uaL, 'iphone') || str_contains($uaL, 'ios') || str_contains($uaL, 'ipad')) $platform = 'iOS';
        elseif (str_contains($uaL, 'linux')) $platform = 'Linux';

        $device = str_contains($uaL, 'mobile') || str_contains($uaL, 'iphone') || str_contains($uaL, 'android') ? 'Mobile' : 'Desktop';

        return compact('browser', 'platform', 'device');
    }
}
