<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (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\Provider\Carrier;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Filesystem\Filesystem;
use CpCreation\VitiCore\Shop\Model\ShippingAuto;
use CpCreation\VitiCore\Shop\Model\ShippingConfig;
use Doctrine\ORM\EntityManagerInterface;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use Symfony\Component\HttpFoundation\RequestStack;

final class Genin2023Provider implements CarrierProviderInterface
{
    public const TYPE = 'genin_2023';
    private const CSV_LENGTH = 2000;

    /**
     * 1 palette comporte 504 bouteilles (vu avec Anne-Lise).
     *
     * @var array<string,string>
     */
    private array $pal = [
        '1/4 de palette' => '0 à 126',
        '1/2 palette' => '126 à 252',
        '1 palette 80x120 ou 100x120' => '252 à 504',
        '2 palettes 80x120' => '504 à 1008',
        '3 palettes 80x120' => '1008 à 1512',
        '4 palettes 80x120 ' => '1512 à 2016',
        '5 palettes 80x120' => '2016 à 2520',
        '6 palettes 80x120' => '2520 à 3024',
        '7 palettes 80x120' => '3024 à 3528',
        '8 palettes 80x120' => '3528 à 4032',
    ];

    public function __construct(
        private RequestStack $requestStack,
        private Filesystem $filesystem,
        private EntityManagerInterface $em,
    ) {
    }

    /**
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function setData(ShippingConfig $config): void
    {
        $request = $this->requestStack->getCurrentRequest();
        if (null === $request) {
            return;
        }

        $files = $request->files->get('shipping_config');
        if (!\is_array($files)) {
            return;
        }

        $uploadedFile = $files['file']['file'] ?? null;
        if (null === $uploadedFile) {
            return;
        }

        $reader = new Xlsx();
        $reader->setReadDataOnly(true);

        $xlsxPath = $this->filesystem->absolutePath('file', $config->getFile()->getPath());
        $spreadsheet = $reader->load($xlsxPath);

        $writer = new Csv($spreadsheet);
        $csvPath = $this->filesystem->absolutePath('file', 'genin2023.csv');
        $writer->save($csvPath);

        $handle = fopen($csvPath, 'r');
        if (false === $handle) {
            return;
        }

        $classMetaData = $this->em->getClassMetadata(ShippingAuto::class);
        $connection = $this->em->getConnection();

        $connection->beginTransaction();

        try {
            (new CarrierTableTruncator())->truncate($connection, $classMetaData->getTableName());

            $shippingQtyCollection = [];
            $keysPal = array_keys($this->pal);

            while (($data = fgetcsv($handle, self::CSV_LENGTH, ',')) !== false) {
                $this->hydrateShippingQuantities($data, $shippingQtyCollection);

                if (($data[0] ?? null) !== 'France') {
                    continue;
                }

                $department = (string) ($data[1] ?? '');
                if ('' === $department || '0' === $department) {
                    continue;
                }

                $county = mb_substr($department, 0, 2);

                foreach ($this->pal as $key => $pal) {
                    unset($pal);

                    if (!isset($shippingQtyCollection[$key])) {
                        continue;
                    }

                    $shipping = new ShippingAuto();
                    $shipping->setCountry('FR');
                    $shipping->setCounty($county);
                    $shipping->setQtyOf($shippingQtyCollection[$key]['of']);
                    $shipping->setQtyAt($shippingQtyCollection[$key]['at'] ?? null);

                    $colIndex = array_search($key, $keysPal, true);
                    if (false !== $colIndex) {
                        $raw = $data[$colIndex + 3] ?? 0;
                        $shipping->setPackagePrice((float) $raw * 100);
                    } else {
                        $shipping->setPackagePrice(0);
                    }

                    $this->em->persist($shipping);
                }
            }

            $this->em->flush();
            fclose($handle);
            $connection->commit();
        } catch (\Throwable $e) {
            fclose($handle);
            $connection->rollBack();

            throw $e;
        }
    }

    public function getCarrier(): string
    {
        return self::TYPE;
    }

    /**
     * @param array<int, string|null>              $data
     * @param array<string, array{of:int, at:int}> $shippingQtyCollection
     */
    private function hydrateShippingQuantities(array $data, array &$shippingQtyCollection): void
    {
        $num = \count($data);

        for ($c = 0; $c < $num; ++$c) {
            if ('Délai de livraison' !== $data[$c]) {
                continue;
            }

            for ($cc = $c + 1; $cc < $num; ++$cc) {
                if ('' === $data[$cc] || null === $data[$cc]) {
                    continue;
                }

                foreach ($this->pal as $key => $pal) {
                    if ($key !== $data[$cc]) {
                        continue;
                    }

                    $explode = explode('à', $pal);
                    $shippingQtyCollection[$data[$cc]]['of'] = (int) mb_trim($explode[0]);
                    $shippingQtyCollection[$data[$cc]]['at'] = (int) mb_trim($explode[1]);
                }
            }

            break;
        }
    }
}
