<?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 League\Csv\Statement;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

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

    public function __construct(private readonly HttpClientInterface $client, private readonly AddressReferenceBaseImporter $baseImporter, private readonly AddressToReferenceMatcher $addressToReferenceMatcher) {}

    public function import(string $lang, array $lists, ?string $sendAddressReportToEmail = null): void
    {
        foreach ($lists as $list) {
            $this->importList($lang, $list, $sendAddressReportToEmail);
        }
    }

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

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

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

    private function importList(string $lang, string $list, ?string $sendAddressReportToEmail = null): void
    {
        $downloadUrl = $this->getDownloadUrl($lang, $list);

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

        if (200 !== $response->getStatusCode()) {
            throw new \Exception('Could not download CSV: '.$response->getStatusCode());
        }

        $tmpname = tempnam(sys_get_temp_dir(), 'php-add-'.$list.$lang);
        $file = fopen($tmpname, 'r+b');

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

        fclose($file);

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

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

        $stmt = new Statement();
        $stmt = $stmt->process($csv);

        foreach ($stmt as $record) {
            $this->baseImporter->importAddress(
                $record['best_id'],
                $record['municipality_objectid'],
                $record['postal_info_objectid'],
                $record['streetname'],
                $record['housenumber'].('' !== $record['boxnumber'] ? ' bte '.$record['boxnumber'] : ''),
                'bestaddress.'.$list,
                (float) $record['Y'],
                (float) $record['X'],
                3812
            );
        }

        $this->baseImporter->finalize(sendAddressReportToEmail: $sendAddressReportToEmail);

        $this->addressToReferenceMatcher->checkAddressesMatchingReferences();

        gzclose($uncompressedStream);
    }
}
