<?php

declare(strict_types=1);

/*
 * This file is part of the VitiCore 2.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Client\GeoClient;

class CheckCity
{
    public function __construct(
        private GeoClient $client,
    ) {
    }

    public function check(string $city, string $department, ?string $postal = null, int $loop = 0): string|false
    {
        $split = explode(' ', $city);

        for ($i = $loop; $i <= 5; ++$i) {
            $result = $this->loop($city, $split, $i);

            if (false === $result) {
                continue;
            }

            $response = $this->call($result, $department, $postal);

            if (false !== $response) {
                return mb_strtoupper($this->strToAscii((string) $response[0]->nom));
            }
        }

        return false;
    }

    private function call(string $city, ?string $postal): array|false
    {
        unset($department);

        $query = [
            'nom' => $city,
        ];

        if (null !== $postal && '' !== $postal) {
            $query['codePostal'] = $postal;
        }

        $request = $this->client->get(
            '/communes',
            [
                'query' => $query,
            ]
        );

        $response = json_decode(
            $request->getBody()->getContents(),
            false,
            512,
            \JSON_THROW_ON_ERROR
        );

        if (!\is_array($response) || [] === $response) {
            return false;
        }

        return $response;
    }

    /**
     * @param array<int, string> $split
     */
    private function loop(string $city, array $split, int $loop): string|false
    {
        if (0 === $loop) {
            return $city;
        }

        if (1 === $loop) {
            if (\count($split) >= 5) {
                return $split[1].' '.$split[2].' '.$split[3].' '.$split[4];
            }

            if (\count($split) >= 4) {
                return $split[1].' '.$split[3];
            }

            if (\count($split) >= 3) {
                return $split[0].' '.$split[2];
            }

            return false;
        }

        if (2 === $loop) {
            if (\count($split) >= 5) {
                return $split[2].' '.$split[3].' '.$split[4];
            }

            if (\count($split) >= 4) {
                return $split[2].' '.$split[3];
            }

            if (\count($split) >= 3) {
                return $split[1].' '.$split[2];
            }

            return false;
        }

        if (3 === $loop) {
            if (\count($split) >= 5) {
                return $split[3].' '.$split[4];
            }

            if (\count($split) >= 4) {
                return $split[0].' '.$split[2];
            }

            if (\count($split) >= 3) {
                return $split[0].' '.$split[1];
            }

            return false;
        }

        if (4 === $loop) {
            if (\count($split) >= 5) {
                return $split[3].' '.$split[4];
            }

            if (\count($split) >= 4) {
                return $split[0].' '.$split[3];
            }

            return false;
        }

        if (5 === $loop) {
            if (\count($split) >= 5) {
                return $split[2].' '.$split[4];
            }

            return false;
        }

        return false;
    }

    private function strToAscii(string $str): string
    {
        $strAscii = [
            'A' => 'ÀÁÂÃÄÅĀĂǍẠẢẤẦẨẪẬẮẰẲẴẶǺĄ',
            'a' => 'àáâãäåāăǎạảấầẩẫậắằẳẵặǻą',
            'C' => 'ÇĆĈĊČ',
            'c' => 'çćĉċč',
            'D' => 'ÐĎĐ',
            'd' => 'ďđ',
            'E' => 'ÈÉÊËĒĔĖĘĚẸẺẼẾỀỂỄỆ',
            'e' => 'èéêëēĕėęěẹẻẽếềểễệ',
            'G' => 'ĜĞĠĢ',
            'g' => 'ĝğġģ',
            'H' => 'ĤĦ',
            'h' => 'ĥħ',
            'I' => 'ÌÍÎÏĨĪĬĮİǏỈỊ',
            'J' => 'Ĵ',
            'j' => 'ĵ',
            'K' => 'Ķ',
            'k' => 'ķ',
            'L' => 'ĹĻĽĿŁ',
            'l' => 'ĺļľŀł',
            'N' => 'ÑŃŅŇ',
            'n' => 'ñńņňŉ',
            'O' => 'ÒÓÔÕÖØŌŎŐƠǑǾỌỎỐỒỔỖỘỚỜỞỠỢ',
            'o' => 'òóôõöøōŏőơǒǿọỏốồổỗộớờởỡợð',
            'R' => 'ŔŖŘ',
            'r' => 'ŕŗř',
            'S' => 'ŚŜŞŠ',
            's' => 'śŝşš',
            'T' => 'ŢŤŦ',
            't' => 'ţťŧ',
            'U' => 'ÙÚÛÜŨŪŬŮŰŲƯǓǕǗǙǛỤỦỨỪỬỮỰ',
            'u' => 'ùúûüũūŭůűųưǔǖǘǚǜụủứừửữự',
            'W' => 'ŴẀẂẄ',
            'w' => 'ŵẁẃẅ',
            'Y' => 'ÝŶŸỲỸỶỴ',
            'y' => 'ýÿŷỹỵỷỳ',
            'Z' => 'ŹŻŽ',
            'z' => 'źżž',
            'AE' => 'Æ',
            'ae' => 'æ',
            'OE' => 'Œ',
            'oe' => 'œ',
        ];

        foreach ($strAscii as $replacement => $chars) {
            $str = mb_ereg_replace('['.$chars.']', $replacement, $str);
        }

        return $str;
    }
}
