<?php

namespace Modules\Panier\Service;

use Entity\Model\OxaUserPanier;
use Entity\Model\OxaUserPanierFour;
use Entity\Model\OxaUserPanierFourContact;
use Entity\Model\OxaUserPanierLigne;
use Helpers\Outil\ArrayHelper;
use Helpers\Outil\Sql;
use Helpers\Parametres\Constante;
use Modules\Ajax\Repository\Listes;
use Modules\Panier\Repository\PanierEntete;
use Modules\Panier\Repository\PanierFrs;
use Modules\Panier\Repository\PanierLigne;

class CritereRegroupService
{
    private \PDO $pdo;
    private \PDO $pdoOxaFT;

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

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

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

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

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

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

    /**
     * @var array<mixed>
     */
    private $bufferZoneGeo;
    private bool $isMobility;


    public function __construct(\PDO $pdo, \PDO $pdoOxaFT)
    {
        $this->pdo = $pdo;

        $this->pdoOxaFT = $pdoOxaFT;

        $listeCritereRegroup = (new OxaUserPanierFour($this->pdo))->findall([
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
        ]);

        $listeCtcFrsLiv = (new OxaUserPanierFourContact($this->pdo))->findAll([
            'ID_USER'       => $_SESSION['id_user'],
            'ID_PANIER'     => $_SESSION['id_panier'],
        ]);

        $this->infoPanier = (new OxaUserPanier($this->pdo))->find([
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
        ]);
        
        
        $listeCtcFrsPanier = [];
        foreach ($listeCtcFrsLiv as $ctc) {
            $listeCtcFrsPanier[$ctc['CRITERE_REGROUP']][$ctc['CODE_FOURN']][$ctc['CTC_TYPE']][$ctc['CTC_IND']][] = $ctc;
        }
        
        $this->listeCtcFrsPanier = $listeCtcFrsPanier;
        $this->listeCritereRegroup = array_column($listeCritereRegroup, null, 'CRITERE_REGROUP');

        $this->listeInfoFrs = [];
        $this->listeTypeAchatByFrs = [];

        $this->bufferZoneGeo = [];

        $this->isMobility = false;

        $this->parametrage = [
            'ADRCDEFOUR_INITDEFAUT'             => Sql::paravrac($this->pdo, 'OXAPROC', 'ADRCDEFOUR_INITDEFAUT') != 'N',
            'CHOIX_INIT_FAXMAILFOUR_SUR_CDE'    => Sql::paravrac($this->pdo, 'PARAMGEN', 'CHOIX_INIT_FAXMAILFOUR_SUR_CDE') == 'O',
        ];
    }

    public function setMobility(bool $isMobility): void
    {
        $this->isMobility = $isMobility;
    }

    public function regroupementCritere(string $critere = null, string $codeFou = null, bool $fraisPort = false) : void
    {
        $listeRegroup = (new OxaUserPanierLigne($this->pdo))->findAll(
            [
            'id_user' => $_SESSION['id_user'],
            'id_panier' => $_SESSION['id_panier'],
            ]
            + ($critere? [
            'CRITERE_REGROUP' => $critere
            ]:[])
            + ($codeFou? [
            'COD_FOURN' => $codeFou
            ]:[]),
            ['DISTINCT CRITERE_REGROUP', 'COD_FOURN', 'COD_DEV']
        );

        $listeFrs = [];
        foreach ($listeRegroup as $regroup) {
            $listeFrs[$regroup['COD_FOURN']] = $regroup['COD_FOURN'];
        }

        $panierFrs = new PanierFrs($this->pdo);

        $listeTmp = $panierFrs->getInfoFrsAndMainContact($listeFrs);
        $this->listeInfoFrs = array_column($listeTmp, null, 'CODE');
        
        $typeAchatParDefaut = sql::paravrac($this->pdo, 'PARAMFOU', 'INITTAC');
        $listeTypeAchatTmp = (new PanierEntete($this->pdo))->getListeTypeAchatByFrs($listeFrs, $typeAchatParDefaut);

        $this->listeTypeAchatByFrs = ArrayHelper::indexBy($listeTypeAchatTmp, 'CODE');

        $this->listeTypeAchatByFrs[Constante::fournisseurStock] = [[
            'TACFOTAC' => $typeAchatParDefaut,
        ]];

        foreach ($listeRegroup as $regroup) {
            $this->controleBlocRegroupement($regroup, $fraisPort);
        }
        
        $panierFrs->deleteGroupWithNoLine();
    }

    /**
     * @param array<mixed> $critere
     * @return void
     */
    private function controleBlocRegroupement($critere, bool $fraisPort = false) : void
    {
        $infoFourPanier = $this->listeCritereRegroup[$critere['CRITERE_REGROUP']]??[];

        $codeFrs = $critere['COD_FOURN'];
        $listeCtcFrsPanier = $this->listeCtcFrsPanier[$critere['CRITERE_REGROUP']][$codeFrs]??[];

        if (!$this->listeInfoFrs) {
            $infoFrs = (new PanierFrs($this->pdo))->getInfoFrsAndMainContact($codeFrs);
        } else {
            $infoFrs = $this->listeInfoFrs[$codeFrs]??[];
        }

        $typeAchat = $this->initTypeAchat($codeFrs);

        $adresseFrsinit = [];
        if (!$infoFourPanier) {
            ValidationPanierService::cleanPanierSession();
            $post = [
                'filter_egal_CODE' => $codeFrs,
                'ADR_COMMANDE'   => '0x54',
            ];


            if (Sql::paravrac($this->pdo, 'OXAPROC', 'ZGEO_SUR_CTR_EMETTEUR') != 'O') {
                $centreZoneGeo = explode('|', $critere['CRITERE_REGROUP'])[2];
            } else {
                $centreZoneGeo = $this->infoPanier['OUPA_CENTRE_EMETTEUR'];
            }

            $zoneGeoCentre = $this->getZoneCentre($centreZoneGeo);

            $adresseFrsinit = $this->getAdresseFrs(
                $this->pdo,
                $zoneGeoCentre,
                $post,
                $infoFrs,
                $this->parametrage['ADRCDEFOUR_INITDEFAUT']
            );

            $arrayInsert = [
                'id_user'                   => $_SESSION['id_user'],
                'id_panier'                 => $_SESSION['id_panier'],
                'CRITERE_REGROUP'           => $critere['CRITERE_REGROUP'],
                
                'COD_FOURN'                 => $codeFrs,
                'MDP'                       => $infoFrs['MODE_PAIE']??'',
                'CDP'                       => $infoFrs['COND_PAIE']??'',
                'MDL'                       => $infoFrs['LIV']??'',
                
                //typeAchat
                'TYP_ACH'                   => $typeAchat,
                
                // adresse
                'CODE_PAYS'                 => $adresseFrsinit['CODE_PAYS']??'',
                'CPOSTAL'                   => $adresseFrsinit['CPOSTAL']??'',
                'VILLE1'                    => $adresseFrsinit['VILLE1']??'',
                'ADR'                       => $adresseFrsinit['ADR']??'',
                
                //date de livraison etc
                'numerique_RECEP_AUTO'      => Sql::setBoolSql(sql::boolSql(($infoFrs['RECEP_AUTO']??false))),
                'PER_REC_AUTO'              => $infoFrs['PER_REC_AUTO']??'',
                'DATELIVR'                  => '',
                'DATEDEBCONT'               => sql::boolSql(($infoFrs['RECEP_AUTO']??false))? '00000000':'',
                'DATEFINCONT'               => sql::boolSql(($infoFrs['RECEP_AUTO']??false))? '00000000':'',
                'FIN_DEB_PER'               => '',
                'OUPF_RECEPAUTO_JOUR'       => '',
                
                'numerique_flg_add_pj'      => '0x46',
                'numerique_flg_add_clause'  => '0x46',
            ];

            (new OxaUserPanierFour($this->pdo))->insert($arrayInsert);

            if ($arrayInsert['PER_REC_AUTO']) {
                (new OxaUserPanierLigne($this->pdo))->update(['PER_REC_AUTO' => $arrayInsert['PER_REC_AUTO']], [
                    'id_user'                   => $_SESSION['id_user'],
                    'id_panier'                 => $_SESSION['id_panier'],
                    'CRITERE_REGROUP'           => $critere['CRITERE_REGROUP'],
                ]);
            }

            if ($fraisPort) {
                (new PanierLigneService($this->pdo, $this->pdoOxaFT, 'panier'))->calculFraisDePort('', $critere['CRITERE_REGROUP'], $codeFrs);
            }
        } else {
            if ($typeAchat) {
                $oxaUserFour = (new OxaUserPanierFour($this->pdo))->find([
                    'id_user' => $_SESSION['id_user'],
                    'id_panier' => $_SESSION['id_panier'],
                    'CRITERE_REGROUP' => $critere['CRITERE_REGROUP'],
                ], ['TYP_ACH']);

                if ($oxaUserFour['TYP_ACH'] == '') {
                    (new OxaUserPanierFour($this->pdo))->update(['TYP_ACH' => $typeAchat], [
                        'id_user' => $_SESSION['id_user'],
                        'id_panier' => $_SESSION['id_panier'],
                        'CRITERE_REGROUP' => $critere['CRITERE_REGROUP']
                    ]);
                }
            }
        }

        if (!isset($listeCtcFrsPanier['fournisseur'][0])) {
            if ($adresseFrsinit) {
                $ctcFrs = (new PanierFrs($this->pdo))->getInfoCtcAdresse($codeFrs, $adresseFrsinit['COD_ADR']);
            } else {
                $ctcFrs = $infoFrs;
            }

            $arrayContact = [
                'ID_USER'       => $_SESSION['id_user'],
                'ID_PANIER'     => $_SESSION['id_panier'],
                'CTC_TYPE'      => 'fournisseur',
                'CTC_IND'       => 0,
                'CODE_CTR_LIV'  => '',
                'CODE_FOURN'    => $codeFrs,
                'CTC_NOM'       => $ctcFrs['CTC_NOM']??'',
                'CTC_TEL'       => $ctcFrs['CTC_TEL']??'',
                'CTC_FCT'       => $ctcFrs['CTC_FCT']??'',
                'CTC_GSM'       => $ctcFrs['CTC_GSM']??'',
                'CRITERE_REGROUP' => $critere['CRITERE_REGROUP'],
    
                'CTC_FAX'       => $infoFrs['CTC_FAX']??'',
                'CTC_MAIL'      => $infoFrs['CTC_MAIL']??'',
            ];

            if ($this->parametrage['CHOIX_INIT_FAXMAILFOUR_SUR_CDE']) {
                $arrayContact['CTC_FAX']    = $adresseFrsinit['FAX']??'';
                $arrayContact['CTC_MAIL']   = $adresseFrsinit['EMAIL']??'';
            }
            
            (new OxaUserPanierFourContact($this->pdo))->insert($arrayContact);
        }

        if (!isset($listeCtcFrsPanier['livraison'][0])) {
            $arrayContact = [
                'ID_USER'       => $_SESSION['id_user'],
                'ID_PANIER'     => $_SESSION['id_panier'],
                'CTC_TYPE'      => 'livraison',
                'CTC_IND'       => 0,
                'CODE_CTR_LIV'  => $this->infoPanier['LIV_CTR']??'',
                'CODE_FOURN'    => $codeFrs,
                'CTC_NOM'       => $this->infoPanier['CTC_NOM']??'',
                'CTC_TEL'       => $this->infoPanier['CTC_TEL']??'',
                'CTC_FCT'       => $this->infoPanier['CTC_FCT']??'',
                'CTC_GSM'       => $this->infoPanier['CTC_GSM']??'',
                'CTC_FAX'       => $this->infoPanier['CTC_FAX']??'',
                'CTC_MAIL'      => $this->infoPanier['CTC_MAIL']??'',

                'CRITERE_REGROUP' => $critere['CRITERE_REGROUP'],
            ];

            (new OxaUserPanierFourContact($this->pdo))->insert($arrayContact);
        }
    }

    /**
     * Summary of initTypeAchat
     * @param string $codeFrs
     * @return string
     */
    private function initTypeAchat($codeFrs)
    {
        if (!$this->listeInfoFrs) {
            $listeTypeAchat = (new PanierEntete($this->pdo))->getListeTypeAchatByFrs([$codeFrs], '');
        } else {
            $listeTypeAchat = $this->listeTypeAchatByFrs[$codeFrs]??[];
        }

        $typeAchat = '';
        if (count($listeTypeAchat) == 1 || $this->isMobility) {
            $typeAchat = $listeTypeAchat[array_key_first($listeTypeAchat)]['TACFOTAC'];
        } else {
            $specifique = new \Helpers\Additional\Specifique\Specifique();
            $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Panier\\Service\\SpecPanierLigneService');
            if (class_exists($namespaceSpecifique)) {
                $typeAchat = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Panier\\Service\\SpecPanierLigneService', 'initTypeAchat', $listeTypeAchat);
            }
        }

        return $typeAchat;
    }

    /**
     * @return array<mixed>
     */
    private function getZoneCentre(string $centre)
    {
        if (isset($this->bufferZoneGeo[$centre])) {
            $zoneCentre = $this->bufferZoneGeo[$centre];
        } else {
            $liste = new Listes($this->pdo);
            $zoneCentre = $liste->calculZoneGeoCentre($centre);
            $this->bufferZoneGeo[$centre] = $zoneCentre;
        }

        return $zoneCentre;
    }

    /**
     * <div class=""></div>
     *
     * @param \PDO $pdo
     * @param array<mixed> $zoneGeoCentre
     * @param array<mixed> $post
     * @param array<mixed> $infoFrs
     * @param boolean $paramAdrFouInit
     * @return array<mixed>
     */
    public static function getAdresseFrs(
        \PDO $pdo,
        $zoneGeoCentre,
        $post,
        $infoFrs,
        bool $paramAdrFouInit
    ) {
        $liste = new Listes($pdo);
        $listeAdresse = $liste->adresseFournisseur($post, $zoneGeoCentre, null);

        if (count($listeAdresse)>1 && !$paramAdrFouInit) {
            $adresseFrsinit = [
                'COD_ADR'   => '',
                'VILLE1'    => '',
                'ADR'       => '',
                'CPOSTAL'   => '',
                'CODE_PAYS' => '',
                'EMAIL'     => '',
                'FAX'       => '',
            ];
        } elseif ($listeAdresse) {
            $fkey = array_key_first($listeAdresse);

            $adresseFrsinit = [
                'COD_ADR'   => $listeAdresse[$fkey]['COD_ADR'],
                'VILLE1'    => $listeAdresse[$fkey]['VILLE1'],
                'ADR'       => $listeAdresse[$fkey]['ADRESSE'],
                'CPOSTAL'   => $listeAdresse[$fkey]['CPOSTAL'],
                'CODE_PAYS' => $listeAdresse[$fkey]['CODPAYS'],

                'EMAIL'     => $listeAdresse[$fkey]['EMAIL'],
                'FAX'       => $listeAdresse[$fkey]['FAX'],
            ];
        } else {
            $adresseFrsinit = [
                'COD_ADR'       => '',
                'VILLE1'        => $infoFrs['VILLE1']??'',
                'ADR'           => $infoFrs['ADR']??'',
                'CPOSTAL'       => $infoFrs['CPOSTAL']??'',
                'CODE_PAYS'     => $infoFrs['CODE_PAYS']??'',
                
                'EMAIL'         => $infoFrs['CTC_MAIL']??'',
                'FAX'           => $infoFrs['CTC_FAX']??'',
            ];
        }

        return $adresseFrsinit;
    }

    /**
     * @param array<mixed> $lignePanier
     * @return string
     */
    public static function generateCritere($lignePanier):string
    {
        $newCritereRegourp =
            $lignePanier['COD_FOURN'] . '|' .
            $lignePanier['COD_DEV'] . '|' .
            $lignePanier['CodeCtrLivraison'] . '|' .
            $lignePanier['MODE_TRS'];
            
        $specifique = new \Helpers\Additional\Specifique\Specifique();
        $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Panier\\Service\\SpecPanierLigneService');
        if (class_exists($namespaceSpecifique)) {
            $newCritereRegourp = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Panier\\Service\\SpecPanierLigneService', 'recalculCritereRegroupSpecifique', $newCritereRegourp, $lignePanier);
        }

        return $newCritereRegourp;
    }

    /**
     * @return array<mixed>
     */
    public static function recalculCritereRegroup(\PDO $pdo, int $id_panier, string $idLignePanier) : ?array
    {
        $changement = false;
        $critereRegroupement = '';
        
        $panierLigne = new PanierLigne($pdo);
        $panierEntete = new PanierEntete($pdo);
        
        $lignePanier = $panierLigne->getAllLignePanier($id_panier, $idLignePanier);
        if ($lignePanier) {
            $oldCritereRegroup = $lignePanier['CRITERE_REGROUP'];
            $newCritereRegourp = self::generateCritere($lignePanier);

            $critereRegroupement = $newCritereRegourp;
            
            if ($oldCritereRegroup != $newCritereRegourp) {
                //todo REMOVE V12
                $_SESSION['CRITERE_REG_CHANGE'] = true;
                
                $infoCritere = explode('|', $oldCritereRegroup);
                $arrayOld = [
                    'COD_FOURN' => $infoCritere[0],
                    'CRITERE_REGROUP' => $oldCritereRegroup
                ];
                
                if ($infoCritere[0] == $lignePanier['COD_FOURN']) {
                    $arrayNew = [
                        'COD_FOURN' => $infoCritere[0],
                        'CRITERE_REGROUP' => $newCritereRegourp
                    ];
                    
                    $infoBlocFournisseurOld = $panierEntete->getInfoFourPanier($arrayOld);
                    if ($infoBlocFournisseurOld) {
                        $infoBlocFournisseurNew = $panierEntete->getInfoFourPanier($arrayNew);
                        if (!$infoBlocFournisseurNew) {
                            $panierEntete->rqCopiePanierFrsPanierPjChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                            $panierEntete->rqCopiePanierFrsPanierClauseChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                            $panierEntete->rqCopiePanierContactLivByBlocFrsClauseChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                            $panierEntete->rqCopiePanierContactFrsByBlocFrsClauseChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                            $panierEntete->rqCopiePanierFrsChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                            $panierEntete->rqCopiePanierFrsPanierDocRattChangeCritere($id_panier, $oldCritereRegroup, $newCritereRegourp);
                        }
                    }
                }
                $panierEntete->rqUpdateCritereRegroupementLigne($idLignePanier, $newCritereRegourp);
                
                $test = $panierEntete->rqGetLignePanierBlocFournisseur($id_panier, $arrayOld);
                if ($test) {
                    $panierEntete->rqDeleteDocRattRegroupement($id_panier, $arrayOld);
                    $panierEntete->rqDeletePjRegroupement($id_panier, $arrayOld);
                    $panierEntete->rqDeleteClauseRegroupement($id_panier, $arrayOld);
                    $panierEntete->rqDeleteContactRegroupement($id_panier, $arrayOld);
                }
                $changement = true;
            }
        }
        
        if ($changement) {
            ValidationPanierService::cleanPanierSession();
        }

        return [
            'changement' => $changement,
            'critereRegroupement' => $critereRegroupement,
        ];
    }
}
