<?php
namespace Helpers\Outil;

use Container\MenuTop\P2P;
use Container\MenuTop\PilotageAchat;
use Container\MenuTop\RelationFournisseur;
use Container\MenuTop\S2C;
use Entity\Model\Paravrac;
use Helpers\Additional\Additional;
use PDO;
use Psr\Container\ContainerInterface;
use Skeleton\Router;
use Helpers\Session\ParseBase1;
use Helpers\User\User;
use Modules\Administration\Repository\UtilisateurRepo;

class Roles
{
    /**
     * @return array<mixed>
     */
    private static function getListDevComputer()
    {
        return [
            'PUYANG',
            'BONIFACIO',
            'CLISSON',
            'CONSTANTINE',
            'DESSOUK',
            'DRAVEIL',
            'FIGARI',
            'GAP',
            'HILLION',
            'HOUSTON',
            'LASVEGAS',
            'MEDAN',
            'MOUTHE',
            //'ONAY',
            'ONOMICHI',
            'PABU',
            'PAREDES',
            'POOLE',
            'POUZZOLES',
            'PUGET',
            'PIRIAC',
            'SEHALTIEL',
            'TAMRI',
            'TAVERNY',
            'TORINO',
            'VIENNE',
            'PAINBLANC',
            'PAIMPONT',
            'PUTEAUX',
            'PRIEZ',
            'OSTENDE'
        ];
    }

    /**
     * @return array<string>
     */
    private static function getListLoginDev()
    {
        return [
            'ADMINCENTRAL',
            'BBA',
            'EQU',
            'IDO',
            'LGU',
            'MASTER',
            'MCH',
            'MSA',
            'OXAUSER',
            'RA',
            'RACHAT',
            'SGR',
            'VICTOR',
            'YAB',
            'YA',
            'APR',
            'TBE'
        ];
    }

    // phpcs:ignore
    public static function GetALL() :bool
    {
        return in_array($_SERVER['COMPUTERNAME'], self::getListDevComputer())
            && in_array(($_SESSION['Session_Login']??''), self::getListLoginDev());
    }

    // phpcs:ignore
    public static function GetAllDev() :bool
    {
        return (isset($_SESSION['Session_Login']) && ($_SESSION['Session_Login']==='MSA' || $_SESSION['Session_Login']==='YAB' || $_SESSION['Session_Login']==='BBA' || $_SESSION['Session_Login']==='EQU' || $_SESSION['Session_Login']==='SGR' || $_SESSION['Session_Login']==='OXAUSER' || $_SESSION['Session_Login']==='MCH' || $_SESSION['Session_Login']==='MASTER' || $_SESSION['Session_Login']==='TBE')) &&
        ((isset($_SESSION['Session_Login']) && 'POOLE' === $_SERVER['COMPUTERNAME'] ||'TAVERNY' === $_SERVER['COMPUTERNAME'] || 'CLISSON' === $_SERVER['COMPUTERNAME'] || "ONOMICHI" === $_SERVER['COMPUTERNAME'] || "LASVEGAS" === $_SERVER['COMPUTERNAME'] || "HOUSTON" === $_SERVER['COMPUTERNAME'] ||'GAP' === $_SERVER['COMPUTERNAME'] || 'PUGET' === $_SERVER['COMPUTERNAME'] || 'BONIFACIO' === $_SERVER['COMPUTERNAME'] || 'HILLION' === $_SERVER['COMPUTERNAME'] || 'MOUTHE' === $_SERVER['COMPUTERNAME'] || 'VIENNE' === $_SERVER['COMPUTERNAME'] || "SEHALTIEL" === $_SERVER['COMPUTERNAME'] || "FIGARI" === $_SERVER['COMPUTERNAME'] || "DRAVEIL" === $_SERVER['COMPUTERNAME'] || 'PAREDES' === $_SERVER['COMPUTERNAME'] || "PABU" === $_SERVER['COMPUTERNAME']  || "DESSOUK" === $_SERVER['COMPUTERNAME'] || "ONAY" === $_SERVER['COMPUTERNAME'] || "PUTEAUX" === $_SERVER['COMPUTERNAME']));
    }
    

    /**
     * @param \PDO $pdo
     * @param string $droit
     * @param string $type
     * @param boolean $texte
     * @return boolean|string
     *
     * return true/false ou la valeur du droit si $texte est a true
     */
    public static function droit($pdo, $droit, $type = 'PARAMGEN', $texte = false)
    {
        $paravrac = new Paravrac($pdo);
        $resultat = $paravrac->find([
            'TYPEPARV' => $type,
            'CODEPARV' => $droit
        ]);

        if (!$texte) {
            if (\str_replace(' ', '', $resultat['LIB01PARV'] ?? '') == 'O') {
                return true;
            } else {
                return false;
            }
        } else {
            return trim($resultat['LIB01PARV']??'');
        }
    }
    
    /**
     * @deprecated use paravrac instead
     * @param \PDO $pdo
     * @param mixed $droit
     * @param string $type
     * return uniquement la valeur du droit
     */
    public static function getDroit($pdo, $droit, $type = 'PARAMGEN') :string
    {
        if (($_SESSION['Session_Login']??'') == 'OXAUSER' || Roles::GetALL()) {
            return '1';
        }
        return (new Paravrac($pdo))->getValue($type, $droit) ?? '';
    }
    
    /**
     * retourne le droit utilisateur
     *
     * @param \PDO $pdo
     * @param string $droit
     * @param string $user
     * @return number|string -> valeur du droit
     */
    public static function droitsUtilisateur($pdo, $droit, $user = null)
    {
        if (!$user) {
            $user = $_SESSION['Session_Login'];
        }

        if ($_SESSION["Session_Login"] == 'ADMIN' && $droit == 'HA_PARAM') {
            return 1;
        }

        if (in_array($droit, ['OX_MOD_SI', 'OX_MOD_CG','OX_MOD_CDC','OX_MOD_SCA'])) {
            //return 0;
        }

        if ($_SESSION['Session_Login'] == 'OXAUSER' || Roles::GetALL()) {
            return 1;
        }

        $winCacheResult = \Helpers\Cache\Cache::surchargeGetUcache($_SESSION['Session_Login'].(new ParseBase1())->getBroker());

        if (!isset($winCacheResult[$droit])) {
            /**
             * TODO BBA : Attention Maxime ca ne gère pas bien les droit
             */
            // if (isset($_SESSION['DROIT'][$droit]) && $_SESSION['Session_Login'] == $user) {
            //     return $_SESSION['DROIT'][$droit];
            // }
            
            $req= "SELECT case when exists
                (select COD_DR from DROITUSR WITH (NOLOCK) where COD_USR = :user_0 AND COD_DR=:droit_0
                union
                select dg.COD_GRP from DROITGRP dg WITH (NOLOCK)
                inner join GRPUSR g WITH (NOLOCK) on g.COD_GRP=dg.COD_GRP AND g.COD_USR = :user_1
                where dg.COD_DR = :droit_1)
                then 1
                else 0
                end as DROIT";
        
            $param = $pdo->prepare($req);
            $param->execute([
                ':user_0' => $user,
                ':droit_0' => $droit,
                ':user_1' => $user,
                ':droit_1' => $droit,
            ]);
            
            $winCacheResult[$droit] = $requete = $param->fetch()['DROIT'] ?? '';

            
            /**
             * TODO BBA : Attention Maxime ca ne gère pas bien les droit
             */
            // if ($_SESSION['Session_Login'] == $user) {
            //     $_SESSION['DROIT'][$droit] = $requete;
            // }
            
            \Helpers\Cache\Cache::surchargeSetUcache($_SESSION['Session_Login'].(new ParseBase1())->getBroker(), $winCacheResult);
            
            return $requete;
        } else {
            return $winCacheResult[$droit];
        }
    }
    
    /**
     * @param array<mixed> $listRightCode
     * @return array<mixed>
     */
    public static function droitsUtilMulti(\PDO $pdo, array $listRightCode)
    {
        $res = [];
        foreach ($listRightCode as $code) {
            $res[ $code ] = self::droitsUtilisateur($pdo, $code);
        }
        return $res;
    }
        
    /**
     * retourne la valeur d'une session
     *
     * @param string $nomValeur
     * @return boolean
     */
    // phpcs:ignore
    public static function GetValeurSession($nomValeur)
    {
        return array_key_exists($nomValeur, $_SESSION) && $_SESSION[$nomValeur];
    }
    
    /**
     * grpDroit
     *
     * @param  PDO $pdo
     * @param  string $codeGroupe
     * @param  string $user
     * @return bool
     */
    public static function grpDroit(PDO $pdo, string $codeGroupe, string $user)
    {
        $query = "SELECT 
            CASE 
                WHEN EXISTS
                    (
                        SELECT gu.COD_USR  
                        FROM GRPUSR gu WITH (NOLOCK)
                            LEFT JOIN GRPDROIT gd WITH (NOLOCK) ON gd.COD_GRP = gu.COD_GRP
                        WHERE gu.COD_GRP = :COD_GRP
                            AND gu.COD_USR = :USER
                    )
                THEN 1
                ELSE 0
            END AS DROIT";

        $params = [
            ':COD_GRP'  => $codeGroupe,
            ':USER'     => $user
        ];
        
        $data = $pdo->prepare($query);

        $data->bindParam(':COD_GRP', $params[':COD_GRP'], PDO::PARAM_STR);
        $data->bindParam(':USER', $params[':USER'], PDO::PARAM_STR);

        $data->execute();

        $data = $data->fetch(PDO::FETCH_ASSOC);

        return $data['DROIT'];
    }
    
    /**
     * isUpperHierarchy
     * retourne la liste des subalternes d'un utilisateur donné, tableau vide si utilisateur supérieur de personne
     *
     * @param  PDO $pdo
     * @param  string $user
     * @return array<mixed>
     */
    public static function isUpperHierarchy(PDO $pdo, string $user)
    {
        $query = "SELECT NOM, CODE
        FROM HASTUTIL WITH (NOLOCK)
        WHERE SUPHIER = :USER";

        $params = [
            ':USER'     => $user
        ];
        
        $data = $pdo->prepare($query);

        $data->bindParam(':USER', $params[':USER'], PDO::PARAM_STR);

        $data->execute();

        $data = $data->fetchAll(PDO::FETCH_ASSOC);

        if ($data) {
            return $data;
        } else {
            return [];
        }
    }

    public static function isAdminCentral(PDO $pdo, string $user): bool
    {
        $query = "SELECT ADMCENTR
        FROM HASTUTIL WITH (NOLOCK)
        WHERE CODE = :USER";

        $params = [
            ':USER'     => $user
        ];
        
        $data = $pdo->prepare($query);

        $data->bindParam(':USER', $params[':USER'], PDO::PARAM_STR);

        $data->execute();

        $data = $data->fetch(PDO::FETCH_ASSOC);

        if (Sql::toBool($data['ADMCENTR'])) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Undocumented function
     *
     * @param bool $withoutExist
     * @return string
     */
    public static function getClausePerimetreSocieteBR(bool $withoutExist = false) : string
    {
        $user = new User();
        if ($user->getUserMultiSoc()) {
            return '';
        }
        
        $req = "";
        
        if ($withoutExist === false) {
            $req .= " AND EXISTS (";
        }

        $req .= "  SELECT SOCIETE.CODE_STE
            FROM SOCIETE WITH (NOLOCK)
            LEFT JOIN SOC_USR WITH (NOLOCK) ON SOC_USR.COD_STE = SOCIETE.CODE_STE AND SOC_USR.COD_USR = '".$_SESSION["Session_Login"]."'
            LEFT JOIN HASTUTIL WITH (NOLOCK) ON HASTUTIL.CODE_STE = SOCIETE.CODE_STE AND HASTUTIL.CODE = '".$_SESSION["Session_Login"]."'
            WHERE (SOC_USR.COD_USR IS NOT NULL OR HASTUTIL.CODE IS NOT NULL)
                AND (SOCIETE.DTEVALMIN = '00000000' OR SOCIETE.DTEVALMIN <= '".date('Ymd')."')
                AND (SOCIETE.DTEVALMAX = '00000000' OR SOCIETE.DTEVALMAX >= '".date('Ymd')."') ";

        if ($withoutExist=== false) {
            $req .= " ) ";
        } else {
            $req .= "  ";
        }

        return $req;
    }

    /**
     * Undocumented function
     *
     * @param string $linkTab
     * @param array<mixed> $arrayReq
     * @return string
     */
    public static function getClausePerimetreSociete($linkTab, &$arrayReq) : string
    {
        $user = new User();
        if ($user->getUserMultiSoc()) {
            return '';
        }

        $req = " AND EXISTS (
            SELECT SOCIETE.CODE_STE
            FROM SOCIETE WITH (NOLOCK)
            LEFT JOIN SOC_USR WITH (NOLOCK) ON SOC_USR.COD_STE = SOCIETE.CODE_STE AND SOC_USR.COD_USR = :objUserSoc1
            LEFT JOIN HASTUTIL WITH (NOLOCK) ON HASTUTIL.CODE_STE = SOCIETE.CODE_STE AND HASTUTIL.CODE = :objUserSoc2
            WHERE (SOC_USR.COD_USR IS NOT NULL OR HASTUTIL.CODE IS NOT NULL)
                AND (SOCIETE.DTEVALMIN = '00000000' OR SOCIETE.DTEVALMIN <= :_perim_now_0)
                AND (SOCIETE.DTEVALMAX = '00000000' OR SOCIETE.DTEVALMAX >= :_perim_now_1)
                AND SOCIETE.CODE_STE = ". Sql::qc($linkTab)."
        )";
        $arrayReq[':objUserSoc1'] = $user->getCodeUser();
        $arrayReq[':objUserSoc2'] = $user->getCodeUser();
        $arrayReq[':_perim_now_0'] = date('Ymd');
        $arrayReq[':_perim_now_1'] = date('Ymd');

        return $req;
    }

    /**
     * getClausePerimetreSociete for OwaDw
     *
     * @param string $linkTab
     * @param array<mixed> $arrayReq
     * @return string
     */
    public static function getClausePerimetreSocieteDw(string $linkTab, array &$arrayReq) : string
    {
        $user = new User();
        if ($user->getUserMultiSoc()) {
            return '';
        }

        $req = " AND EXISTS (
            SELECT PerimSoc.SOC_CODE_SOCIETE
            FROM SOCIETES as PerimSoc WITH (NOLOCK)
            LEFT JOIN SOCIETES_UTILISATEURS as PerimSocUsr WITH (NOLOCK) 
                ON PerimSocUsr.SUT_CODE_SOCIETE = PerimSoc.SOC_CODE_SOCIETE 
                AND PerimSocUsr.SUT_CODE_UTILISATEUR = :objUserSoc1
            LEFT JOIN UTILISATEURS as Util WITH (NOLOCK) 
                ON Util.USR_CODE_SOCIETE = PerimSoc.SOC_CODE_SOCIETE 
                AND Util.USR_CODE_UTILISATEUR = :objUserSoc2
            WHERE (PerimSocUsr.SUT_CODE_UTILISATEUR IS NOT NULL OR Util.USR_CODE_UTILISATEUR IS NOT NULL)
                AND (PerimSoc.SOC_DATE_DEBUT IS NULL OR PerimSoc.SOC_DATE_DEBUT <= :_perim_now_0)
                AND (PerimSoc.SOC_DATE_FIN IS NULL OR PerimSoc.SOC_DATE_FIN >= :_perim_now_1)
                AND PerimSoc.SOC_CODE_SOCIETE COLLATE French_BIN = ". Sql::qc($linkTab)."
        )";
        $arrayReq[':objUserSoc1'] = $user->getCodeUser();
        $arrayReq[':objUserSoc2'] = $user->getCodeUser();
        $arrayReq[':_perim_now_0'] = date('Y-m-d');
        $arrayReq[':_perim_now_1'] = date('Y-m-d');

        return $req;
    }

    /**
     * @deprecated use getClauseSocieteOuvert2 instead
     */
    public static function getClauseSocieteOuvert(string $alias = ''): string
    {
        if ($alias) {
            $alias .= '.';
        }

        $req = " AND ({$alias}DTEVALMIN <= '".date('Ymd')."' AND ({$alias}DTEVALMAX = '00000000' or {$alias}DTEVALMAX >= '".date('Ymd')."')) ";

        return $req;
    }

    /**
     * @param array<mixed> $param
     */
    public static function getClauseSocieteOuvert2(string $alias, array &$param): string
    {
        if ($alias) {
            $alias .= '.';
        }

        $req = " AND ({$alias}DTEVALMIN <= :_clause_socouv_now_0 AND ({$alias}DTEVALMAX = '00000000' or {$alias}DTEVALMAX >= :_clause_socouv_now_1)) ";
        $param[':_clause_socouv_now_0'] = date('Ymd');
        $param[':_clause_socouv_now_1'] = date('Ymd');
        return $req;
    }

    public static function getSelectSocieteOuvert(string $alias = ''):string
    {
        if ($alias) {
            $alias .= '.';
        }

        $req = "CASE WHEN 
                    (
                        {$alias}DTEVALMIN <= '".date('Ymd')."'
                        AND ({$alias}DTEVALMAX = '00000000' or {$alias}DTEVALMAX >= '".date('Ymd')."')
                    ) then 1
                else 0
                end STATUT_SOC";

        return $req;
    }
    
    public static function p2pAcces(PDO $pdo, Router $router, ContainerInterface $container): bool
    {
        if (isset($_SESSION['DROIT']['P2P'])) {
            return $_SESSION['DROIT']['P2P'];
        }

        $additional = new Additional($pdo, $router);
        $s2c = new P2P($additional);
        $action = $s2c->getListeAction($router, $container, $pdo);

        $_SESSION['DROIT']['P2P'] = $action? true:false;
        return $_SESSION['DROIT']['P2P'];
    }

    public static function s2cAccess(PDO $pdo, Router $router, ContainerInterface $container): bool
    {
        if (isset($_SESSION['DROIT']['S2C'])) {
            return $_SESSION['DROIT']['S2C'];
        }

        $additional = new Additional($pdo, $router);
        $s2c = new S2C($additional);
        $action = $s2c->getListeAction($router, $container, $pdo);

        $_SESSION['DROIT']['S2C'] = $action? true:false;
        return $_SESSION['DROIT']['S2C'];
    }

    public static function rfAccess(PDO $pdo, Router $router, ContainerInterface $container) : bool
    {
        // if (isset($_SESSION['DROIT']['RF'])) {
        //     return $_SESSION['DROIT']['RF'];
        // }

        $additional = new Additional($pdo, $router);
        $s2c = new RelationFournisseur($additional);
        $action = $s2c->getListeAction($router, $container, $pdo);
        
        $_SESSION['DROIT']['RF'] = $action? true:false;
        return $_SESSION['DROIT']['RF'];
    }


    public static function paAccess(PDO $pdo, Router $router, ContainerInterface $container): bool
    {
        if (isset($_SESSION['DROIT']['PA'])) {
            return $_SESSION['DROIT']['PA'];
        }

        $additional = new Additional($pdo, $router);
        $s2c = new PilotageAchat($additional);
        $action = $s2c->getListeAction($router, $container, $pdo);

        $_SESSION['DROIT']['PA'] = $action? true:false;
        return $_SESSION['DROIT']['PA'];
    }

    public static function getTypeAdmin() :string
    {
        if ($_SESSION['PROFIL'] == 'responsable') {
            return 'responsable';
        }
        if ($_SESSION['AdmCentral']) {
            return 'centrale';
        }
        if ($_SESSION['AdmLocal']) {
            return 'locale';
        }
        return '';
    }

    

    public static function isAdmCentral() :bool
    {
        return $_SESSION['AdmCentral'];
    }

    public static function isAdmLocal() :bool
    {
        return $_SESSION['AdmLocal'];
    }
    
    public static function isAdmLocalOnly() :bool
    {
        return Roles::isAdmLocal() && ! Roles::isAdmin();
    }

    public static function isAdmin() :bool
    {
        return $_SESSION['AdmCentral'] || $_SESSION['AdmLocal'];
    }

    public static function isSuperieurHierarchique() :bool
    {
        $modeBackup = $_SESSION['MODE_BACKUP']??false;
        return (! $modeBackup && $_SESSION['SuperieurHierarchique'])
            || ($modeBackup && $_SESSION['TYPE_BACKUP_RESP']);
    }
}
