<?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\ShippingAutoSup;
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 OenotransProvider implements CarrierProviderInterface
{
    public const TYPE = 'oenotrans';

    /**
     * @var array<string,string>
     */
    private array $pal = [
        '1/2 PAL' => '151 à 228',
        '1 PAL' => '229 à 480',
        '2 PAL' => '481 à 960',
        '3 PAL' => '961 à 1440',
    ];

    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 (!$request) {
            return;
        }

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

        $file = $files['file']['file'] ?? null;
        $fileSup = $files['fileSup']['file'] ?? null;

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

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

            $writer = new Csv($spreadsheet);
            $csvPath = $this->filesystem->absolutePath('file', 'oenotrans.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 = [];

                while (($data = fgetcsv($handle, 1000, ',')) !== false) {
                    $num = \count($data);

                    for ($c = 0; $c < $num; ++$c) {
                        if (($data[$c] ?? null) === 'Localités') {
                            for ($cc = 1; $cc < $num; ++$cc) {
                                if (($data[$cc] ?? '') === '') {
                                    continue;
                                }

                                if (str_contains((string) $data[$cc], 'à')) {
                                    $explode = explode('à', (string) $data[$cc]);
                                    $of = (int) mb_trim((string) ($explode[0] ?? 0));
                                    if ($of > 0) {
                                        --$of;
                                    }

                                    $shippingQtyCollection[$cc]['of'] = $of;
                                    $shippingQtyCollection[$cc]['at'] = (int) mb_trim((string) ($explode[1] ?? 0));
                                } else {
                                    foreach ($this->pal as $key => $pal) {
                                        if ($key === $data[$cc]) {
                                            $explode = explode('à', $pal);
                                            $of = (int) mb_trim((string) ($explode[0] ?? 0));
                                            if ($of > 0) {
                                                --$of;
                                            }

                                            $shippingQtyCollection[$cc]['of'] = $of;
                                            $shippingQtyCollection[$cc]['at'] = (int) mb_trim((string) ($explode[1] ?? 0));
                                        }
                                    }
                                }
                            }
                        }

                        if (isset($data[0]) && is_numeric(mb_substr((string) $data[0], 0, 2))) {
                            for ($cc = 1; $cc < $num; ++$cc) {
                                if (($data[$cc] ?? '') === '') {
                                    continue;
                                }

                                $shipping = new ShippingAuto();
                                $shipping->setCountry('FR');

                                $countyCell = (string) $data[0];
                                $valueCell = (string) $data[$cc];

                                if (mb_strstr($countyCell, 'VHM') || mb_strstr($valueCell, 'I')) {
                                    $county = mb_substr($countyCell, 0, 2);
                                    $shipping->setHM(1);
                                } elseif (mb_strstr($valueCell, '2A/2B')) {
                                    $county = 20;
                                } elseif (mb_strlen($countyCell) < 2) {
                                    $county = '0'.$countyCell;
                                } else {
                                    $county = $countyCell;
                                }

                                $shipping->setCounty($county);

                                $value = (float) str_replace(',', '.', (string) $data[$cc]);

                                $shipping->setQtyOf($shippingQtyCollection[$cc]['of'] ?? 0);
                                $shipping->setQtyAt($shippingQtyCollection[$cc]['at'] ?? null);

                                if ($value > 10) {
                                    $shipping->setPackagePrice((int) ($value * 100));
                                } else {
                                    $shipping->setBottlePrice((int) ($value * 100));
                                }

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

                $this->em->flush();
                fclose($handle);

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

        // =========================
        // FICHIER SUP
        // =========================
        if ($fileSup) {
            $xlsxSupPath = $this->filesystem->absolutePath('file', $config->getFileSup()->getPath());
            $spreadsheetSup = $reader->load($xlsxSupPath);

            $writerSup = new Csv($spreadsheetSup);
            $writerSup->setSheetIndex(1);

            $csvSupPath = $this->filesystem->absolutePath('file', 'oenotrans_sup.csv');
            $writerSup->save($csvSupPath);

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

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

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

                $row = 0;
                while (($data = fgetcsv($handle, 1000, ',')) !== false) {
                    ++$row;

                    $firstCityBegin = 0;
                    $secondCityBegin = 3;

                    if (!isset($data[$firstCityBegin]) || !is_numeric($data[$firstCityBegin])) {
                        continue;
                    }

                    if ((int) $data[$firstCityBegin] < 10) {
                        $data[$firstCityBegin] = '0'.$data[$firstCityBegin];
                    }

                    $cityColumn = $firstCityBegin + 1;
                    $city = (string) ($data[$cityColumn] ?? '');

                    $shippingSup = new ShippingAutoSup();
                    $shippingSup->setCountry('FR');
                    $shippingSup->setCounty((string) $data[$firstCityBegin]);
                    $shippingSup->setOldName((string) ($data[$cityColumn] ?? ''));
                    $shippingSup->setCity($city);
                    $this->em->persist($shippingSup);

                    if (isset($data[$secondCityBegin]) && is_numeric($data[$secondCityBegin])) {
                        if ((int) $data[$secondCityBegin] < 10) {
                            $data[$secondCityBegin] = '0'.$data[$secondCityBegin];
                        }

                        $cityColumn = $secondCityBegin + 1;
                        $city = (string) ($data[$cityColumn] ?? '');

                        $shippingSup2 = new ShippingAutoSup();
                        $shippingSup2->setCountry('FR');
                        $shippingSup2->setCounty((string) $data[$secondCityBegin]);
                        $shippingSup2->setOldName((string) ($data[$cityColumn] ?? ''));
                        $shippingSup2->setCity($city);
                        $this->em->persist($shippingSup2);
                    }

                    // comportement existant : break après la première ligne valide
                    break;
                }

                $this->em->flush();
                fclose($handle);

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

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