<?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 SchenkerProvider implements CarrierProviderInterface
{
    public const string TYPE = 'DB-Schenker';

    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;

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

            // =========================
            // 1) SHEET "zoning"
            // =========================
            $reader->setLoadSheetsOnly(['zoning']);

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

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

            $zoneList = [];
            $shippingQtyCollection = [];

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

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

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

                while (($data = fgetcsv($handle, 1000, ',')) !== false) {
                    $count = \count($data);
                    for ($i = 0; $i < $count; ++$i) {
                        if (($data[$i] ?? null) === 'FRANCE') {
                            $zoneNumber = (int) mb_substr((string) ($data[$i + 2] ?? ''), 2, 1);
                            $department = mb_substr((string) ($data[$i + 3] ?? ''), 0, 2);
                            if ($zoneNumber > 0 && '' !== $department) {
                                $zoneList[$zoneNumber][] = $department;
                            }
                        }
                    }
                }

                fclose($handle);

                // =========================
                // 2) SHEET "transport"
                // =========================
                $reader->setLoadSheetsOnly(['transport']);
                $spreadsheet2 = $reader->load($xlsxPath);

                $writer2 = new Csv($spreadsheet2);
                $transportCsvPath = $this->filesystem->absolutePath('file', 'schenker-transport.csv');
                $writer2->save($transportCsvPath);

                $handle2 = fopen($transportCsvPath, 'r');
                if (false === $handle2) {
                    $connection->commit();

                    return;
                }

                // (comportement historique) on retronque ShippingAuto encore une fois
                (new CarrierTableTruncator())->truncate($connection, $classMetaData->getTableName());

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

                    for ($i = 0; $i < $num; ++$i) {
                        // Ajout des quantités minimum
                        if (($data[$i] ?? null) === 'Nombre de bouteilles') {
                            for ($c = 1; $c < $num; ++$c) {
                                if (($data[$c] ?? '') !== '') {
                                    $shippingQtyCollection[$c - 2]['of'] = ((int) $data[$c]) - 1;
                                }
                            }
                        }

                        // Ajout des quantités maximum
                        $cell = (string) ($data[$i] ?? '');
                        if ('' !== $cell && 'à' === mb_substr($cell, 1, 1, 'UTF-8')) {
                            for ($d = 0; $d < $num; ++$d) {
                                if (($data[$d] ?? '') !== '') {
                                    $maxQuantity = (int) filter_var((string) $data[$d], \FILTER_SANITIZE_NUMBER_INT);
                                    $shippingQtyCollection[$d - 2]['at'] = (string) $maxQuantity;
                                }
                            }
                        }
                    }

                    if (isset($data[0], $data[1]) && is_numeric($data[0]) && (explode(' ', (string) $data[1])[0] ?? '') === 'Zone') {
                        $zone = (int) (explode(' ', (string) $data[1])[1] ?? 0);
                        $departmentsPerZone = $zoneList[$zone] ?? [];

                        for ($e = 2; $e < $num; ++$e) {
                            if (($data[$e] ?? '') === '') {
                                continue;
                            }

                            $price = (float) str_replace(',', '.', (string) $data[$e]);

                            foreach ($departmentsPerZone as $department) {
                                $shipping = new ShippingAuto();
                                $shipping->setCountry('FR');
                                $shipping->setCounty($department);

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

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

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

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

                $connection->commit();
            } catch (\Throwable $e) {
                fclose($handle);
                if (isset($handle2) && \is_resource($handle2)) {
                    fclose($handle2);
                }
                $connection->rollBack();
                throw $e;
            }
        }

        // =========================
        // FICHIER SUP
        // =========================
        if ($fileSup) {
            $readerSup = new Xlsx();
            $readerSup->setReadDataOnly(true);

            $xlsxSupPath = $this->filesystem->absolutePath('file', $config->getFileSup()->getPath());
            $spreadsheetSup = $readerSup->load($xlsxSupPath);

            $writerSup = new Csv($spreadsheetSup);
            $supCsvPath = $this->filesystem->absolutePath('file', 'geodis_sup.csv');
            $writerSup->save($supCsvPath);

            $handle = fopen($supCsvPath, '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) {
                    if ($row > 0) {
                        if (mb_strlen((string) ($data[1] ?? '')) < 5) {
                            $data[1] = '0'.$data[1];
                        }
                        if (mb_strlen((string) ($data[3] ?? '')) < 2) {
                            $data[3] = '0'.$data[3];
                        }

                        $shippingSup = new ShippingAutoSup();
                        $shippingSup->setCountry('FR');
                        $shippingSup->setCounty((string) ($data[3] ?? ''));
                        $shippingSup->setPostal((string) ($data[1] ?? ''));

                        $city = mb_trim((string) ($data[2] ?? ''));

                        // $city = str_replace(" ST ", " SAINT ", trim($data[2]));
                        // $city = str_replace("ST ", "SAINT ", $city);
                        // $city = $this->checkCity->check($city, $data[3], $data[1]);
                        // if ($city) {
                        //     $shippingSup->setVerification(1);
                        // }

                        $shippingSup->setOldName(mb_trim((string) ($data[2] ?? '')));
                        $shippingSup->setCity($city);

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

                    ++$row;
                }

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

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

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