<?php

namespace App\Services\Analytics;

use App\Models\User;
use App\Services\Api\API;
use App\Services\CacheService;
use Illuminate\Support\Facades\DB;

class StatsService
{
    protected API $api;

    public function __construct(API $api)
    {
        $this->api = $api;
    }

    public function getUserStats(): array
    {
        return CacheService::remember(
            CacheService::statsKey('user_stats'),
            CacheService::TTL_MEDIUM,
            function () {
                $stats = User::query()
                    ->select('role', DB::raw('COUNT(*) as count'))
                    ->groupBy('role')
                    ->pluck('count', 'role')
                    ->toArray();

                return [
                    'total' => array_sum($stats),
                    'admins' => $stats['admin'] ?? 0,
                    'players' => $stats['player'] ?? 0,
                ];
            }
        );
    }

    public function getTotalUsers(): int
    {
        return CacheService::remember(
            CacheService::statsKey('total_users'),
            CacheService::TTL_MEDIUM,
            fn () => User::count()
        );
    }

    public function getRecentUsers(int $limit = 5): array
    {
        return CacheService::remember(
            CacheService::statsKey('recent_users_'.$limit),
            CacheService::TTL_MEDIUM,
            fn () => User::latest('ID')->take($limit)->get(['ID', 'name', 'email', 'role'])->toArray()
        );
    }

    public function getOnlineData(): array
    {
        $isServerOnline = $this->api->serverOnline();

        if (! $isServerOnline) {
            return [
                'count' => 0,
                'gms' => 0,
                'list' => [],
                'serverOnline' => false,
            ];
        }

        // Server is online — hit API directly for player count/list
        try {
            $onlineUsers = $this->api->getOnlineList();
            $onlineCount = count($onlineUsers);

            // Get GM user IDs from auth table (database stores GM info, not game server API)
            $gmUserIds = DB::table('auth')
                ->distinct()
                ->pluck('userid')
                ->toArray();

            // Count online GMs by checking if online user's userid exists in auth table
            $onlineGMs = collect($onlineUsers)->filter(function ($user) use ($gmUserIds) {
                return isset($user['userid']) && in_array($user['userid'], $gmUserIds);
            })->count();

            return [
                'count' => $onlineCount,
                'gms' => $onlineGMs,
                'list' => $onlineUsers,
                'serverOnline' => true,
            ];
        } catch (\Exception $e) {
            // Port check succeeded but getOnlineList failed
            // Server is still online, just return empty data
            \Log::warning('Failed to get online list but server is online', [
                'error' => $e->getMessage(),
            ]);

            return [
                'count' => 0,
                'gms' => 0,
                'list' => [],
                'serverOnline' => true,
            ];
        }
    }

    public function getServerTimezone(): string
    {
        return CacheService::remember(
            CacheService::statsKey('server_timezone'),
            CacheService::TTL_EXTENDED,
            fn () => DB::table('settings')->where('key', 'server_timezone')->value('value') ?? 'Asia/Jakarta'
        );
    }

    public static function invalidateUserStats(): void
    {
        CacheService::forget(CacheService::statsKey('user_stats'));
        CacheService::forget(CacheService::statsKey('total_users'));
        CacheService::forget(CacheService::statsKey('recent_users_5'));
        CacheService::forget(CacheService::statsKey('recent_users_10'));
    }
}
