<?php

namespace Modules\Consultation\Service;

use Entity\Model\AoContFour;
use Entity\Model\AoContribGrp;
use Entity\Model\AoExcFofo;
use Entity\Model\AoFour;
use Entity\Model\AoFourQR;
use Entity\Model\AoLigne;
use Entity\Model\AoPijo;
use Entity\Model\AoClaus;
use Entity\Model\AoContrib;
use Entity\Model\AoQstTh;
use Entity\Model\AoRepQst;
use Entity\Model\AoRepSl;
use Entity\Model\ConsultDocDefault;
use Entity\Model\Hastutil;
use Entity\Model\TploOperations;
use Helpers\Fichier\Gestion_Fic_PJ;
use Helpers\Scheduler\Scheduler;
use Helpers\Trad\ITrad;
use Modules\Consultation\Enums\TypeConsultationsEnums;
use Modules\Consultation\Repository\Contributor;
use Modules\Consultation\Repository\QuestionReponseRepo;
use Modules\Evaluation\Repository\BibliothequeDeQuestions;
use Helpers\Outil\Sql;
use Entity\Model\Docatt;
use Modules\Consultation\Repository\Consultation;
use Entity\Model\AoQstQ;
use Entity\Model\AoQstR;
use Helpers\Fichier\Fichier;
use Entity\Model\AoEntet;
use Modules\Consultation\Repository\AoEvent;
use Entity\Model\AoRetParLigne;
use Entity\Model\AoDocAttendus;
use Entity\Model\AoGrpContrib;
use Entity\Model\AoPlann;
use Helpers\ChampsSupplementaire\ChampSupp;
use Modules\Consultation\Repository\GestionConsultation;
use Modules\Consultation\Repository\Reponse;
use Modules\ProjetAchat\Service\ActionService;
use Helpers\Outil\Mail;
use Helpers\Outil\Outils;
use Helpers\Outil\Date;
use Helpers\Session\ParseBase1;
use Helpers\Trad\Trad;
use Skeleton\Router;

class ConsultationService
{
    public function __construct(
        private \PDO $pdo,
        private ITrad $trad,
        private ?Router $router = null,
    ) {
    }

    public function deleteComposant(string $idAO, string $composant, bool $all = true, bool $accordConf = false): void
    {
        if ($composant == 'COMP_FOURNISS') {
            /** delete fournisseur **/
            $aoFour = new AoFour($this->pdo);
            $aoFour->delete(['NO_AO' => $idAO]);
        } elseif ($composant == 'COMP_LIGNE') {
            /** delete ligne **/
            $aoLigne = new AoLigne($this->pdo);
            $aoLigne->delete(['NO_AO' => $idAO]);
        } elseif ($composant == 'COMP_PJ') {
            /** delete PJ **/
            $aoPJ  = new AoPijo($this->pdo);
            $allPj = $aoPJ->fetchAll([], ['filter_egal_NO_AO' => $idAO]);
            $aoPJ->delete(['NO_AO' => $idAO]);

            foreach ($allPj as $pj) {
                unlink((new ParseBase1())->getRep()->pj . $pj['NOM_FIC']);
            }
        } elseif ($composant == 'COMP_DOC_ATT') {
            /** delete doc attendu **/
            $aoDocAttendu = new AoDocAttendus($this->pdo);
            $aoDocAttendu->delete(['NO_AO' => $idAO]);
        } elseif ($composant == 'COMP_DOC_INT') {
            /** delete doc interne + file + memo **/
            $docAtt   = new Docatt($this->pdo);
            $listeDoc = $docAtt->fetchAll([], ['filter_egal_NO_DA' => 'AO_ENTET', 'filter_egal_COD_ENR' => str_pad($idAO, 9, '0', STR_PAD_LEFT)]);

            foreach ($listeDoc as $doc) {
                $docAtt->delete([
                    'NO_DA' => 'AO_ENTET',
                    'COD_ENR' => str_pad($idAO, 9, '0', STR_PAD_LEFT)
                ]);
                if ($all || $doc['NO_ORDRE'] != $accordConf) {
                    unlink((new ParseBase1())->getRep()->pj . $doc['NOM_FIC']);
                    sql::deleteMemos($this->pdo, $doc['NM_COMM']);
                }
            }
        } elseif ($composant == 'COMP_CLAUSE') {
            /** delete clause + memo **/
            $aoClause    = new AoClaus($this->pdo);
            $listeClause = $aoClause->fetchAll([], ['filter_egal_NO_AO' => $idAO]);
            $aoClause->delete(['NO_AO' => $idAO]);
            // TODO : merge query
            foreach ($listeClause as $clause) {
                sql::deleteMemos($this->pdo, $clause['NM_PARAG']);
            }
        } elseif ($composant == 'COMP_QUEST') {
            /** delete Question (AO_QST_TH - AO_QST_R - AO_QST_Q) + memo **/
            $aoQstTh   = new AoQstTh($this->pdo);
            $themePere = $aoQstTh->fetchAll([], ['filter_egal_NO_AO' => $idAO, 'filter_egal_ID_PERE' => '']);

            $bibliotheque = new BibliothequeDeQuestions($this->pdo);
            foreach ($themePere as $theme) {
                if ($theme['ID_THEME'] != 'APRIX' || $all) {
                    $bibliotheque->deleteTheme('AO', $idAO, $theme['ID_THEME']);
                }
            }
        } elseif ($composant == 'AO_FOUR_QR') {
            //delete Q/r
            (new AoFourQR($this->pdo))->delete([
                'NO_AO' => (int) $idAO,
            ]);

            //delete document question
            $listedocQ = (new QuestionReponseRepo($this->pdo))->getAllDocumentAOQR($idAO);

            $ficPj = new Gestion_Fic_PJ($this->pdo);
            foreach ($listedocQ as $doc) {
                $ficPj->deleteFichier($doc['NOM_FIC']);
            }

            (new QuestionReponseRepo($this->pdo))->deleteAllDocumentAOQR($idAO);
        }
    }

    public function duplicateComposant(string $idAOOrigine, string $idNewAo, string $composant, bool $newAccord = false, string $societe = '', bool $dontDuplicateAccConf = false): void
    {
        $consultationRepo = new Consultation($this->pdo);
        if ($composant == 'COMP_FOURNISS') {
            $consultationRepo->duplicateFrsAO($idAOOrigine, $idNewAo);

            $consultationRepo = new Consultation($this->pdo);
            $listeAoFour      = $consultationRepo->getListeFrsAo($idNewAo);
            $aoFourRepo       = new AoFour($this->pdo);

            foreach ($listeAoFour as $frs) {
                if (Sql::boolSql($frs['GEREPORTAIL'])) {
                    $ctcFound = $consultationRepo->getOxalinkUser($frs['CODE_FOU'], $frs['EMAILCONT']);

                    if (!$ctcFound) {
                        $ctcUpdate = $consultationRepo->getOxalinkUser($frs['CODE_FOU']);

                        if ($ctcUpdate) {
                            $aoFourRepo->update([
                                'NOM_CTCT' => $ctcUpdate['NOM'],
                                'TEL_CTCT' => $ctcUpdate['TEL'],
                                'FAX_CTCT' => $ctcUpdate['FAX'],
                                'POR_CTCT' => $ctcUpdate['TELPORT'],
                                'EMAILCONT' => $ctcUpdate['EMAIL'],
                            ], ['NO_AO' => $idNewAo, 'CODE_FOU' => $frs['CODE_FOU']]);
                        }
                    }
                } else {
                    $ctcFound = $consultationRepo->getContactFrs($frs['CODE_FOU'], $frs['EMAILCONT']);

                    if (!$ctcFound) {
                        $ctcUpdate = $consultationRepo->getContactFrs($frs['CODE_FOU']);

                        if ($ctcUpdate) {
                            $aoFourRepo->update([
                                'NOM_CTCT' => $ctcUpdate['NOM'],
                                'TEL_CTCT' => $ctcUpdate['TEL'],
                                'FAX_CTCT' => $ctcUpdate['FAX'],
                                'POR_CTCT' => $ctcUpdate['TELPORT'],
                                'EMAILCONT' => $ctcUpdate['EMAIL'],
                            ], ['NO_AO' => $idNewAo, 'CODE_FOU' => $frs['CODE_FOU']]);
                        }
                    }
                }

                $AoContFour = new AoContFour($this->pdo);

                $allContactFour = $AoContFour->findAll(['NO_AO' => $idAOOrigine]);

                foreach ($allContactFour as $contactFour) {
                    $AoContFour->insert([
                        'NO_AO' => $idNewAo,
                        'CODE_FOUR' => $contactFour['CODE_FOUR'],
                        'TYPE_FG' => $contactFour['TYPE_FG'],
                        'NUM_ORDRE' => $contactFour['NUM_ORDRE'],
                        'NOM_CTCT' => $contactFour['NOM_CTCT'],
                        'TEL_CTCT' => $contactFour['TEL_CTCT'],
                        'FAX_CTCT' => $contactFour['FAX_CTCT'],
                        'POR_CTCT' => $contactFour['POR_CTCT'],
                        'EMAILCONT' => $contactFour['EMAILCONT']
                    ]);
                    $consultationService = new ConsultationService($this->pdo, $this->trad);
                    $consultationService->checkAoFourContactWithAoContFour((int) $idNewAo, $contactFour['CODE_FOUR'], $contactFour['TYPE_FG']);
                }
            }
        } elseif ($composant == 'COMP_LIGNE') {
            $aoLigne    = new AoLigne($this->pdo);
            $listeLigne = $aoLigne->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($listeLigne as $ligne) {
                $memoDesComp = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $ligne['NM_DCOMP']));
                $memoStAv    = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $ligne['NM_ST_AV']));

                if (!$societe) {
                    $societe = $ligne['CODE_STE'];
                }

                $aoLigne->insert([
                    'NO_AO' => $idNewAo,
                    'NO_PO' => $ligne['NO_PO'],
                    'NO_DA' => $ligne['NO_DA'],
                    'NO_PO_DA' => $ligne['NO_PO_DA'],
                    'CHIF_EXEC' => $ligne['CHIF_EXEC'] ?? '',
                    'CODE_ART' => $ligne['CODE_ART'] ?? '',
                    'DES' => $ligne['DES'] ?? '',
                    'QTE' => $ligne['QTE'] ?? '',
                    'DELAI' => $ligne['DELAI'] ?? '',
                    'UNITE' => $ligne['UNITE'] ?? '',
                    'NM_DCOMP' => $memoDesComp,
                    'BUDGET' => $ligne['BUDGET'] ?? '',
                    'CODE_STE' => $societe,
                    'SSFAMILLE' => $ligne['SSFAMILLE'] ?? '',
                    'NM_ST_AV' => $memoStAv,
                    'numerique_ST_APLIG' => Sql::setBoolSql(sql::boolSql($ligne['ST_APLIG'])),
                    'TITREST' => $ligne['TITREST'] ?? '',
                    'COD_FAB' => $ligne['COD_FAB'] ?? '',
                    'COD_GAM' => $ligne['COD_GAM'] ?? '',
                    'REF_FAB' => $ligne['REF_FAB'] ?? '',
                    'PRIX_REF' => $ligne['PRIX_REF'] ?? '',
                ]);
            }
        } elseif ($composant == 'COMP_PJ') {
            $aoPJ  = new AoPijo($this->pdo);
            $allPj = $aoPJ->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($allPj as $pj) {
                if (!empty($pj['NOM_FIC'])) {
                    $newFile = Fichier::copyFileFicPJ($pj['NOM_FIC']);
                }
                $aoPJ->insert([
                    'NO_AO' => $idNewAo,
                    'NO_ORDRE' => $pj['NO_ORDRE'],
                    'TYPE_PJ' => $pj['TYPE_PJ'],
                    'TITRE' => $pj['TITRE'],
                    'numerique_COPIE' => Sql::setBoolSql(sql::boolSql($pj['COPIE'])),
                    'numerique_LECTURE' => Sql::setBoolSql(sql::boolSql($pj['LECTURE'])),
                    'numerique_IMP_PJ' => Sql::setBoolSql(sql::boolSql($pj['IMP_PJ'])),
                    'numerique_IMP_TITRE' => Sql::setBoolSql(sql::boolSql($pj['IMP_TITRE'])),
                    'NOM_FIC' => $newFile['newPath'] ?? '',
                    'NOM_ORI' => $pj['NOM_ORI'],
                    'FIC_PDF' => $pj['FIC_PDF'],
                ]);
            }
        } elseif ($composant == 'COMP_DOC_ATT') {
            $aoDocAttendu = new AoDocAttendus($this->pdo);

            $listeDoc = $aoDocAttendu->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($listeDoc as $doc) {
                $aoDocAttendu->insert([
                    'NO_AO' => $idNewAo,
                    'NUM_ORDRE' => $doc['NUM_ORDRE'],
                    'CODE_DOC' => $doc['CODE_DOC'],
                    'TITRE_DOC' => $doc['TITRE_DOC'],
                    'COMMENTAIRE' => $doc['COMMENTAIRE'],
                    'numerique_OBLIGATOIRE' => Sql::setBoolSql(sql::boolSql($doc['OBLIGATOIRE'])),
                ]);
            }
        } elseif ($composant == 'COMP_DOC_INT') {
            $aoEntet     = new AoEntet($this->pdo);
            $infoConsult = $aoEntet->find($idAOOrigine);

            $docAtt   = new Docatt($this->pdo);
            $listeDoc = $docAtt->fetchAll([], ['filter_egal_NO_DA' => 'AO_ENTET', 'filter_egal_COD_ENR' => str_pad($idAOOrigine, 9, "0", STR_PAD_LEFT)]);

            foreach ($listeDoc as $doc) {
                if ($infoConsult['ACC_CONF_NODOC'] == $doc['NO_ORDRE'] && $newAccord) {
                } elseif (!$newAccord && $dontDuplicateAccConf) {
                } else {
                    $idMemo = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $doc['NM_COMM']));

                    $newFile = Fichier::copyFileFicPJ($doc['NOM_FIC']);

                    $docAtt->insert([
                        'NO_DA' => $doc['NO_DA'],
                        'NO_ORDRE' => $doc['NO_ORDRE'],
                        'TYPE_PJ' => $doc['TYPE_PJ'],
                        'TITRE' => $doc['TITRE'],
                        'numerique_COPIE' => sql::setBoolSql(sql::boolSql($doc['COPIE'])),
                        'NOM_FIC' => $newFile['newPath'],
                        'DT_PARUT' => $doc['DT_PARUT'],
                        'DT_VALID' => $doc['DT_VALID'],
                        'COD_ENR' => str_pad($idNewAo, 9, '0', STR_PAD_LEFT),
                        'AUTEUR' => $doc['AUTEUR'],
                        'CENTRE' => $doc['CENTRE'],
                        'NM_COMM' => $idMemo,
                        'NOM_ORI' => $doc['NOM_ORI'],
                        'numerique_FI_TECH' => sql::setBoolSql(sql::boolSql($doc['FI_TECH'])),
                        'CODE_FOU' => $doc['CODE_FOU'],
                        'numerique_NPRELANCE' => sql::setBoolSql(sql::boolSql($doc['NPRELANCE'])),
                        'numerique_PJ_CDE' => sql::setBoolSql(sql::boolSql($doc['PJ_CDE'])),
                        'numerique_GERE_PAR_PARTENAIRE' => sql::setBoolSql(sql::boolSql($doc['GERE_PAR_PARTENAIRE'])),
                        'numerique_DOC_INUTILE' => sql::setBoolSql(sql::boolSql($doc['DOC_INUTILE'])),
                        'CODE_CAT' => $doc['CODE_CAT'],
                        'DTE_DERNREL' => $doc['DTE_DERNREL'],
                        'numerique_CONTRATCDE' => sql::setBoolSql(sql::boolSql($doc['CONTRATCDE'])),
                    ]);

                    if ($infoConsult['ACC_CONF_NODOC'] == $doc['NO_ORDRE']) {
                        $aoEntetEntity = new AoEntet($this->pdo);
                        $aoEntetEntity->update(['ACC_CONF_NODOC' => $doc['NO_ORDRE']], $idNewAo);
                    }
                }
            }
        } elseif ($composant == 'COMP_CLAUSE') {
            $aoClause    = new AoClaus($this->pdo);
            $listeClause = $aoClause->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($listeClause as $clause) {
                $idMemos = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $clause['NM_PARAG']));

                $aoClause->insert([
                    'NO_AO' => $idNewAo,
                    'NO_ORDRE' => $clause['NO_ORDRE'],
                    'NM_PARAG' => $idMemos,
                ]);
            }
        } elseif ($composant == 'COMP_QUEST') {
            $aoQstTh   = new AoQstTh($this->pdo);
            $themePere = $aoQstTh->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($themePere as $theme) {
                $idMemo = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $theme['NM_COM']));

                $aoQstTh->insert([
                    'NO_AO' => $idNewAo,
                    'ID_THEME' => $theme['ID_THEME'],
                    'ID_PERE' => $theme['ID_PERE'],
                    'LIB_THEME' => $theme['LIB_THEME'],
                    'NM_COM' => $idMemo,
                    'NM_ORDRE' => $theme['NM_ORDRE'],
                    'POIDS' => $theme['POIDS'],
                    'THEME_LIE' => $theme['THEME_LIE'],
                ]);
            }
            $aoQstQ        = new AoQstQ($this->pdo);
            $listeQuestion = $aoQstQ->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($listeQuestion as $question) {
                $idMemo = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $question['NM_COM']));
                $idMemo = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $question['NM_COM']));

                $aoQstQ->insert([
                    'NO_AO' => $idNewAo,
                    'ID_THEME' => $question['ID_THEME'],
                    'ID_QUEST' => $question['ID_QUEST'],
                    'G_B_QST_LIE' => $question['G_B_QST_LIE'],
                    'LIB_QUEST' => $question['LIB_QUEST'],
                    'NM_COM' => $idMemo,
                    // @phpstan-ignore-next-line TODO MSA regarder le $ligne['QUEST_FOUR']
                    'numerique_QUEST_FOUR' => Sql::setBoolSql(sql::boolSql($question['QUEST_FOUR'] ?? false)),
                    'TYPE_REP' => $question['TYPE_REP'],
                    'NOTE_FAUX' => $question['NOTE_FAUX'],
                    'NOTE_VRAI' => $question['NOTE_VRAI'],
                    'NUM_FORMAT' => $question['NUM_FORMAT'],
                    'NUM_MIN' => $question['NUM_MIN'],
                    'NUM_MAX' => $question['NUM_MAX'],
                    'POIDS' => $question['POIDS'],
                    'NM_ORDRE' => $question['NM_ORDRE'],
                    'ID_MODEL' => $question['ID_MODEL'],
                ]);
            }

            $aoQstR       = new AoQstR($this->pdo);
            $listeReponse = $aoQstR->fetchAll([], ['filter_egal_NO_AO' => $idAOOrigine]);

            foreach ($listeReponse as $reponse) {
                $idMemo = sql::updateMemo($this->pdo, '', sql::getMemo($this->pdo, $reponse['NM_COM']));

                $aoQstR->insert([
                    'NO_AO' => $idNewAo,
                    'ID_THEME' => $reponse['ID_THEME'],
                    'ID_QUEST' => $reponse['ID_QUEST'],
                    'ID_REP' => $reponse['ID_REP'],
                    'TXT_REP' => $reponse['TXT_REP'],
                    'NM_COM' => $idMemo,
                    // @phpstan-ignore-next-line TODO MSA regarder le $ligne['COM_MANUEL']
                    'numerique_COM_MANUEL' => Sql::setBoolSql(sql::boolSql($reponse['COM_MANUEL'] ?? false)),
                    'NOTE' => $reponse['NOTE'],
                ]);
            }
        } elseif ($composant == 'COMP_CONTRIB') {
            $aoContrib    = new AoContrib($this->pdo);
            $aoGrpContrib = new AoGrpContrib($this->pdo);
            $aoContribGrp = new AoContribGrp($this->pdo);

            $contributors = $aoContrib->findAll(['NO_AO' => $idAOOrigine]);
            foreach ($contributors as $contributor) {
                $contributor['NO_AO'] = $idNewAo;
                $aoContrib->insert($contributor);
            }

            $groups = $aoGrpContrib->findAll(['NO_AO' => $idAOOrigine]);
            foreach ($groups as $group) {
                $group['NO_AO'] = $idNewAo;
                $aoGrpContrib->insert($group);
            }

            $groupsContrib = $aoContribGrp->findAll(['NO_AO' => $idAOOrigine]);
            foreach ($groupsContrib as $groupContrib) {
                $groupContrib['NO_AO'] = $idNewAo;
                $aoContribGrp->insert($groupContrib);
            }
        }
    }

    public function validateConsultation(string $idAO): void
    {
        $aoQstQ = new AoQstQ($this->pdo);
        $aoQstQ->update(['G_B_QST_LIE' => ''], ['NO_AO' => $idAO]);

        $aoQstTh = new AoQstTh($this->pdo);
        $aoQstTh->update(['THEME_LIE' => ''], ['NO_AO' => $idAO]);

        $AoEntet      = new AoEntet($this->pdo);
        $consultation = $AoEntet->find($idAO);
        $acheteur     = (new Hastutil($this->pdo))->find($consultation['ACH']);

        $aoEvent = new AoEvent($this->pdo);

        // vérification de l'existence d'un questionnaire pour contributeur
        $contribQuestions           = (new Reponse($this->pdo))->getContributorsQuestions($idAO);
        $existsContribQuestionnaire = count($contribQuestions) > 0;

        // si le questionnaire contributeur existe, on crée les réponses vides dans AO_REP_QST
        if ($existsContribQuestionnaire) {
            $destinataires    = '';
            $contributorsList = (new Contributor($this->pdo))->getAllRfxContributors($idAO);
            foreach ($contributorsList as $contributor) {
                if (empty($contributor['EMAIL'])) {
                    continue;
                }
                // TODO: A deleyer si pas à la date ni heure de lancement
                Mail::generateMail(
                    $this->pdo,
                    $this->trad,
                    $contributor['EMAIL'],
                    'AO_CONTRIB_MAIL',
                    $contributor['COD_LNG'],
                    [
                        'NO_AO' => $idAO,
                        'NOM_CONTRIB' => $contributor['NOM'],
                        'DTE_DEBUT_NOTATION' => Date::dateConverte($consultation['DEL_REP']),
                        'DTE_FIN_NOTATION' => Date::dateConverte($consultation['DTE_LIMIT_CONTRIB']),
                        'NOM_ACH' => $acheteur['NOM'],
                    ],
                );
                if ($destinataires != '') {
                    $destinataires .= ', ';
                }
                $destinataires .= $contributor['NOM'] . ' (' . $contributor['CONTRIB'] . ')';
            }

            $aoEvent->rqInsertEventAO(
                $idAO,
                'CTB',
                Trad::strBuild($this->trad->t('Alerte des contributeurs de la consultation : @1@'), $destinataires),
                '',
                ''
            );
        }

        // TODO: A deleyer si pas à la date ni heure de lancement
        if (Sql::toBool($consultation['ENVOI_EMAIL_AUTO_FRS'] ?? '')) {
            if ($consultation['DTE_LANCEMENT'] . $consultation['HEURE_LANCEMENT'] <= date('YmdHis')) {
                $infoMail    = [
                    'NAO' => $idAO,
                    'TITREAO' => sql::getMemo($this->pdo, $consultation['NM_TITRE']),
                    'RS_SOC' => Outils::convertLibelleGlobal($this->pdo, $consultation['TYPE_SG'] == 'S' ? 'Societe' : 'GrpSociete', '', $consultation['CODE_STE']),
                    'OBJETAO' => $consultation['OBJET_AO'],
                    'NOM_ACH' => $acheteur['NOM'],
                    'DTE_VALID_AO' => Date::dateConverte($consultation['DTE_VALID_AO']),
                    'DTE_LANCEMENT' => Date::dateConverte($consultation['DTE_LANCEMENT']),
                    'URL' => Sql::paravrac($this->pdo, 'PF_OXALINK', 'URLACCESOXALINK'),
                    'DATEREPAO' => Date::dateConverte($consultation['DEL_REP']),
                    'NOMACH' => $acheteur['NOM'],
                ];
                $consultRepo = new Consultation($this->pdo);
    
                $listeOxalink    = [];
                $listeNonOxalink = [];
    
                $allCtcts = $consultRepo->getAllCtcWithCheckIfOxalinkAccess($idAO);
    
                foreach ($allCtcts as $currentCtct) {
                    if ($currentCtct['fourHasContactWithOxalinkAccess']) {
                        $listeOxalink[] = $currentCtct;
                    } else {
                        $listeNonOxalink[] = $currentCtct;
                    }
                }
    
                foreach ($listeOxalink as $ctct) {
                    if (Sql::boolSql($consultation['ACC_CONF']) == true) {
                        Mail::generateMail(
                            $this->pdo,
                            $this->trad,
                            $ctct['EMAILCONT'],
                            'EXT_FOU_ACCCONF_LINK',
                            $ctct['COD_LNG'],
                            $infoMail,
                            [],
                        );
                    } else {
                        $infoMail['NOM_ACH'] = $infoMail['NOMACH'];
                        Mail::generateMail(
                            $this->pdo,
                            $this->trad,
                            $ctct['EMAILCONT'],
                            'EXT_FOU_INFOAO_LINK',
                            $ctct['COD_LNG'],
                            $infoMail,
                            [],
                        );
                    }
    
                    $message = Sql::boolSql($consultation['ACC_CONF']) == true
                        ? 'Demande de signature de l\'accord de confidentialité'
                        : '';
                    $aoEvent->rqInsertEventAO($idAO, 'ENV', $message, $ctct['CODE_FOUR'], $ctct['TYPE_FG']);
                }
    
                $docAtt = new Docatt($this->pdo);
                $idDoc  = str_pad($idAO, 9, '0', STR_PAD_LEFT);
    
                $infoDoc   = $docAtt->find(['NO_DA' => 'AO_ENTET', 'COD_ENR' => $idDoc, 'NO_ORDRE' => $consultation['ACC_CONF_NODOC']]);
                $path_info = pathinfo($infoDoc['NOM_FIC']);
    
                if (Sql::boolSql($consultation['ACC_CONF']) == true) {
                    foreach ($listeNonOxalink as $ctctNonOxalink) {
                        $new_name = 'Consult_' . $idAO . '_' . $ctctNonOxalink['CODE_FOUR']
                            . '_' . str_replace('t| ', '', $this->trad->t('Accord de Confidentialité'))
                            . '.' . ($path_info['extension'] ?? '');
    
                        $oldFic = (new ParseBase1())->getRep()->pj . $infoDoc['NOM_FIC'];
                        $newFic = (new ParseBase1())->getRep()->tmp . $new_name;
    
                        copy($oldFic, $newFic);
    
                        $ctctNonOxalink['pj']       = $new_name;
                        $ctctNonOxalink['sourcePJ'] = $newFic;
    
                        Mail::generateMail(
                            $this->pdo,
                            $this->trad,
                            $ctctNonOxalink['EMAILCONT'],
                            'AO_FOU_ACCORD_CONF',
                            $ctctNonOxalink['COD_LNG'],
                            $infoMail,
                            [],
                            [$ctctNonOxalink['sourcePJ']]
                        );
    
                        $aoEvent->rqInsertEventAO($idAO, 'ENV', 'Demande de signature de l\'accord de confidentialité', $ctctNonOxalink['CODE_FOUR'], $ctctNonOxalink['TYPE_FG']);
                    }
                } else {
                    $AoExcFofo = new AoExcFofo($this->pdo);
    
                    $listeFrs = [];
                    foreach ($listeNonOxalink as $ctctNonOxalink) {
                        if (!isset($listeFrs[$ctctNonOxalink['CODE_FOUR']])) {
                            $listeFrs[$ctctNonOxalink['CODE_FOUR']] = [
                                'CODE_FOU' => $ctctNonOxalink['CODE_FOUR'],
                                'TYPE_FG' => $ctctNonOxalink['TYPE_FG'],
                                'parMail' => 'true',
                                'emails' => $ctctNonOxalink['EMAILCONT']
                            ];
    
                            // TODO : merge queries
                            $paramExcelByfrs  = $AoExcFofo->find([
                                'SOCIETE' => $consultation['CODE_STE'],
                                'CTRE' => $consultation['EMETTEUR'],
                                'CODE_FOU' => $ctctNonOxalink['CODE_FOUR']
                            ]);
                            $paramExcelDefaut = $AoExcFofo->getForm($consultation);
    
                            if ($paramExcelByfrs) {
                                $listeFrs[$ctctNonOxalink['CODE_FOUR']]['typeFormatExcel'] = $paramExcelByfrs['CODEFORM'] ?? '';
                                $listeFrs[$ctctNonOxalink['CODE_FOUR']]['versionFormat']   = $paramExcelByfrs['VERSFORM'] ?? '';
                            } else {
                                $listeFrs[$ctctNonOxalink['CODE_FOUR']]['typeFormatExcel'] = $paramExcelDefaut['CODEFORM'] ?? '';
                                $listeFrs[$ctctNonOxalink['CODE_FOUR']]['versionFormat']   = $paramExcelDefaut['VERSFORM'] ?? '';
                            }
                        } else {
                            $listeFrs[$ctctNonOxalink['CODE_FOUR']]['emails'] .= ',' . $ctctNonOxalink['EMAILCONT'];
                        }
                    }
    
                    $envoieExcelService = new EnvoieExcelService($this->pdo, $this->trad, $this->router);
    
                    foreach ($listeFrs as $key => &$frs) {
                        if ($frs['typeFormatExcel'] !== '' && $frs['versionFormat'] !== '') {
                            $envoieExcelService->generationEnvoieExcel(
                                $idAO,
                                $frs,
                                $consultation,
                                $acheteur
                            );
                            unset($listeFrs[$key]);
                        }
                    }
    
                    $consultWsdl = new \Modules\Consultation\WebService\Consultation();
                    $xmlResult   = $consultWsdl->sendConsultation($idAO, "P", $listeFrs);
                    $reponse     = new \SimpleXMLElement($xmlResult->responseData);
                }
            } else {
                (new Scheduler(new TploOperations($this->pdo)))->create(
                    'Consultation.Mail.envoieMailFournisseur',
                    ['idAO' => $idAO],
                    $consultation['DTE_LANCEMENT'],
                    $consultation['HEURE_LANCEMENT']
                );

                (new Scheduler(new TploOperations($this->pdo)))->create(
                    'Consultation.Mail.envoieMailContrib',
                    ['idAO' => $idAO],
                    $consultation['DEL_REP'],
                    $consultation['HEURE_LANCEMENT']
                );
            }
        }

        $aoEvent = new AoEvent($this->pdo);
        $aoEvent->rqInsertEventAO($idAO, 'VAL');

        $noEvent = $aoEvent->getLastOrder($idAO, 'VAL')['MAX_NUM_ORDRE'];

        $AoEntet->update([
            'DTE_VALID_AO' => date('Ymd'),
            'EVE_VALPREP' => $noEvent,
        ], $idAO);

        //___________________________________
        // Post processes

        // Send notif to Demandeur
        $trad = $this->trad;
        $listMailInfo = (new GestionConsultation($this->pdo))->getInfoMailEnvoieInfoToDem($idAO);
        foreach (array_column($listMailInfo, null, 'Demandeur_EMAIL') as $infoMail) {
            Mail::generateMail(
                $this->pdo,
                $trad,
                $infoMail['Demandeur_EMAIL'],
                'AO_CREAT_FOR_DEM',
                $infoMail['Demandeur_COD_LNG'],
                [
                    'NAO' => $infoMail['NO_AO'],
                    'NDA' => $infoMail['NO_DA'],
                    'NOM_ACH' => $infoMail['Acheteur_CODE'],
                    'CODE_ACH' => $infoMail['Acheteur_NOM'],
                ]
            );
        }

        $aoEvent = new AoEvent($this->pdo);
        $aoEvent->rqInsertEventAO($idAO, 'VAL');

        $noEvent = $aoEvent->getLastOrder($idAO, 'VAL')['MAX_NUM_ORDRE'];

        $AoEntet->update([
            'DTE_VALID_AO' => date('Ymd'),
            'EVE_VALPREP' => $noEvent,
        ], $idAO);
    }

    /**
     * @return array
     *      arrayRepFrs : Liste des dernières réponse par Frs
     *      arrayCompare : Liste du prix le plus bas pour chaque ligne
     *      arraySelected : Liste des frs selectionné pour chaque ligne (si AO_REP vide, on met le plus bras par défaut)
     *      totalFrs : Cumul des lignes frs
     *      totalSelected : Cumul des lignes selectionné frs
     */
    public function calculeChoixFrs(string $idAO, &$listeFrs): array
    {
        $aoDocAttendu    = new AoDocAttendus($this->pdo);
        $docAttenduActif = $aoDocAttendu->find(['NO_AO' => $idAO, 'OBLIGATOIRE' => 'T']);

        $reponseRepo       = new Reponse($this->pdo);
        $gestionConsu      = new GestionConsultation($this->pdo);
        $ligneConsultation = $gestionConsu->listeLigneConsultation($idAO);

        $arrayRepFrs   = [];
        $totalFrs      = [];
        $totalSelected = [];
        $arrayCompare  = [];
        $arraySelected = [];

        $aoRepSl = new AoRepSl($this->pdo);

        //On boucle sur tout les fournisseurs
        foreach ($listeFrs as &$frs) {
            //init du calcule par fournisseur
            $totalFrs[$frs['CODE_FOU']]      = 0;
            $totalSelected[$frs['CODE_FOU']] = 0;
            //On boucle sur toute les lignes de consultation (par fournisseur)
            foreach ($ligneConsultation as $ligne) {
                $infoRep = $reponseRepo->getInfoRep($idAO, $frs['CODE_FOU'], $frs['TYPE_FG'], $ligne['NO_PO']);

                $listePJ = null;

                if ($infoRep) {
                    $listeRepSl = $aoRepSl->findAll([
                        'NO_AO' => $idAO,
                        'NO_PO_AO' => $ligne['NO_PO'],
                        'DTE_REP' => $infoRep['DTE_REP'],
                        'CODE_FOU' => $infoRep['CODE_FOU'],
                        'TYPE_FG' => $infoRep['TYPE_FG'],
                        'C_V' => $infoRep['C_V'],
                    ]);

                    $totalSousLigne = 0;

                    if ($listeRepSl) {
                        foreach ($listeRepSl as $row) {
                            $totalSousLigne += (float) $row['QTE_PROP'] * (float) $row['PU'];
                        }

                        $infoRep['TOTAL_REPSL'] = $totalSousLigne;
                    }

                    $note = $reponseRepo->getNoteFrs($idAO, $frs['CODE_FOU'], $frs['TYPE_FG'], $infoRep['C_V'], $infoRep['DTE_REP']);

                    $frs['NOTE'] = $note[0];

                    $frs['DTE_REP'] = $infoRep['DTE_REP'];

                    if ($docAttenduActif) {
                        $listePJ = $reponseRepo->getListDocAtt($idAO, $frs['TYPE_FG'], $frs['CODE_FOU'], $infoRep['C_V'], $infoRep['DTE_REP'], true);
                    }

                    $frs['C_V']        = $infoRep['C_V'];
                    $frs['docAbsent']  = $listePJ ? true : false;
                    $frs['repDepasse'] = $infoRep['DTELIMIT'] < date('Ymd');

                    $arrayRepFrs[$frs['CODE_FOU']][$ligne['NO_PO']] = $infoRep;
                    $totalFrs[$frs['CODE_FOU']] += ((float) $infoRep['QTE'] * (float) $infoRep['PU']);

                    //Genere le tableau des prix les plus bas (afin de mettre la case en vert dans la vue)
                    if (isset($arrayCompare[$ligne['NO_PO']])) {
                        if ((float) $infoRep['PU'] == 0) {
                            if ((float) $totalSousLigne && (float) $arrayCompare[$ligne['NO_PO']]['savePU'] > (float) $totalSousLigne) {
                                $arrayCompare[$ligne['NO_PO']] = [
                                    'CODE_FOU' => $frs['CODE_FOU'],
                                    'TYPE_FG' => $frs['TYPE_FG'],
                                    'C_V' => $infoRep['C_V'],
                                    'saveQTE' => $infoRep['QTE'],
                                    'savePU' => $totalSousLigne
                                ];
                            }
                        } else {
                            if (((float) $arrayCompare[$ligne['NO_PO']]['savePU'] > (float) $infoRep['PU'])) {
                                $arrayCompare[$ligne['NO_PO']] = [
                                    'CODE_FOU' => $frs['CODE_FOU'],
                                    'TYPE_FG' => $frs['TYPE_FG'],
                                    'C_V' => $infoRep['C_V'],
                                    'saveQTE' => $infoRep['QTE'],
                                    'savePU' => $infoRep['PU']
                                ];
                            }
                        }
                    } elseif ((float) $infoRep['PU'] != 0) {
                        $arrayCompare[$ligne['NO_PO']] = [
                            'CODE_FOU' => $frs['CODE_FOU'],
                            'TYPE_FG' => $frs['TYPE_FG'],
                            'C_V' => $infoRep['C_V'],
                            'saveQTE' => $infoRep['QTE'],
                            'savePU' => $infoRep['PU']
                        ];
                    } elseif ($totalSousLigne != 0) {
                        $arrayCompare[$ligne['NO_PO']] = [
                            'CODE_FOU' => $frs['CODE_FOU'],
                            'TYPE_FG' => $frs['TYPE_FG'],
                            'C_V' => $infoRep['C_V'],
                            'saveQTE' => $infoRep['QTE'],
                            'savePU' => $totalSousLigne
                        ];
                    }


                    //Genere table de fournisseur au prix le plus bas si aucun fournisseur n'a été séléctionné pour cette ligne
                    if ($infoRep['CODE_FOU'] == '') {
                        $arraySelected[$ligne['NO_PO']] = $arrayCompare[$ligne['NO_PO']] ?? [];
                    } else {
                        if ($infoRep['CODE_FOU'] == $frs['CODE_FOU']) {
                            $arraySelected[$ligne['NO_PO']] = [
                                'CODE_FOU' => $frs['CODE_FOU'],
                                'TYPE_FG' => $frs['TYPE_FG'],
                                'C_V' => $infoRep['C_V'],
                                'saveQTE' => $infoRep['QTE'],
                                'savePU' => $infoRep['PU']
                            ];
                        }
                    }
                }
            }
        }

        //On insère la ligne par defaut si elle n'existe pas déjà
        $aoRetParLigne = new AoRetParLigne($this->pdo);
        /** @var array<mixed> $selected */
        foreach ($arraySelected as $key => $selected) {
            if (($selected['CODE_FOU'] ?? false) == '') {
                continue;
            }
            $checkLigne = $aoRetParLigne->find([
                'NO_AO' => $idAO,
                'NO_PO' => $key,
                'CODE_FOU' => $selected['CODE_FOU'],
                'TYPE_FG' => $selected['TYPE_FG'],
                'RET_CV' => $selected['C_V']
            ]);

            if (!$checkLigne) {
                $aoRetParLigne->insert([
                    'NO_AO' => $idAO,
                    'NO_PO' => $key,
                    'CODE_FOU' => $selected['CODE_FOU'],
                    'TYPE_FG' => $selected['TYPE_FG'],
                    'RET_CV' => $selected['C_V']
                ]);
            }

            $totalSelected[$selected['CODE_FOU']] += ((float) $selected['saveQTE'] * (float) $selected['savePU']);
        }

        $returnArray = [];

        $returnArray = [
            'arrayRepFrs' => $arrayRepFrs,
            'totalFrs' => $totalFrs,
            'totalSelected' => $totalSelected,
            'arrayCompare' => $arrayCompare,
            'arraySelected' => $arraySelected,
        ];

        return $returnArray;
    }

    /**
     * Summary of addFourniss
     * @param string $idAO
     * @param string $typFG
     * @param string $codeFou
     * @param string $idRecord
     * @return bool|array<mixed>
     */
    public function addFourniss(string $idAO, string $typFG, string $codeFou, ?string $idRecord = null)
    {
        $aoEntet   = new AoEntet($this->pdo);
        $infoEntet = $aoEntet->find($idAO);
        if ($infoEntet && $infoEntet['VALCHXFOU'] != '00000000') {
            return false;
        }

        $gestionConsu = new GestionConsultation($this->pdo);
        $reponse      = new Reponse($this->pdo);
        $aoFourEntity = new AoFour($this->pdo);
        $aoContFour   = new AoContFour($this->pdo);

        if ($typFG == 'F') {
            $frs        = $gestionConsu->getInfoFrs($codeFou);
            $contactfrs = $gestionConsu->getContactFrs($codeFou);
        } else {
            $frs        = $gestionConsu->getInfoGrpFrs($codeFou);
            $contactfrs = $gestionConsu->getContactGrpFrs($codeFou);
        }

        $frsExist = $aoFourEntity->find([
            'NO_AO' => $idAO,
            'TYPE_FG' => $typFG,
            'CODE_FOU' => $frs['CODE'] ?? '',
        ]);

        if ($frsExist) {
            return true;
        }

        $noCol = $reponse->getMaxCol($idAO);

        $aoFourEntity->insert([
            'NO_AO' => $idAO,
            'CODE_FOU' => $frs['CODE'] ?? '',
            'NOM_CTCT' => '',
            'TEL_CTCT' => '',
            'FAX_CTCT' => '',
            'POR_CTCT' => '',
            'EMAILCONT' => '',
            'ADR' => $frs['ADR'] ?? '',
            'VILLE' => $frs['VILLE'] ?? '',
            'PAYS' => $frs['CODE_PAYS'] ?? '',
            'CPOSTAL' => $frs['CPOSTAL'] ?? '',
            'VILLE1' => $frs['VILLE1'] ?? '',
            'RET_CV' => 'C',
            'TYPE_FG' => $typFG,
            'NO_COL' => ((int) ($noCol['MAX_NO_COL'] ?? '0')) + 1
        ]);

        $aoEvent = new AoEvent($this->pdo);
        $aoEvent->rqInsertEventAO($idAO, 'AJF', '', $frs['CODE'], $typFG);

        $anchor = '<a href="' . $this->router->generateUri('Consultation.AjoutFournisseur.editFournisseur', ['idAO' => $idAO, 'idFrs' => ($frs['CODE'] ?? ''), 'typeFG' => $typFG, 'changeContact' => 1]) . '"> ' . ($frs['RS'] ?? '') . ' (' . ($frs['CODE'] ?? '') . ')</a>';

        if ($typFG == 'F') {
            $actionService = new ActionService($this->pdo);
            $actionService->insertInfoConsultToProject($codeFou, (int) $idAO, (int) $idRecord);
        }

        $countContact = count($contactfrs);
        if ($countContact == 0) {
            return ['error' => $this->trad->t('Aucun contact n\'est présent sur la fiche du fournisseur') . ' ' . $anchor . '.'];
        }

        $contactInserted = 0;
        if ($countContact == 1) {
            if (trim($contactfrs[0]['EMAIL']) != '') {
                $aoContFour->insert([
                    'NO_AO' => $idAO,
                    'CODE_FOUR' => $frs['CODE'],
                    'TYPE_FG' => $typFG,
                    'NOM_CTCT' => $contactfrs[0]['NOM'] ?? '',
                    'TEL_CTCT' => $contactfrs[0]['TEL'] ?? '',
                    'FAX_CTCT' => $contactfrs[0]['FAX'] ?? '',
                    'POR_CTCT' => $contactfrs[0]['TELPORT'] ?? '',
                    'EMAILCONT' => $contactfrs[0]['EMAIL'],
                    'NUM_ORDRE' => 1
                ]);
                $contactInserted++;
            } else {
                return ['error' => $this->trad->t('Aucun contact avec un email n\'est présent sur la fiche du fournisseur') . ' ' . $anchor . '.'];
            }
        }

        if ($countContact > 1 && $contactInserted == 0) {
            foreach ($contactfrs as $contact) {
                if (Sql::toBool($contact['CTC_CONSULT'] ?? '')) {
                    $aoContFour->insert([
                        'NO_AO' => $idAO,
                        'CODE_FOUR' => $frs['CODE'] ?? '',
                        'TYPE_FG' => $typFG,
                        'NOM_CTCT' => $contact['NOM'] ?? '',
                        'TEL_CTCT' => $contact['TEL'] ?? '',
                        'FAX_CTCT' => $contact['FAX'] ?? '',
                        'POR_CTCT' => $contact['TELPORT'] ?? '',
                        'EMAILCONT' => $contact['EMAIL'] ?? '',
                        'NUM_ORDRE' => intval($aoContFour->getMaxNumOrdre($idAO, $frs['CODE'], $typFG)) + 1
                    ]);
                    $contactInserted++;
                }
            }
        }

        $consultationService = new ConsultationService($this->pdo, $this->trad);
        $consultationService->checkAoFourContactWithAoContFour((int) $idAO, $codeFou, $typFG);

        if ($contactInserted == 0) {
            return ['error' => $this->trad->t('Aucun contact n\'est affecté en tant que Contact Consultation sur la fiche du fournisseur') . ' ' . $anchor . '.'];
        }

        return true;
    }

    /**
     * @param array<mixed> $article
     */
    public function addArticleToConsult(string $idConsult, $article, bool $articleGenerique = false): void
    {
        $aoEntet   = new AoEntet($this->pdo);
        $infoEntet = $aoEntet->find($idConsult);

        $gestionConsultation = new GestionConsultation($this->pdo);
        $idLigne             = (int) $gestionConsultation->getMaxLigneAo($idConsult)['MAX_PO'];
        $idLigne             = $idLigne + 1;

        if ($articleGenerique) {
            $prix = '0';
        } else {
            $prix = $article['PX_ART'];
        }

        $aoLigne = new AoLigne($this->pdo);
        $aoLigne->insert([
            'NO_AO' => $idConsult,
            'NO_PO' => $idLigne,
            'NO_DA' => 0,
            'NO_PO_DA' => 0,
            'CODE_ART' => $article['COD_ART'],
            'DES' => $article['DES_ART'],
            'NM_DCOMP' => Sql::updateMemo($this->pdo, '', $article['DES_ART']),
            'QTE' => 1,
            'UNITE' => $article['COD_UNIT'],
            'DELAI' => '00000000',
            'BUDGET' => 0,
            'PRIX_REF' => $prix,
            'SSFAMILLE' => $article['COD_SFAM'],
            'COD_FAB' => $article['COD_FAB'],
            'COD_GAM' => $article['COD_GAM'],
            'REF_FAB' => $article['COD_FAB'] ?? '',
            'CODE_STE' => $infoEntet['CODE_STE'],
        ]);

        $aoPlann = new AoPlann($this->pdo);
        $aoPlann->insert([
            'NO_AO' => $idConsult,
            'NO_PO' => $idLigne,
            'DTE' => '00000000',
            'QTE' => 0,
        ]);

        $champSupp = new ChampSupp($this->pdo);
        $listeCS   = $champSupp->getInfoCS('AO_LIGNE');

        foreach ($listeCS as $cs) {
            $valueCS = '';
            if ($cs['TAB_SOUR'] == 'ARTICLES' && $article['COD_ART'] != '') {
                $idCS    = $article['COD_ART'];
                $valueCS = ChampSupp::getValueCS($cs['TAB_SOUR'], $idCS, $cs['CHP_SOUR'], $this->pdo);
            } elseif ($cs['TAB_SOUR'] == 'AO_ENTET') {
                $idCS    = $champSupp::autoCompletCodeEnr($idConsult, '', 'AO_ENTETE');
                $valueCS = ChampSupp::getValueCS($cs['TAB_SOUR'], $idCS, $cs['CHP_SOUR'], $this->pdo);
            }

            $idCSLigne = $champSupp::autoCompletCodeEnr($idConsult, $idLigne, 'AO_LIGNE');
            $champSupp->insertChampSupp('AO_LIGNE', $idCSLigne, $cs['NUM_FIX'], $valueCS, $this->pdo);
        }
    }

    /**
     * @param array<mixed> $infoEntet
     * @param array<mixed> $article
     */
    public function getPrixRef($infoEntet, $article): string
    {
        $consultation = new Consultation($this->pdo);
        $prixRef      = 0;

        if ($article['REF_FAB'] != '' && $article['COD_FAB'] != '') {
            $prixRef = $consultation->getPrixRef($infoEntet['TYPE_SG'], $infoEntet['CODE_STE'], true, $article);
        }

        if (!$prixRef) {
            $prixRef = $consultation->getPrixRef($infoEntet['TYPE_SG'], $infoEntet['CODE_STE'], false, $article);
        }

        return $prixRef;
    }

    /**
     * Summary of createDefaultDocumentsReponses
     * @param string $idAo
     * @param string $codeLangue
     * @param TypeConsultationsEnums $RFI_Q
     * @return void
     */
    public function createDefaultDocumentsReponses(string $idAo, string $codeLangue, TypeConsultationsEnums $RFI_Q): void
    {
        $ConsultDocDefaut = new ConsultDocDefault($this->pdo);

        $listeDocRep = $ConsultDocDefaut->findAll(
            ['TYPE_DOC' => 'A', 'COD_LNG ' => $codeLangue, "POUR_" . $RFI_Q->name => 'T'],
            [],
            ['tri_NUM_ORDRE' => 'ASC']
        );

        $aoDocAttendu = new AoDocAttendus($this->pdo);

        foreach ($listeDocRep as $doc) {
            $aoDocAttendu->merge([
                'NO_AO' => $idAo,
                'NUM_ORDRE' => $doc['NUM_ORDRE'],
                'CODE_DOC' => "",
                'TITRE_DOC' => $doc['TITRE_DOC'],
                'COMMENTAIRE' => "",
                'OBLIGATOIRE' => Sql::setBoolSqlText($doc[$RFI_Q->name . "_OBLIG"]),
            ]);
        }
    }

    /**
     * Permet d'obtenir les paramètres par défault de pour les champs
     * défini par l'admin
     * @param array<mixed> $consultation
     * @return bool[]
     */
    public function getChampsObligatoireCreatEditConsult(&$consultation = []): array
    {
        if ($consultation != []) {
            $listOfSwitch = [
                'ACC_CONF' => 'O',
                'AO_PUBLIC' => 'O',
                'REPDEV' => 'O',
                'VARIANTE' => 'O',
            ];

            foreach ($listOfSwitch as $name => $default) {
                $consultation[$name] ??= Sql::paravrac($this->pdo, 'OXAPROC', 'CONSULT_CREAT_' . $name) ?: $default;
            }
        }

        $listOfInput = [
            "EMETTEUR" => true,
            "CODE_STE" => true,
            "ACH" => true,
            "DEL_REP" => true,
            "DEVISE" => true,
            "COMMENT_INT" => false,
            "OBJET_AO" => false,
            "DESCR" => false,
            "PRESCRIPTEUR" => false,
            "DTE_LANCEMENT" => false,
            "HEURE_LANCEMENT" => false,
            "HEURE_CLOTURE" => false,
            "BUDG_ENT" => false,
        ];

        foreach ($listOfInput as $name => $default) {
            $champsObligatoire[$name] = Sql::toBool(Sql::paravrac($this->pdo, 'OXAPROC', 'CONSULT_CREAT_' . $name) ?: $default);
        }

        return $champsObligatoire;
    }

    /**
     * This method has for objective to verify if the frs in AO_FOUR has a contact from AO_CONTFOUR
     * ! Cette fonction est appellé plusieurs fois afin de s'assurer qu'il y est toujours le contact principal (le premier) de AO_CONTFOUR
     * ! qui soit transféré dans AO_FOUR pour que l'envoi des différents emails depuis MAGIC se fasse correctement
     * @return void
     */
    public function checkAoFourContactWithAoContFour(int $idAO, string $codeFrs, string $typeFG)
    {
        $AoFour     = new AoFour($this->pdo);
        $AoContFour = new AoContFour($this->pdo);

        $aoActualFourniss     = $AoFour->find(['NO_AO' => (int) $idAO, 'CODE_FOU' => $codeFrs, 'TYPE_FG' => $typeFG]);
        $aoActualContactsFour = $AoContFour->findAll(['NO_AO' => (int) $idAO, 'CODE_FOUR' => $codeFrs, 'TYPE_FG' => $typeFG]);

        if (!isset($aoActualFourniss['EMAILCONT']) || trim($aoActualFourniss['EMAILCONT']) == '') {
            $allNames  = array_map(fn($ctc) => $ctc['NOM_CTCT'], $aoActualContactsFour);
            $allEmails = array_map(fn($ctc) => $ctc['EMAILCONT'], $aoActualContactsFour);

            if (!in_array($aoActualFourniss['NOM_CTCT'], $allNames) || !in_array($aoActualFourniss['EMAILCONT'], $allEmails)) {
                $AoFour->update([
                    'NOM_CTCT' => $aoActualContactsFour[0]['NOM_CTCT'] ?? '',
                    'EMAILCONT' => $aoActualContactsFour[0]['EMAILCONT'] ?? '',
                    'TEL_CTCT' => $aoActualContactsFour[0]['TEL_CTCT'] ?? '',
                    'POR_CTCT' => $aoActualContactsFour[0]['POR_CTCT'] ?? '',
                    'FAX_CTCT' => $aoActualContactsFour[0]['FAX_CTCT'] ?? '',
                ], [
                    'NO_AO' => (int) $idAO,
                    'CODE_FOU' => $codeFrs,
                    'TYPE_FG' => $typeFG,
                ]);
                // TODO: Réimplémenter la façon dont sont géré les contacts. Fait pour l'envoi des mails par Magic...
                $AoContFour->delete(['NO_AO' => (int) $idAO, 'CODE_FOUR' => $codeFrs, 'TYPE_FG' => $typeFG, 'EMAILCONT' => $aoActualContactsFour[0]['EMAILCONT']]);
            }
        }
        foreach ($aoActualContactsFour as $aoContFourContact) {
            if (($aoContFourContact['EMAILCONT'] ?? '') === ($aoActualFourniss['EMAILCONT'] ?? '')) {
                $AoContFour->delete([
                    'NO_AO' => (int) $idAO,
                    'CODE_FOUR' => $codeFrs,
                    'TYPE_FG' => $typeFG,
                    'EMAILCONT' => $aoContFourContact['EMAILCONT'] ?? ''
                ]);
            }
            if (($aoContFourContact['NOM_CTCT'] ?? '') === ($aoActualFourniss['NOM_CTCT'] ?? '')) {
                $AoContFour->delete([
                    'NO_AO' => (int) $idAO,
                    'CODE_FOUR' => $codeFrs,
                    'TYPE_FG' => $typeFG,
                    'NOM_CTCT' => $aoContFourContact['NOM_CTCT'] ?? ''
                ]);
            }
        }
    }
}
