<?php
namespace Modules\GlobalApplication\Controller;

use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Date;
use Helpers\Outil\Sql;
use Helpers\Parametres\Constante;
use Skeleton\Controller\Controller;

abstract class AbsExportController extends Controller
{
    /**
     * @param array<mixed> $post
     * @param array<mixed> $exportTab
     * @return \stdClass
     */
    protected function extractConfig(array $post, array $exportTab, string $ligneKey) :object
    {
        $arrayMultiSelect = array_filter($post, function ($k) {
            return stristr($k, 'multiSelect');
        }, ARRAY_FILTER_USE_KEY);

        // Filter any unauthorized fields
        $arrayMultiSelect = array_intersect(
            $arrayMultiSelect,
            array_keys($exportTab)
        );

        $listeEntityField = [];
        $listeCSEntete = [];
        $listeCSLigne = [];
        
        foreach ($arrayMultiSelect as $key => &$val) {
            if (strpos($val, 'CS_EXTENSION_ENTETE') === 0) {
                $listeCSEntete[] = substr($val, 19);
            } elseif (strpos($val, 'CS_EXTENSION_LIGNE') === 0) {
                $listeCSLigne[] = substr($val, 18);
            } else {
                if ($val == 'DA_ENTET.NM_COMMEN') {
                    $listeEntityField[] = 'Commentaire.CONTMEMO as "'.$val.'"';
                } elseif ($val == 'DA_ENTET.NM_TITRE') {
                    $listeEntityField[] = 'memoTitle.CONTMEMO as "'.$val.'"';
                } elseif ($val == 'DA_LIGNE.NM_DCOMP') {
                    $listeEntityField[] = 'DCompArtDA.CONTMEMO as "'.$val.'"';
                } else {
                    $listeEntityField[] = $val . ' as "'.$val.'"';
                }
            }
        }

        if (empty($post['okFilter'])) {
            $post = [];
        }

        $param = [];
        foreach ($post as $key => $value) {
            if (strpos($key, 'filter_') === 0) {
                $tblKey = explode(Constante::spliter, $key);
                $param[$tblKey[0]] = $value;
            } else {
                $param[$key] = $value;
            }
        }

        return (object) [
            'listeEntityField' => $listeEntityField,
            'listeCSEntete' => $listeCSEntete,
            'listeCSLigne' => $listeCSLigne,
            'arrayMultiSelect' => $arrayMultiSelect,
            'param' => $param,
        ];
    }

    /**
     * @param array<mixed> $mapArchi
     * @param array<mixed> $listFieldSelected
     * @return array<string, string>
     */
    protected function getEntityTitle(
        array $mapArchi,
        string $table, // TODO : deduce from $entityRepo
        array $listFieldSelected
    ) {
        $tab = [];
        foreach ($mapArchi as $k => $value) {
            $key = $table.'.' . $k;
            if (in_array($key, $listFieldSelected)) {
                $tab[$key] = $value['nomChamp'];
            }
        }
        return $tab;
    }


    /**
     * @param array<mixed>[] $listeCSEntete List of CsChps
     * @param array<mixed>[] $listeCSLigne List of CsChps
     * @return array<string,string>
     */
    protected function getChampSupTitle(array $listeCSEntete, array $listeCSLigne)
    {
        $tab = [];
        foreach ($listeCSEntete as $cs) {
            $tab['CS_EXTENSION_ENTETE'.$cs['NUM_FIX']] = $cs['NOM'];
        }
        foreach ($listeCSLigne as $cs) {
            $tab['CS_EXTENSION_LIGNE'.$cs['NUM_FIX']] = $cs['NOM'];
        }
        return $tab;
    }

    /**
     * @param array<string> $listChampSup
     * @return array<mixed>[] List of CsChps
     */
    protected function getCsSchema(string $codTab, array $listChampSup)
    {
        $repoChampSup = new ChampSupp($this->pdo);
        return array_map(function ($cs) use ($repoChampSup, $codTab) {
            return $repoChampSup->getinfoOneCs($codTab, $cs); // TODO : merge query
        }, $listChampSup);
    }

    /**
     * @param array<mixed>[] $listEntity
     * @param array<mixed>[] $listCSEnteteSchema
     * @param array<mixed>[] $listCSLigneSchema
     * @return array<mixed>[] List of CsDon
     */
    protected function listChampSupForEntityList(
        array $listEntity,
        string $entetId,
        string $ligneId,
        array $listCSEnteteSchema,
        array $listCSLigneSchema
    ) {
        $champSupp = new ChampSupp($this->pdo);

        $csId = [];
        foreach ($listEntity as $entity) {
            foreach ($listCSEnteteSchema as $schema) {
                $csId[] = [
                    $schema['COD_TAB'],
                    $champSupp->autoCompletCodeEnr(
                        $entity[$entetId],
                        null,
                        $schema['COD_TAB']
                    ),
                    $schema['NUM_FIX']
                ];
            }
            foreach ($listCSLigneSchema as $schema) {
                $csId[] = [
                    $schema['COD_TAB'],
                    $champSupp->autoCompletCodeEnr(
                        $entity[$entetId],
                        $entity[$ligneId],
                        $schema['COD_TAB']
                    ),
                    $schema['NUM_FIX']
                ];
            }
        }

        // Note : following code cannot work due the limit in parametre of PDO and the large amount of id
        //return $champSupp->getCsDon($csId);

        return array_filter(array_map(function ($id) use ($champSupp) {
            return $champSupp->getCsDon([$id])[0] ?? null;// TODO : merge with main request
        }, $csId));
    }

    /**
     * @param array<mixed> $mapArchi as returned by QueryBuilder::getArchitecture()
     * @param array<mixed> $entity
     * @return array<mixed>[]
     */
    protected function getEntityView($mapArchi, $entity) :array
    {
        $trad = $this->getTranslationService();
        $view = $entity;
        foreach ($entity as $fullname => $value) {
            // Case : field is prefixed by it's table
            $field = $fullname;
            if (strpos($field, '.')) {
                $field = explode('.', $field)[1];
            }
            if (! isset($mapArchi[ $field ])) {
                continue;
            }
            switch ($mapArchi[ $field ]['type']) {
                case 'DATE':
                    $view[ $fullname ] = Date::dateConverte($value);
                    break;
                case 'RADIO':
                    $view[ $fullname ] = Sql::toBool($value) ?
                        $trad->t('Oui') : $trad->t('Non');
                    break;
            }
        }
        return $view;
    }

    /**
     * @param array<mixed> $mapArchi as returned by QueryBuilder::getArchitecture()
     * @param array<mixed>[] $listEntity
     * @return array<mixed>[]
     */
    protected function getListEntityView(array $mapArchi, array $listEntity) :array
    {
        return array_map(function ($entity) use ($mapArchi) {
            return $this->getEntityView($mapArchi, $entity);
        }, $listEntity);
    }
}
