<?php

namespace App\Support;

use App\Models\UserActivityLog;
use Illuminate\Http\Request;

class ActivityLogger
{
    public static function log(
        string  $action,
        ?int    $userId     = null,
        ?string $subjectType = null,
        ?int    $subjectId   = null,
        ?array  $meta        = null,
        ?Request $request    = null
    ): void {
        try {
            $req     = $request ?? request();
            $ip      = $req->ip();
            $ua      = $req->userAgent() ?? '';
            $isBot   = (bool) $req->attributes->get('is_bot', false);
            $geo     = cache()->remember("geo_{$ip}", 3600, fn() => self::geoIp($ip));

            UserActivityLog::create([
                'user_id'      => $userId ?? auth()->id(),
                'session_id'   => session()->getId(),
                'action'       => $action,
                'subject_type' => $subjectType,
                'subject_id'   => $subjectId,
                'ip'           => $ip,
                'country'      => $geo['country'] ?? null,
                'city'         => $geo['city'] ?? null,
                'device'       => self::device($ua),
                'browser'      => self::browser($ua),
                'user_agent'   => mb_substr($ua, 0, 500),
                'is_bot'       => $isBot,
                'meta'         => $meta,
                'created_at'   => now(),
            ]);
        } catch (\Throwable) {
            // never break the app
        }
    }

    private static function geoIp(string $ip): array
    {
        try {
            if (in_array($ip, ['127.0.0.1', '::1']) || str_starts_with($ip, '192.168.') || str_starts_with($ip, '10.')) {
                return ['country' => 'Local', 'city' => null];
            }
            $r = \Illuminate\Support\Facades\Http::timeout(2)->get("http://ip-api.com/json/{$ip}?fields=country,city,status");
            $d = $r->json();
            return ($d['status'] ?? '') === 'success' ? ['country' => $d['country'], 'city' => $d['city']] : [];
        } catch (\Throwable) {
            return [];
        }
    }

    private static function device(string $ua): string
    {
        $ua = strtolower($ua);
        if (str_contains($ua, 'mobile') || str_contains($ua, 'android') || str_contains($ua, 'iphone')) return 'mobile';
        if (str_contains($ua, 'tablet') || str_contains($ua, 'ipad')) return 'tablet';
        return 'desktop';
    }

    private static function browser(string $ua): string
    {
        if (str_contains($ua, 'Chrome'))  return 'Chrome';
        if (str_contains($ua, 'Firefox')) return 'Firefox';
        if (str_contains($ua, 'Safari'))  return 'Safari';
        if (str_contains($ua, 'Edge'))    return 'Edge';
        if (str_contains($ua, 'Opera'))   return 'Opera';
        return 'Other';
    }
}
