<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Service\Import;

use League\Csv\Reader;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class PostalCodeBEFromBestAddress
{
    private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.0.0';

    public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) {}

    public function import(string $lang = 'fr'): void
    {
        $fileDownloadUrl = $this->getFileDownloadUrl($lang);

        $response = $this->client->request('GET', $fileDownloadUrl);

        $tmpname = tempnam(sys_get_temp_dir(), 'postalcodes');
        $tmpfile = fopen($tmpname, 'r+b');

        if (false === $tmpfile) {
            throw new \RuntimeException('could not create temporary file');
        }

        foreach ($this->client->stream($response) as $chunk) {
            fwrite($tmpfile, $chunk->getContent());
        }

        fclose($tmpfile);

        $uncompressedStream = gzopen($tmpname, 'r');

        $csv = Reader::from($uncompressedStream);
        $csv->setDelimiter(',');
        $csv->setHeaderOffset(0);

        foreach ($csv as $offset => $record) {
            $this->handleRecord($record);
        }

        gzclose($uncompressedStream);
        unlink($tmpname);

        $this->logger->info(self::class.' list of postal code downloaded');

        $this->baseImporter->finalize();

        $this->logger->info(self::class.' postal code fetched', ['offset' => $offset ?? 0]);
    }

    private function getFileDownloadUrl(string $lang): string
    {
        try {
            $release = $this->client->request('GET', self::RELEASE)
                ->toArray();
        } catch (TransportExceptionInterface $e) {
            throw new \RuntimeException('could not get the release definition', 0, $e);
        }

        $postals = array_filter($release['assets'], static fn (array $item) => 'postals.'.$lang.'.csv.gz' === $item['name']);

        return array_values($postals)[0]['browser_download_url'];
    }

    private function handleRecord(array $record): void
    {
        $this->baseImporter->importCode(
            'BE',
            trim((string) $record['municipality_name']),
            trim((string) $record['postal_info_objectid']),
            $record['municipality_objectid'],
            'bestaddress',
            (float) $record['Y'],
            (float) $record['X'],
            3812
        );
    }
}
