<?php

namespace Modules\Ajax\Controller;

use Entity\Model\Centre;
use Entity\Model\Fourniss;
use Entity\Model\OxaUserCnt;
use GuzzleHttp\Psr7\Response;
use Helpers\Outil\Roles;
use Helpers\Outil\ZoomHelper;
use Helpers\User\User;
use Modules\Ajax\Repository\Autocomplete;
use Skeleton\Controller\Controller;
use Modules\Ajax\Repository\Listes;
use Modules\RechercheArticles\Repository\RequeteCont;
use Entity\Entity;
use Helpers\Log\LogSysteme;
use Helpers\Pagination\PaginatorGestion;

class AutoCompleteController extends Controller
{

    private function listeEntitylist(string $entity) :?string
    {
        // S'assurer que le premier champs de l'array qui sera retrourné est bien la désignation
        $array = [
            'ARTICLES'      => 'listeArticles',
            'CONDPAIE'      => 'ConditionPaiement',
            'FAMILLE'       => 'famille',
            'SOUSFAMILLE'   => 'Sousfamille',
            'MODELIVR'      => 'modeLivraison',
            'MODEPAIE'      => 'modePaiement',
            'TYPEACHAT'     => 'typeAchat',
        ];
        
        return $array[$entity]??null;
    }

    private function specifiqueEntity(string $entity):string
    {
        $array = [
            'FournissPanier' => 'Fourniss',
        ];

        return $array[$entity]??'';
    }

    public function autocomplete2Action() :Response
    {
        $post = $this->request->getParsedBody();

        if (empty($post['zoom_path'])) {
            throw new \Exception('Missing zoom_path in "'. $_SERVER['HTTP_REFERER'] . '"');
        }

        if (empty($post['search'])) {
            return $this->createJsonResponse([]);
        }

        $path = $post['zoom_path'];

        $zoom = ZoomHelper::getListeCallback($post['zoom_path'], $this->contenaire);
        $primaryKey = $zoom->primaryKey ?? null;
        if ($primaryKey == null) {
            // @phpstan-ignore-next-line
            $entityClass = ZoomHelper::getEntityFromPath($path);

            if (empty($entityClass)) {
                throw new \Exception('Invalid zoom config for "' . $path . '"');
            }

            /** @var \Helpers\QueryBuilder\QueryBuilder */
            $qb = new $entityClass($this->pdo);
            
            $primaryKey = $qb->getPrimaryKey();
            if (empty($primaryKey)) {
                throw new \Exception('Incompatible entity "' . $entityClass . '"');
            }
            $label = $zoom->libelle ?? $qb->getLibelle();
            $table = $qb->getTable();
        } else {
            $label = $zoom->libelle ?? null;
            $table = null;
        }

        /** @var callable */
        $callable = $zoom->callable;
        
        (new PaginatorGestion())->generate(10);
        $list = $callable([
            'filter_' . implode(
                \Helpers\Parametres\Constante::spliter,
                array_map(
                    fn($key) => ($table != null ? $table . '.' : '') . $key,
                    array_filter([$label, $primaryKey])
                )
            ) =>  $post['search'],
        ] + ($post['filter'] ?? []));

        return $this->createJsonResponse(array_map(function ($item) use ($label, $primaryKey) {
            return [
                'label' => !empty($item[ $label ])
                    ? $item[ $label ] . ' ('.$item[ $primaryKey ].')'
                    : $item[ $primaryKey ],
                'value' => $item[ $primaryKey ],
            ];
        }, $list));
    }
    
    public function autocompleteAction() :Response
    {
        $post = $this->request->getParsedBody();
        $liste = new Listes($this->pdo);
        
        if (in_array(strtoupper($post['entity']), ['HASTUTIL', 'SOCIETE']) && !(new User())->getCodeUser()) {
            return new Response(200, [], (string)json_encode([]));
        }

        parse_str($post['postperimetre'], $post['postperimetre']);

        if ($post['entity'] == 'articleCatalogue') {
            $where = '';

            $listeCataPriver = [];
            foreach ($post['postperimetre'] as $k => $v) {
                if (strpos((string)$k, 'catalogue') === 0) {
                    $idCatalogue = str_replace('catalogue', '', (string)$k);

                    $listeCataPriver[] = $idCatalogue;
                }
            }
            
            if ($listeCataPriver) {
                $where = "AND EXISTS (SELECT * FROM STRING_SPLIT(CATPRLST, ';') WHERE value IN ('".implode("','", $listeCataPriver)."'))";
            }

            $oxaUserCnt = new OxaUserCnt($this->pdo);

            $result = $oxaUserCnt->find([
                'COD_USR' => $_SESSION["Session_Login"],
                'COD_TYPE' => 'SESSION',
                'COD_CHAMP' => 'AUTOCOMP_NB_RESULT_MAX',
            ]);

            if ($result) {
                $paramUser['AUTOCOMP_NB_RESULT_MAX'] = $result['VALEUR'];
            } else {
                $paramUser['AUTOCOMP_NB_RESULT_MAX'] = '20';
            }

            $centre = new Centre($this->pdo);
            $centre = $centre->find($_SESSION['Session_CodeCtrLivraison']);
            $siteStock = $centre['SITSTOCK'];

            $post['search'] = str_replace("'", "''", $post['search']);

            $rechercheArticle = new RequeteCont($this->pdoOxaFT, $_SESSION["Session_Login"], $_SESSION['Session_CodeCtrLivraison'], $siteStock);
            $rechercheArticle->setDesactiveZoneGeo('1');
            $rechercheArticle->setRecherche('"'.$post['search'].'*"', $where, 'DES_ART');
            $rechercheArticle->setTable('CATAPROC');
            $contents = $rechercheArticle->articleByRank(1, $paramUser['AUTOCOMP_NB_RESULT_MAX']);
            
            $return = [];
            foreach ($contents as $content) {
                $arrayTuple = $content['DES_ART'];

                $return[]=$arrayTuple;
            }
    
            return new Response(200, [

            ], (string)json_encode($return));
        }
        if (isset($post['value'])) {
            $post['entity'] = $this->specifiqueEntity($post['entity'])?: $post['entity'];
            $generatorEntity = "\\Entity\\Model\\".$post['entity'];
            
            /** @var Entity $entity */
            $entity = new $generatorEntity($this->pdo);
    
            if ($entity->getLibelle()) {
                if ($this->listeEntitylist(strtoupper($post['entity']))) {
                    $listeEntity = $this->listeEntitylist(strtoupper($post['entity']));
                    $contentTMP = $liste->{$listeEntity}(['filter_'.$entity->getLibelle() => $post['value']], $entity->getPrimaryKey());
                    $content[0] = $contentTMP[0][$entity->getPrimaryKey()];
                } else {
                    $where = [$entity->getLibelle() =>  $post['value']];
                    $select = [$entity->getPrimaryKey()];
                    
                    $content = $entity->find($where, $select);
                    $content[0] = $content[$entity->getPrimaryKey()];
                }
                
                return new Response(200, [], (string)json_encode($content[0]));
            } else {
                return new Response(200, [], (string)json_encode($post['value']));
            }
        } elseif ($post['entity'] == 'FournissPanier') {
            $fourniss = new Fourniss($this->pdo);
            $contents = (new Autocomplete($this->pdo))->fournisseurSociete($post['search']);
            
            $return = [];
            foreach ($contents as $content) {
                $arrayTuple = $content[$fourniss->getLibelle()];
                
                $return[] = $arrayTuple;
            }
            
            return new Response(200, [], (string)json_encode($return));
        } else {
            $generatorEntity = "\\Entity\\Model\\".$post['entity'];
       
            /** @var \Helpers\QueryBuilder\QueryBuilder */
            $entity = new $generatorEntity($this->pdo);

            $arrayAxesSecto = [
                'SECTIMPU' => Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE')? 'CODE_STE':null,
                'SSCPTANA' => Roles::droit($this->pdo, 'SCASECTO', 'PARAMSTE')? 'CODE_STE':null,
                'CODECOMP' => Roles::droit($this->pdo, 'CDCSECTO', 'PARAMSTE')? 'CODE_STE':null,
            ];

            $arraySte = [];
            if ($post['codeSte']) {
                $rowSte = $arrayAxesSecto[strtoupper($post['entity'])]??null;
                if ($rowSte) {
                    $arraySte = [
                        'ROW_SECTO_'.$rowSte => $post['codeSte']
                    ];
                }
            }
            
            if ($post['tsDon']) {
                $arraySte += [
                    'ROW_SECTO_TYPEDICO' => $post['tsDon']
                ];
            }

            if ($entity->getLibelle()) {
                $where = [$entity->getLibelle() =>  $post['search'], $entity->getPrimaryKey() =>  $post['search']]+$arraySte;
                $select = ['distinct TOP 5 '.$entity->getLibelle()];
            } else {
                $where = [$entity->getPrimaryKey() =>  $post['search']]+$arraySte;
                $select = [' distinct TOP 5 '.$entity->getPrimaryKey()];
            }

            if ($this->listeEntitylist(strtoupper($post['entity']))) {
                $listeEntity = $this->listeEntitylist(strtoupper($post['entity']));
                $contents = $liste->{$listeEntity}([$entity->getPrimaryKey() => $post['search']]+$arraySte, 'distinct TOP 5 '.$entity->getLibelle());
            } else {
                $contents = $entity->findAllSearch($where, $select);
            }
            
            $return = [];
            foreach ($contents as $content) {
                $return[] = $content[1] ?? $content[0];
            }

            if (!isset($return[0])) {
                $return = [];
                foreach ($contents as $content) {
                    $return[] = $content[array_key_first($content)];
                }
            }
            
            return new Response(200, [], (string)json_encode($return));
        }
    }

    /**
     * used with .autocomplete (cf global.js) [data-autocompletefunction]
     */
    public function functionAction() :Response
    {
        $return = [];
        $post = $this->request->getParsedBody();
        $autocomplete = new \Modules\Ajax\Repository\Autocomplete($this->pdo);

        $contents = [];

        switch ($this->request->getAttribute('function')) {
            case 'fournisseurFacture':
                $contents = $autocomplete->fournisseurFacture($post['search'] ?? '', $post['valid']);
                break;
            default:
                LogSysteme::prefixErrorLog('Invalid arg function "'.$this->request->getAttribute('function').'" (Referer: '.$_SERVER['HTTP_REFERER'].')');
        }
        
        foreach ($contents as $content) {
            $arrayTuple= $content[1] ?? $content[0];
           
            $return[]=$arrayTuple;
        }

        return $this->createJsonResponse($return);
    }
}
