<?php

namespace Modules\Additional\Specifique\Client155\Modules\Fournisseur\Outil;

use Entity\Model\Fourniss;
use Entity\Model\Periodes;
use Entity\Model\SousFamille;
use Entity\Model\TSDon;
use Helpers\ExportTo\Generate;
use Helpers\Fichier\Fichier;
use Helpers\Phpspreadsheet\SpreadsheetHelper;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use PhpOffice\PhpSpreadsheet\IOFactory;

class ImportReporting
{
    const FILE_MODE = 'r';
    const SEPARATOR = ',';

    /** @var array<mixed>  */
    private static array $baseMapping = [
        [
            'sqlChamp'      => 'CODE_PERIODE',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'CODE_FOURNISSEUR',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'RS_FOURNISSEUR',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'CODE_SOUS_FAMILLE',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'LIBELLE_SOUS_FAMILLE',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'MONTANT_CA_PREVI',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'OBJECTIF_NE',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'OBJECTIF_NE_PERCENT',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'RESULT_NE',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'RESULT_NE_PERCENT',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'GAIN_PROMOTIONNEL',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'GAIN_EXCEPTIONNEL',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'TAUX_ADHESION',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'COM_TAUX_ADHESION',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'HAUSSE_ASKED',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'HAUSSE_VALIDATED',
            'dataType'      => 'float',
        ],
        [
            'sqlChamp'      => 'DATE_APPLICATION',
            'dataType'      => 'date',
        ],
        [
            'sqlChamp'      => 'DETAIL_HAUSSE',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'CODE_CANAL',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'LIBELLE_CANAL',
            'dataType'      => 'string',
        ],
        [
            'sqlChamp'      => 'MOV_DOSS',
            'dataType'      => 'string',
        ],
    ];

    /** @var string $type */
    private string $type;

    private ITrad $trad;

    public function __construct(string $type, ITrad $trad)
    {
        $this->type = $type;
        $this->trad = $trad;
    }

    /**
     * @var array<mixed>
     */
    private array $mappingBuffer;

    /**
     * @return array<mixed>
     */
    private function getMapping()
    {
        if (isset($this->mappingBuffer)) {
            return $this->mappingBuffer;
        }

        $mapping = self::$baseMapping;
        if ($this->type === 'mono') {
            $mapping = array_values(array_filter($mapping, function ($fieldConf) {
                return ! in_array($fieldConf['sqlChamp'], [
                    'CODE_FOURNISSEUR',
                    'RS_FOURNISSEUR',
                ]);
            }));
        }
        return $this->mappingBuffer = $mapping;
    }

    /**
     * Prépare le traitement du fichier en récupérant l'extension ainsi que le contenu
     * Avec les éventuelles erreurs liées à la structure de l'entête
     * @return void
     * @throws \Exception
     */
    public function prepareTreatment()
    {
    }

    /**
     * @return array<mixed>
     * @throws \Exception
     */
    public function extractFromCsv(string $file)
    {
        $list = [];

        $header = false;
        $headerInFile = array_column($this->getMapping(), 'sqlChamp');
        $fp = fopen($file, self::FILE_MODE);
        while ($fp && ($data = fgetcsv($fp, 0, self::SEPARATOR)) !== false) {
            if (! $header) {
                $header = true;
                continue;
            }
            
            $row = array_combine($headerInFile, $data);
            foreach ($row as $k => &$v) {
                $v = $this->processValue($k, $v);
            }
            $list[] = $row;
        }

        return $list;
    }

    /**
     * @return array<mixed>
     * @throws \PhpOffice\PhpSpreadsheet\Calculation\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function extractFromExcel(string $file)
    {
        $objReader = IOFactory::createReader(IOFactory::identify($file));
        $objReader->setReadDataOnly(true);
        $sheet = $objReader->load($file)->getSheet(0);
        $nbRow = $sheet->getHighestRow();

        $listEntity = [];
        foreach ($sheet->getRowIterator(1, $nbRow) as $rowId => $row) {
            $entity = [];
            
            // Ignore Title row
            if ($rowId === 1) {
                continue;
            }
            
            foreach ($this->getMapping() as $colIndex => $mapping) {
                $cell = $sheet->getCellByColumnAndRow($colIndex + 1, $rowId);

                // Première ligne = en tête
                $value = $cell->getCalculatedValue();

                $key = $mapping['sqlChamp'];

                if ($mapping['dataType'] === 'date') {
                    $value = SpreadsheetHelper::parseDate($cell->getValue());
                }

                $value = $this->processValue($key, $value);

                $entity[ $key ] = $value;
            }

            $listEntity[] = $entity;
        }

        return $listEntity;
    }

    /**
     * @param mixed $value
     * @return mixed
     */
    private function processValue(string $key, $value)
    {
        
        $mapping = array_column(
            $this->getMapping(),
            null,
            'sqlChamp'
        );
        $dataType = $mapping[ $key ]['dataType'];

        $valToReturn = trim($value?? '', " \r\n");// Note : do not trim '0'
        switch ($dataType) {
            case "float":
                return (float)number_format((float)$valToReturn, 2, '.', '');

            // case "date":
            // case "string":
            // default:
            //     return (string) $valToReturn;
        }

        return $valToReturn;
    }

    /**
     * @return Generate|string
     */
    public function generatePattern()
    {
        $trad = $this->trad;
        $fileName = 'exempleImportReporting_'.$this->type;

        if (!Fichier::fileExisteTmp($fileName)) {
            $generate = new Generate($fileName, 'excel', [], array_merge(
                [
                    $trad->t('Période'),
                ],
                ($this->type !== 'mono' ? [
                    $trad->t('Code fournisseur'),
                    $trad->t('Raison sociale fournisseur'),
                ] : []),
                [
                    $trad->t('Code ss famille'),
                    $trad->t('Libellé ss famille'),
                    $trad->t('CA prévisionnel'),
                    $trad->t('CA réalisé N-1'),
                    $trad->t('Objectif négo en EUR'),
                    $trad->t('Objectif négo en %'),
                    $trad->t('Résultat de négo en EUR'),
                    $trad->t('Résultat de négo en %'),
                    $trad->t('Gain additionnel promotionnel'),
                    $trad->t('Gain exceptionnel'),
                    $trad->t('Taux d\'adhésion'),
                    $trad->t('Comm. taux d\'adhésion'),
                    $trad->t('Hausse demandée en EUR'),
                    $trad->t('Hausse validée en EUR'),
                    $trad->t('Date d\'application'),
                    $trad->t('Détail des hausses'),
                    $trad->t('Code canal'),
                    $trad->t('Libellé Canal'),
                    $trad->t('Mouvement dossiers'),
                ]
            ), false, false);
        } else {
            $generate = Fichier::URLDownload($fileName);
        }

        /** @phpstan-ignore-next-line */
        return $generate;
    }
}
