<?php

declare(strict_types=1);

namespace App\Infrastructure\Enrichment\Downloaders;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;

/**
 * Opt-in — requires IPINFO_TOKEN. Direct .mmdb downloads, no
 * compression, no integrity file. Verification is the cross-provider
 * MmdbVerifier (open + metadata + node-count sanity).
 *
 * The token is never logged: error messages substitute "***" for the
 * real value.
 */
final class IPinfoDownloader implements GeoIpDownloader
{
    private const COUNTRY_URL = 'https://ipinfo.io/data/free/country.mmdb';
    private const ASN_URL = 'https://ipinfo.io/data/free/asn.mmdb';

    public function __construct(
        private readonly ClientInterface $http,
        private readonly string $token,
    ) {
    }

    public function name(): string
    {
        return 'ipinfo';
    }

    public function requiresCredential(): bool
    {
        return true;
    }

    public function hasCredential(): bool
    {
        return $this->token !== '';
    }

    public function download(string $tempDir): array
    {
        $countryPath = $tempDir . '/country.mmdb';
        $asnPath = $tempDir . '/asn.mmdb';

        $this->fetch(self::COUNTRY_URL, $countryPath);
        MmdbVerifier::assertCountry($countryPath);

        $this->fetch(self::ASN_URL, $asnPath);
        MmdbVerifier::assertAsn($asnPath);

        return ['country' => $countryPath, 'asn' => $asnPath];
    }

    private function fetch(string $url, string $sink): void
    {
        try {
            $this->http->request('GET', $url, [
                'sink' => $sink,
                'query' => ['token' => $this->token],
            ]);
        } catch (GuzzleException $e) {
            throw new DownloaderException(sprintf('GET %s?token=*** failed', $url), 0, $e);
        }
    }
}
