<?php

namespace App\Support;

use Illuminate\Support\Facades\DB;

class AvatarUrl
{
    private static array $hashCache = [];

    public static function forUser(int $userId, ?string $hash = null, int $size = 128): string
    {
        if ($userId <= 0) {
            return self::default();
        }

        $avatarHash = $hash ?: self::resolveHash($userId);

        if (!$avatarHash) {
            return self::default();
        }

        $base = rtrim((string) config('cdn.avatar_url', 'https://files.skinbase.org'), '/');
        $resolvedSize = self::resolveSize($size);

        // Use hash-based path: avatars/ab/cd/{hash}/{size}.webp?v={hash}
        $p1 = substr($avatarHash, 0, 2);
        $p2 = substr($avatarHash, 2, 2);

        // Always use CDN-hosted avatar files.
        return sprintf('%s/avatars/%s/%s/%s/%d.webp', $base, $p1, $p2, $avatarHash, $resolvedSize);
    }

    public static function default(): string
    {
        $base = rtrim((string) config('cdn.avatar_url', 'https://files.skinbase.org'), '/');

        return sprintf('%s/default/avatar_default.webp', $base);
    }

    private static function resolveHash(int $userId): ?string
    {
        if (array_key_exists($userId, self::$hashCache)) {
            return self::$hashCache[$userId];
        }

        try {
            $value = DB::table('user_profiles')
                ->where('user_id', $userId)
                ->value('avatar_hash');
        } catch (\Throwable $e) {
            $value = null;
        }

        self::$hashCache[$userId] = $value ? (string) $value : null;

        return self::$hashCache[$userId];
    }

    private static function resolveSize(int $requestedSize): int
    {
        $sizes = array_values(array_filter(
            (array) config('avatars.sizes', [32, 64, 128, 256, 512]),
            static fn ($size): bool => (int) $size > 0
        ));

        if ($sizes === []) {
            return max(1, $requestedSize);
        }

        sort($sizes);

        foreach ($sizes as $size) {
            if ($requestedSize <= (int) $size) {
                return (int) $size;
            }
        }

        return (int) end($sizes);
    }
}
