<?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\HttpClientInterface;

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

    public function import(string $departementNo, ?string $sendAddressReportToEmail = null): void
    {
        if (!is_numeric($departementNo)) {
            throw new \UnexpectedValueException('Could not parse this department number');
        }

        $url = sprintf('https://adresse.data.gouv.fr/data/ban/adresses/latest/csv/adresses-%s.csv.gz', $departementNo);

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

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

        $path = sys_get_temp_dir().'/'.$departementNo.'.csv.gz';
        $file = fopen($path, 'w');

        if (false === $file) {
            throw new \Exception('Could not create temporary file');
        }

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

        fclose($file);

        // re-open it to read it
        $csvDecompressed = gzopen($path, 'r');

        $csv = Reader::from($csvDecompressed);
        $csv->setDelimiter(';')->setHeaderOffset(0);
        $stmt = new Statement();
        $stmt = $stmt->process($csv, [
            'id',
            'id_fantoir',
            'numero',
            'rep',
            'nom_voie',
            'code_postal',
            'code_insee',
            'nom_commune',
            'code_insee_ancienne_commune',
            'nom_ancienne_commune',
            'x',
            'y',
            'lon',
            'lat',
            'type_position',
            'alias',
            'nom_ld',
            'libelle_acheminement',
            'nom_afnor',
            'source_position',
            'source_nom_voie',
            'certification_commune',
            'cad_parcelles',
        ]);

        foreach ($stmt as $record) {
            $this->baseImporter->importAddress(
                $record['id'],
                $record['code_insee'],
                $record['code_postal'],
                $record['nom_voie'],
                $record['numero'].' '.$record['rep'],
                'BAN.'.$departementNo,
                (float) $record['lat'],
                (float) $record['lon'],
                4326
            );
        }

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

        $this->addressToReferenceMatcher->checkAddressesMatchingReferences();

        fclose($csvDecompressed);
        unlink($path);
    }
}
