<?php

namespace Helpers\Outil;

use Helpers\Trad\ITrad;
use Modules\Ajax\Repository\Signataires;

class ZoomHelper
{

    public static function getZoomTitle(string $path, ITrad $trad) :string
    {
        switch ($path) {
            case 'Ajax.liste.articles':
                return $trad->t('Liste des articles');
            case 'Ajax.liste.articlesFraisPort':
                return $trad->t('Liste des articles frais de port');
            case 'Ajax.liste.societe':
                return $trad->t('Liste des sociétés');
            case 'Ajax.liste.fonctionUser':
                return $trad->t('Liste fonctions');
            case 'Ajax.liste.grpfou':
                return $trad->t('Liste des groupements');
            case 'Ajax.liste.si':
                return $trad->t('Liste des sections d\'imputation');
            case 'Ajax.liste.cdc':
                return $trad->t('Liste des codes complémentaires');
            case 'Ajax.liste.conditionPaiement':
                return $trad->t('Condition de paiement');
            case 'Ajax.liste.contactFournisseur':
                return $trad->t('Contact fournisseur');
            case 'Ajax.liste.delegatairePref':
                return $trad->t('Liste des délégataires');
            case 'Ajax.liste.sca':
                return $trad->t('Liste des sous-comptes d\'analyse');
            case 'Ajax.liste.utilisateur':
                return $trad->t('Liste des utilisateurs');
            case 'Ajax.liste.centreEmetteur':
                return $trad->t('Liste des centres émetteurs');
            case 'Ajax.liste.centreLivraison':
                return $trad->t('Liste des centres de livraisons');
            case 'Ajax.liste.domaineCompetence':
                return $trad->t('Liste des domaines de compétence');
            case 'Ajax.liste.motClef':
                return $trad->t('Liste des mots clés');
            case 'Ajax.liste.modelivraison':
                return $trad->t('Mode de livraison');
            case 'Ajax.liste.modePaiement':
                return $trad->t('Mode de paiement');
            case 'Ajax.liste.regroup':
                return $trad->t('Liste des regroupements fournisseurs');
            case 'GlobalApplication.MultiSelect.afficher': // TODO : entity should be specified in the route
                return $trad->t('Liste des domaines fonctionnels');
            case 'Ajax.Treeview.uoTreeview':
                return $trad->t('Liste des unités organisationnelles');
            case 'Ajax.liste.typeAchat':
                return $trad->t('Liste des types d\'achat');
            case 'Ajax.liste.typeDoc':
                return $trad->t('Type de document');
            case 'Ajax.liste.sousFamille':
                return $trad->t('Liste des sous-familles');
            case 'Ajax.liste.sitesto':
                return $trad->t('Liste des sites de stock');
            // case \Entity\Model\Centre::class:
            //     return $trad->t('Liste des centres');
            case 'Ajax.liste.devise':
                return $trad->t('Liste des devise');
        }
        throw new \Exception('Invalid zoom path "'.$path.'"');
    }

    /**
     * @deprecated zoom path should deduce the entity and not the other way around
     * @param class-string<\Helpers\QueryBuilder\QueryBuilder> $entity
     */
    public static function getZoomPath(string $entity) :string
    {
        switch ($entity) {
            case \Entity\Model\Societe::class:
                return 'Ajax.liste.societe';
            case \Entity\Model\Sectimpu::class:
                return 'Ajax.liste.si';
            case \Entity\Model\Codecomp::class:
                return 'Ajax.liste.cdc';
            case \Entity\Model\Sscptana::class:
                return 'Ajax.liste.sca';
            case \Entity\Model\Hastutil::class:
                return 'Ajax.liste.utilisateur';
            case \Entity\Model\FoncUsr::class:
                return 'Ajax.liste.fonctionUser';
            case \Entity\Model\CentreEmetteur::class:
                return 'Ajax.liste.centreEmetteur';
            case \Entity\Model\CentreLivraison::class:
                return 'Ajax.liste.centreLivraison';
            case \Entity\Model\UO::class:
                return 'Ajax.Treeview.uoTreeview';
            case \Entity\Model\SSiteSto::class:
                return 'Ajax.liste.sitesto';
            case \Entity\Model\Devise::class:
                return 'Ajax.liste.devise';
        }
        throw new \Exception('Invalid entity "'.$entity.'"');
    }

    /**
     * @return class-string<\Helpers\QueryBuilder\QueryBuilder>
     */
    public static function getEntityFromPath(string $path) :string
    {
        switch ($path) {
            case 'Ajax.liste.articlesFraisPort':
            case 'Ajax.liste.articles':
                return \Entity\Model\Articles::class;
            case 'Ajax.liste.societe':
                return \Entity\Model\Societe::class;
            case 'Ajax.liste.si':
                return \Entity\Model\Sectimpu::class;
            case 'Ajax.liste.cdc':
                return \Entity\Model\Codecomp::class;
            case 'Ajax.liste.conditionPaiement':
                return \Entity\Model\CondPaie::class;
            case 'Ajax.liste.contactFournisseur':
                return \Entity\Model\Contfour::class;
            case 'Ajax.liste.delegatairePref':
                return \Entity\Model\Hastutil::class;
            case 'Ajax.liste.domaineCompetence':
                return \Entity\Model\DomaineCompetence::class;
            case 'Ajax.liste.sca':
                return \Entity\Model\Sscptana::class;
            case 'Ajax.liste.utilisateur':
                return \Entity\Model\Hastutil::class;
            case 'Ajax.liste.fonctionUser':
                return \Entity\Model\FoncUsr::class;
            case 'Ajax.liste.grpfou':
                return \Entity\Model\Grpfou::class;
            case 'Ajax.liste.centreEmetteur':
                return \Entity\Model\CentreEmetteur::class;
            case 'Ajax.liste.centreLivraison':
                return \Entity\Model\CentreLivraison::class;
            case 'Ajax.liste.motClef':
                return \Entity\Model\MotClef::class;
            case 'Ajax.liste.modelivraison':
                return \Entity\Model\Modelivr::class;
            case 'Ajax.liste.modePaiement':
                return \Entity\Model\Modepaie::class;
            case 'Ajax.liste.regroup':
                return \Entity\Model\Regroupement::class;
            case 'Ajax.Treeview.uoTreeview':
                return \Entity\Model\UO::class;
            case 'Ajax.liste.typeAchat':
                return \Entity\Model\TypeAchat::class;
            case 'Ajax.liste.typeDoc':
                return \Entity\Model\TypeDoc::class;
            case 'Ajax.liste.sousFamille':
                return \Entity\Model\SousFamille::class;
            case 'Ajax.liste.sitesto':
                return \Entity\Model\SSiteSto::class;
            case 'Ajax.liste.devise':
                return \Entity\Model\Devise::class;
        }
        throw new \Exception('Invalid zoom path "'.$path.'"');
    }
    

    /**
     *
     * @return \stdClass{
     *     callable:callable,
     *     ?mainId:string,
     *     ?entity:class-string<QueryBuilder>
     * }
     */
    public static function getListeCallback(string $path, \PDO $pdo)
    {
        $repo = new \Modules\Ajax\Repository\Listes($pdo);
        $treeview = new \Modules\Ajax\Repository\Treeview($pdo);
        $soc = new \Modules\GlobalApplication\Repository\Societe($pdo);
        $callable = [
            'Ajax.liste.accadre' => (object) [
                'callable' => [$repo, 'AccordCadre'],
                'entity' => \Entity\Model\Acccadre::class,
            ],
            'Ajax.liste.acheteur' => (object) [
                'callable' => [$repo, 'acheteur'],
                'entity' => \Entity\Model\Hastutil::class,
            ],
            'Ajax.liste.aoFormatExcel' =>
                self::simpleEntityFetch(\Entity\Model\AoExCentre::class, $pdo),
            'Ajax.liste.articles' => (object) [
                'callable' => function ($post) use ($pdo) {
 // TODO : split into 3 and factorize with ListeController
           
                    // Case : ???
                    if (empty($post['filter_CODE_ART']) && ($post['filter_CODE_ART'] ?? null) !== '') {
                        $post['valide'] = 1;
                    } else {
                        Outils::isCheck($post['valide']);
                    }
            
                    $liste = new \Modules\Ajax\Repository\Listes($pdo);
                    if (!empty($post['art_acd'])) {
                        return $liste->getFrameworkItems($post);
                    }
                    if (!empty($post['art_fou'])) {
                        // si un fournisseur est renseigné on cherche uniquement les articles liés au fournisseur
                        return $liste->getSupplierItems($post);
                    }
                    return $liste->listeArticles($post);
                },
                'entity' => \Entity\Model\Articles::class,
            ],
            'Ajax.liste.articlesFrsFaSfa' => (object) [
                'callable' => [$repo, 'listeArticlesFrsFaSfa'],
                'entity' => \Entity\Model\Articles::class,
            ],
            'Ajax.liste.articlesSiCdcSca' => (object) [
                'callable' => [$repo, 'listeArticlesSiCdcSca'],
                'entity' => \Entity\Model\Articles::class,
            ],
            //TODO 'Ajax.liste.br' => (object) [
            //     'callable' => [$repo, ''],
            //     'entity' => \Entity\Model\::class,
            // ],
            'Ajax.liste.caEntet' => (object) [
                'callable' => [$repo, 'CaEntet'],
                'entity' => \Entity\Model\CaEntet::class,
            ],
            'Ajax.liste.campNotEx' => (object) [
                'callable' => [$repo, 'listeCampNotex'],
                'entity' => \Entity\Model\CampNotex::class,
            ],
            'Ajax.liste.cdc' => (object) [
                'callable' => [$repo, 'Cdc'],
                'entity' => \Entity\Model\Codecomp::class,
            ],
            'Ajax.liste.centrana' => (object) [
                'callable' => [$repo, 'Centrana'],
                'entity' => \Entity\Model\Centrana::class,
            ],
            'Ajax.liste.centre' =>
                self::simpleEntityFetch(\Entity\Model\Centre::class, $pdo),
            'Ajax.liste.centreAnalyseUtilisateurAutorise' => (object) [
                'callable' => [$repo, 'centreAnalyseUtilisateur'],
                'entity' => \Entity\Model\Centrana::class,
            ],
            //  TODO 'Ajax.liste.centreByType' => (object) [
            //     'callable' => [$repo, 'centreByType'],
            //     'entity' => \Entity\Model\::class,
            // ],
            'Ajax.liste.centreEmetteur' => (object) [
                'callable' => [$repo, 'centreEmetteur'],
                'mainId' => 'filter_egal_cen.CODE_CTR',// TODO: get rid of the table alias
            ],
            'Ajax.liste.centreLivraison' => (object) [
                'callable' => [$repo, 'centreLivraison'],
                'mainId' => 'filter_egal_cen.CODE_CTR',// TODO: get rid of the table alias
            ],
            'Ajax.liste.commandeModele' => (object) [
                'callable' => [$repo, 'getListeModeleCommande'],
                'entity' => \Entity\Model\MCa::class,
            ],
            'Ajax.liste.conditionPaiement' => (object) [
                'callable' => [$repo, 'ConditionPaiement'],
                'entity' => \Entity\Model\CondPaie::class,
            ],
            'Ajax.liste.contactFournisseur' => (object) [
                'callable' => [$repo, 'contactsFournisseur'],
                // 'entity' => \Entity\Model\Contfour::class,
                'mainId' => 'filter_egal_IND_FOU',//!\\ Assuming that there is a CODE_FOU in the filter
            ],
            'Ajax.liste.cqualite' =>
                self::simpleEntityFetch(\Entity\Model\Cqualite::class, $pdo),
            'Ajax.liste.dccEntet' =>
                self::simpleEntityFetch(\Entity\Model\DccEntet::class, $pdo),
            'Ajax.liste.delegatairePref' => (object) [
                'callable' => [$repo, 'listDeleg'],
                'entity' => \Entity\Model\Hastutil::class,
            ],
            'Ajax.liste.demandeur' => (object) [
                'callable' => function ($post) use ($repo) {
 // TODO : factorize
                    return $repo->utilisateurListe([
                        'DEMAND' => true,
                        'CODE_STE' => $post['filter_egal_CODE_STE'],
                    ] + $post);
                },
                'entity' => \Entity\Model\Hastutil::class,
            ],
            'Ajax.liste.devise' => (object) [
                'callable' => [$repo, 'Devise'],
                'entity' => \Entity\Model\Devise::class,
            ],
            'Ajax.liste.directio' => (object) [
                'callable' => [$repo, 'Directio'],
                'entity' => \Entity\Model\Directio::class,
            ],
            'Ajax.liste.doa' =>
                self::simpleEntityFetch(\Entity\Model\Doa::class, $pdo),
            'Ajax.liste.domaineCompetence' =>
                self::simpleEntityFetch(\Entity\Model\DomaineCompetence::class, $pdo),
            'Ajax.liste.douanes' =>
                self::simpleEntityFetch(\Entity\Model\Douanes::class, $pdo),
            // TODO : restrict 'Ajax.liste.entityList' =>
            'Ajax.liste.etatStat' => (object) [
                'callable' => [$repo, 'etatStat'],
                'entity' => \Entity\Model\EtatStat::class,
            ],
            'Ajax.liste.fabricant' =>
                self::simpleEntityFetch(\Entity\Model\Fabricant::class, $pdo),
            'Ajax.liste.famille' => (object) [
                'callable' => [$repo, 'famille'],
                'entity' => \Entity\Model\Famille::class,
            ],
            'Ajax.liste.fonction' =>
                self::simpleEntityFetch(\Entity\Model\Fcontfrn::class, $pdo),
            'Ajax.liste.fonctionUser' =>
                self::simpleEntityFetch(\Entity\Model\FoncUsr::class, $pdo),
            // TODO 'Ajax.liste.fournisseur' =>
            // TODO 'Ajax.liste.fournisseurSansArticlesSansCommande' =>
            'Ajax.liste.gamme' =>
                self::simpleEntityFetch(\Entity\Model\Gamme::class, $pdo),
            'Ajax.liste.groupeSignataire' => (object) [
                'callable' => [(new Signataires($pdo)), 'signataireREFGroupe'],
                'entity' => \Entity\Model\WfGrpSig::class,
            ],
            'Ajax.liste.grpfou' =>
                self::simpleEntityFetch(\Entity\Model\Grpfou::class, $pdo),
            'Ajax.liste.grpSociete' => (object) [
                'callable' => [$repo, 'findGroupedCompanies'],
                'entity' => \Entity\Model\GrpSociete::class,
            ],
            'Ajax.liste.messstan' =>
                self::simpleEntityFetch(\Entity\Model\Messstan::class, $pdo),
            'Ajax.liste.modelivraison' => (object) [
                'callable' => [$repo, 'modeLivraison'],
                'entity' => \Entity\Model\Modelivr::class,
            ],
            'Ajax.liste.modePaiement' => (object) [
                'callable' => [$repo, 'modePaiement'],
                'entity' => \Entity\Model\Modepaie::class,
            ],
            'Ajax.liste.motClef' =>
                self::simpleEntityFetch(\Entity\Model\MotClef::class, $pdo),
            'Ajax.liste.natana' => (object) [
                'callable' => [$repo, 'Natana'],
                'entity' => \Entity\Model\Natana::class,
            ],
            'Ajax.liste.ordonance' =>
                self::simpleEntityFetch(\Entity\Model\Ordonanc::class, $pdo),
            'Ajax.liste.pays' =>
                self::simpleEntityFetch(\Entity\Model\Country::class, $pdo),
            'Ajax.liste.periodes' =>
                self::simpleEntityFetch(\Entity\Model\Periodes::class, $pdo),
            'Ajax.liste.sca' => (object) [
                'callable' => [$repo, 'Sca'],
                'entity' => \Entity\Model\Sscptana::class,
            ],
            'Ajax.liste.si' => (object) [
                'callable' => [$repo, 'SectionImputation'],// TODO : handle $post['panier']
                'entity' => \Entity\Model\Sectimpu::class,
            ],
            'Ajax.liste.sitesto' => (object) [
                'callable' => [$repo, 'siteStockAlone'],
                'entity' => \Entity\Model\SSiteSto::class,
            ],
            'Ajax.liste.societe' => (object) [
                'callable' => [$soc, 'listUserSociete'],
                'entity' => \Entity\Model\Societe::class,
                'mainId' => 'filter_CODE_STE',
            ],
            // TODO: add FilterTable to listeSocieteCommuneSignataireDelegataire
            // 'Ajax.liste.societeCommune' => (object) [
            //     'callable' => [$soc, 'listeSocieteCommuneSignataireDelegataire'],
            //     'mainId' => 'filter_CODE_STE',
            // ],
            'Ajax.liste.sousFamille' => (object) [
                'callable' => [$repo, 'sousFamille'],
                'entity' => \Entity\Model\SousFamille::class,
                'mainId' => 'filter_egal_SousFam.CODE_SFA',
            ],
            // TODO: 'Ajax.liste.sscptana' =>
                // TODO : remove  if (!$scaSecto) unset($post['CODE_STE']);


            'Ajax.liste.ssItesto' => (object) [
                'callable' => [$repo, 'siteStock'],
                'entity' => \Entity\Model\SSiteSto::class,
            ],
            // TODO : 'Ajax.liste.tsDon' =>
            'Ajax.liste.TVA' =>
                self::simpleEntityFetch(\Entity\Model\TVA::class, $pdo),
            'Ajax.liste.typeAchat' => (object) [
                'callable' => [$repo, 'typeAchat'],
                'entity' => \Entity\Model\TypeAchat::class,
            ],
            'Ajax.liste.typeAchatFournis' => (object) [
                'callable' => [$repo, 'typeAchatFournisseur'],
                'entity' => \Entity\Model\TacFyfo::class,
            ],
            'Ajax.liste.typeDeMarche' =>
                self::simpleEntityFetch(\Entity\Model\TypeDeMarche::class, $pdo),
            'Ajax.liste.typeDoc' => (object) [
                'callable' => [$repo, 'listeTypeDoc'],
                'entity' => \Entity\Model\TypeDoc::class,
            ],
            'Ajax.liste.unites' => (object) [
                'callable' => [$repo, 'listeUnite'],
                'entity' => \Entity\Model\Unites::class,
            ],
            'Ajax.liste.utilisateur' => (object) [
                'callable' => [$repo, 'utilisateurListe'],
                'entity' => \Entity\Model\Hastutil::class,
            ],

            'Ajax.Treeview.uoTreeview' => (object) [
                // TODO : get rid of HASSTD_ListeUO_PerimetreUser
                // 'callable' => [$treeview, 'UO'],
                'callable' => function ($post) use ($pdo) {
                    return (new \Entity\Model\UO($pdo))->fetchAll([], $post);
                },
                'entity' => \Entity\Model\UO::class,
            ],

            /**
             * TODO
Commande.GareDeTriage.popupCritereRegroup
Commande.popupCreationCde.popupListeAO
Commande.popupCreationCde.popupListeDA
Commande.popupCreationCde.popupListeligneDA
Evaluation.BibliothequeDeQuestions.popupNoteur', {'origine_noteur' : origine_noteur, 'entity' : entity}),
Evaluation.Question.parentQuestionList
Evaluation.Question.parentQuestionList', {mode: mode, id: idMode, theme: idTheme, questionId: idQuestion}),
GlobalApplication.MultiSelect.afficher
Panier.ImportLigne.listeFormat
ProjetAchat.BibliothequeDonnee.popupFormatDocument
Reception.Lot.listeLots
Specifique118.TableauReporting.listeAcheteurs
Specifique118.TableauReporting.listeFamilles
Specifique118.TableauReporting.listeFournisseurs
Specifique118.TableauReporting.listeNature
Specifique118.TableauReporting.listePole
Specifique118.TableauReporting.listePrestation
Specifique118.TableauReporting.listeSI
Specifique118.TableauReporting.listeSignataire
Specifique118.TableauReporting.listeSousFamilles
Specifique95.EtatStatistique.liste', {'type' : 'centre'}),
Specifique95.EtatStatistique.liste', {'type' : 'compte'}),
Utilisateur.MesBackup.listeBackup
             */
            
        ][ $path ] ?? null;
        if ($callable == null) {
            throw new \Exception('Invalid path "'.$path.'"');
        }
        return $callable;
    }

    /**
     * @param class-string<\Helpers\QueryBuilder\QueryBuilder> $entityClass
     * @return \stdClass
     */
    private static function simpleEntityFetch(string $entityClass, \PDO $pdo) :object
    {
        return (object) [
            'callable' => function ($post) use ($pdo, $entityClass) {
                return (new $entityClass($pdo))->fetchAll([], $post);
            },
            'entity' => $entityClass,
        ];
    }
}
