<?php

namespace App\Services\Geolocation;

use Illuminate\Http\Request;

class ClientIpExtractor
{
    public function fromRequest(Request $request): ?string
    {
        $forwarded = $request->header('x-forwarded-for');
        if (is_string($forwarded) && $forwarded !== '') {
            $candidate = $this->firstPublicIp($forwarded);
            if ($candidate !== null) {
                return $candidate;
            }
        }

        $remote = $request->ip();
        return $this->isPublic($remote) ? $remote : null;
    }

    private function firstPublicIp(string $header): ?string
    {
        foreach (explode(',', $header) as $part) {
            $ip = trim($part);
            if ($this->isPublic($ip)) {
                return $ip;
            }
        }

        return null;
    }

    private function isPublic(?string $ip): bool
    {
        if (!is_string($ip) || $ip === '') {
            return false;
        }

        return filter_var(
            $ip,
            FILTER_VALIDATE_IP,
            FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
        ) !== false;
    }
}
