<?php
namespace Modules\Catalogue\Controller;

use Entity\Model\CFormats;
use Entity\Model\CrossRefFmt;
use Entity\Model\FmtMapp;
use Entity\Model\FValDef;
use Entity\Model\MultiMapp;
use Entity\Model\MultiTranscod;
use Entity\Model\PFormats;
use Entity\Model\RegValid;
use Entity\Model\Transcod;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\Ariane;
use Helpers\Ariane\ArianeSub;
use Helpers\Fichier\Fichier;
use Helpers\Outil\ArrayHelper;
use Helpers\Outil\Sql;
use Helpers\Pagination\PaginatorGestion;
use Helpers\Securite\Securite;
use Helpers\Session\ParseBase1;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Modules\Catalogue\Enum\ListeFormatEnum;
use Modules\Catalogue\MenuContextuel\FormatMenuContextuel;
use Modules\Catalogue\Repository\FormatRepository;
use Modules\Catalogue\Service\MappingDefaultService;
use Modules\Catalogue\Validator\FormatValidator;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use PHPStan\Type\ArrayType;
use Skeleton\Controller\Controller;

class FormatController extends Controller
{

    public function listeFormatAction():string
    {
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();

        if (!$post) {
            $post['tri_IDFORMAT'] = 'ASC';
        }

        $paginator = new \Helpers\Pagination\PaginatorGestion();
        $paginator->generate(0, 'IDFORMAT');
        $listeFormat = (new FormatRepository($this->pdo))->getListeFormat($post);

        $formatMenuContextuel = new FormatMenuContextuel($this->pdo, $this->router, $trad);
        foreach ($listeFormat as &$format) {
            $format['menuContextuel'] = $formatMenuContextuel->generate($format);
        }

        $nombreArticle  = PaginatorGestion::getNbrArticle();
        $infopagination = PaginatorGestion::getInfoPagination();

        Ariane::generate(0, $trad->t('Gestion des formats'), $post, $nombreArticle);

        return $this->renderer->render('@catalogue/Format/listeFormat', [
            'menuActive'        => 'Catalogue',
            'typeFormat'        => [...ListeFormatEnum::getAsAssoc($trad)],
            'listeFormat'       => $listeFormat,
            'post'              => $post,
            'infoPagination'    => $infopagination,
        ]);
    }

    public function createAction():string
    {
        $trad = $this->getTranslationService();

        $format['TYPDATAS'] = 'CSV';
        Ariane::generate(1, $trad->t('Création d\'un format'));

        $listeCle = (new CrossRefFmt($this->pdo))->fetchAll(['DISTINCT IDCLE']);
        $listeCle = array_column($listeCle, 'IDCLE', 'IDCLE');

        $listeConnecteur = (new CrossRefFmt($this->pdo))->fetchAll();
        $listeConnecteur = ArrayHelper::indexBy($listeConnecteur, 'IDCLE');
        foreach ($listeConnecteur as &$connecteur) {
            $connecteur = array_column($connecteur, 'NOM_PARAMETRE', 'NOM_PARAMETRE');
        }

        return $this->renderer->render('@catalogue/Format/creatEdit', [
            'menuActive'        => 'Catalogue',
            'format'            => $format,
            'typeFormat'        => [...ListeFormatEnum::getAsAssoc($trad)],
            'listeConnecteur'   => $listeConnecteur,
            'listeCle'          => $listeCle,
        ]);
    }

    public function ajaxConnecteurAction():string
    {
        $listeConnecteur = (new CrossRefFmt($this->pdo))->fetchAll();
        $listeConnecteur = ArrayHelper::indexBy($listeConnecteur, 'IDCLE');
        foreach ($listeConnecteur as &$connecteur) {
            $connecteur = array_column($connecteur, 'NOM_PARAMETRE', 'NOM_PARAMETRE');
        }

        $listeCle = (new CrossRefFmt($this->pdo))->fetchAll(['DISTINCT IDCLE']);
        $listeCle = array_column($listeCle, 'IDCLE', 'IDCLE');

        return $this->renderer->render('@catalogue/Format/_connecteur', [
            'listeConnecteur'   => $listeConnecteur,
            'listeCle'          => $listeCle,
        ]);
    }

    public function validateAction():string|Response
    {
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();

        $connecteur = [];

        $validator = (new FormatValidator($this->pdo, $trad));
        $validator->validateForm($post);
        if ($post['TYPDATAS'] == 'OCI' || $post['TYPDATAS'] == 'cXML') {
            $validator->validateConnecteur($post, $connecteur);
        }

        if ($validator->isValid()) {
            (new PFormats($this->pdo))->delete(['IDFORMAT' => $post['IDFORMAT']]); // on s'assure qu'il n'existe pas un ancien paramétrage mal supprimé.

            (new CFormats($this->pdo))->insert([
                'IDFORMAT'      => $post['IDFORMAT'],
                'DESCFRMT'      => $post['DESCFRMT'] ,
                'TYPDATAS'      => $post['TYPDATAS'],
                'RACINEXML'     => $post['RACINEXML']??'',
                'DATECREAT'     => date('Ymd'),
                'HEURCREAT'     => date('His'),
                'CREATPAR'      => $_SESSION["Session_Login"],
                'DATEMODIF'     => date('Ymd'),
                'HEURMODIF'     => date('His'),
                'MODIFPAR'      => $_SESSION["Session_Login"],
                'ENCODING'      => $post['ENCODING'],
            ]);

            if ($post['TYPDATAS'] == 'OCI' || $post['TYPDATAS'] == 'cXML') {
                $mappingService = new MappingDefaultService(
                    (new Csv()),
                    (new ParseBase1()),
                    (new ArrayHelper()),
                    (new FmtMapp($this->pdo)),
                    (new MultiMapp($this->pdo)),
                    (new Transcod($this->pdo)),
                    (new FValDef($this->pdo)),
                    (new RegValid($this->pdo)),
                );
                $mappingService->setTypeMapping($post['TYPDATAS'] == 'OCI'? $mappingService::OCI:$mappingService::CXML);
                $mappingService->initializeMapping($post['IDFORMAT']);
            }

            foreach ($connecteur as $c) {
                (new PFormats($this->pdo))->insert([
                    'IDFORMAT'          => $post['IDFORMAT'],
                    'IDCLE'             => $c['IDCLE'],
                    'ORDRE'             => $c['ORDRE'],
                    'NOM_PARAMETRE'     => $c['NOM_PARAMETRE'],
                    'VALEUR_PARAM'      => $c['VALEUR_PARAM'],
                    'TYPE_PARAM'        => $c['TYPE_PARAM']
                ]);
            }

            return new Response(443, [], (string) json_encode(['path' => $this->router->generateUri('Catalogue.parametrageFormat.paramMappage', ['IdFormat' => $post['IDFORMAT']])]));
        } else {
            return new Response(200, [], $this->renderer->render('@popup-erreur/ErreurCreation', [
                'ErreurValid' => $validator->getError(),
                'desactiveRow' => true,
            ]));
        }
    }

    public function deleteAction():string
    {
        $idFormat = $this->request->getAttribute('IdFormat');

        (new CFormats($this->pdo))->delete($idFormat);
        (new PFormats($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        (new FmtMapp($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        (new MultiMapp($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        (new MultiTranscod($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        
        (new Transcod($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        (new FValDef($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        (new RegValid($this->pdo))->delete(['IDFORMAT' => $idFormat]);
        
        return '';
    }

    public function exportJsonAction():string
    {
        $idFormat = $this->request->getAttribute('IdFormat');

        $array = [
            'version'       => $this->getVersion(),
            'CFormats'      => (new CFormats($this->pdo))->find($idFormat),
            'PFormats'      => (new PFormats($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
            'FmtMapp'       => (new FmtMapp($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
            'MultiMapp'     => (new MultiMapp($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
            'MultiTranscod' => (new MultiTranscod($this->pdo))->findAll(['IDFORMAT' => $idFormat]),

            'Transcod'      => (new Transcod($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
            'FValDef'       => (new FValDef($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
            'RegValid'      => (new RegValid($this->pdo))->findAll(['IDFORMAT' => $idFormat]),
        ];

        $codeImport = Securite::encodeChiffrageFormMagic('*%*FORMAT_OXALYS*%*'.json_encode($array));

        $fileName = 'export_'.$idFormat.rand().'.oxa';
        Fichier::createFichierTmp($fileName, $codeImport);

        $message = fichier::UploadClient((new ParseBase1())->getRep()->tmp.$fileName, $fileName);

        return $message;
    }

    public function importJsonAction():Response|string
    {
        $post = $this->request->getParsedBody();
        $trad = $this->getTranslationService();
        $file = $this->request->getUploadedFiles();

        if ($post) {
            $newIDFORMAT = $post['newID'];
            $validator = $this->createValidator();
            $validator->isStringAvecEspace($trad->t('Identification du format'), $newIDFORMAT, 1, 30);

            $infoFormat = (new CFormats($this->pdo))->find($newIDFORMAT);
            $validator->isTrue($infoFormat, $trad->t('Ce code existe déjà.'));

            if ($file) {
                $fileName = $file['importimportFormat']->getClientFilename();
                $fileSize = $file['importimportFormat']->getSize();
            }

            $validator->fileCheck($trad->t('Fichier d\'import'), $fileName ?? '', [], '', $fileSize ?? 0);
            $newPath = Fichier::UploadDocAtt($fileName ?? '');
            $file['importimportFormat']->moveTo($newPath["racine"] . $newPath["new_name"]);

            $importFormat = (string)file_get_contents($newPath["racine"] . $newPath["new_name"]);
            $decode = securite::decodeChiffrageFromMagic($importFormat);

            $validator->isFalse(str_starts_with($decode, '*%*FORMAT_OXALYS*%*'), $trad->t('Le code d\'import est erroné.'));

            if (!$validator->isValid()) {
                return new Response(400, [], (string) json_encode([
                    'statut'    => 'E',
                    'message'   => $validator->getError()
                ]));
            }
            
            $tmp = str_replace('*%*FORMAT_OXALYS*%*', '', $decode);
            $json = json_decode($tmp, true);
            
            $this->clearJson($json, $newIDFORMAT);
    
            (new CFormats($this->pdo))->insert($json['CFormats']);
    
            foreach ($json['PFormats'] as $array) {
                (new PFormats($this->pdo))->insert($array);
            }
            foreach ($json['FmtMapp'] as $array) {
                (new FmtMapp($this->pdo))->insert($array);
            }
            foreach ($json['MultiMapp'] as $array) {
                (new MultiMapp($this->pdo))->insert($array);
            }
            foreach ($json['MultiTranscod'] as $array) {
                (new MultiTranscod($this->pdo))->insert($array);
            }
            
            foreach ($json['Transcod'] as $array) {
                (new Transcod($this->pdo))->insert($array);
            }
            foreach ($json['FValDef'] as $array) {
                (new FValDef($this->pdo))->insert($array);
            }
            foreach ($json['RegValid'] as $array) {
                (new RegValid($this->pdo))->insert($array);
            }

            return new Response(200, [], (string) json_encode([
                'path' => ariane::getBackPath(),
                'post' => Ariane::getBackPost(),
            ]));
        }

        return $this->renderer->render('@catalogue/Format/popupImport', [
        ]);
    }

    /**
     * Summary of clearJson
     * @param array<mixed> $array
     * @param string $newID
     * @return void
     */
    public function clearJson(&$array, $newID) :void
    {
        foreach ($array as $keyBloc => &$v) {
            if ($keyBloc == 'CFormats') {
                $v['IDFORMAT'] = $newID;
            } else {
                foreach ($v as &$subV) {
                    $subV['IDFORMAT'] = $newID;

                    if ($keyBloc == 'FmtMapp') {
                        $subV['ACTIVE'] = sql::boolSql($subV['ACTIVE'])? true:false;
                        $subV['OBLIGATOI'] = sql::boolSql($subV['OBLIGATOI'])? true:false;
                    }

                    if ($keyBloc == 'MultiMapp') {
                        $subV['CONTROLE'] = sql::boolSql($subV['CONTROLE'])? true:false;
                        $subV['TRANSCODAGE'] = sql::boolSql($subV['TRANSCODAGE'])? true:false;
                    }
                }
            }
        }
    }
}
