<?php

namespace Helpers\Outil;

use Entity\Model\TypeTVA;
use Helpers\Fichier\Fichier;

use Helpers\Log\LogSysteme;

use Helpers\Session\ParseBase1;
use Modules\Ajax\Repository\Listes;
use Modules\Evaluation\Repository\Question;
use Entity\Entity;
use Entity\Model\Unites;
use Helpers\Parametres\Constante;

class Outils
{

    public static function isJson(string $string) :bool
    {
        json_decode($string);
        return (json_last_error() == JSON_ERROR_NONE);
    }

    /**
     * @param mixed $array
     * @param mixed $xml
     */
    // phpcs:ignore
    public static function array_to_xml($array, &$xml) :void
    {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                if (!is_numeric($key)) {
                    $subnode = $xml->addChild($key);
                    \Helpers\Outil\Outils::array_to_xml($value, $subnode);
                } else {
                    \Helpers\Outil\Outils::array_to_xml($value, $subnode);
                }
            } else {
                $xml->addChild($key, htmlspecialchars($value, ENT_XML1, 'UTF-8'));
            }
        }
    }
    
    /**
     * arrayToXml
     *
     * @param  \SimpleXMLElement $node
     * @param  array<mixed> $array
     * @param  string $keyTmp
     * @return void
     */
    public static function arrayToXml(\SimpleXMLElement $node, array $array, string $keyTmp = '') : void
    {
        foreach ($array as $key => $value) {
            if (is_array(($value))) {
                if (!is_numeric($key)) {
                    $keyTmp = $key;
                }
                Outils::arrayToXml(
                    isset($value[0])
                        ?
                        $node
                        :
                        $node->addChild(
                            is_numeric($keyTmp)
                            ?
                            'item'
                            :
                            $keyTmp
                        ),
                    $value,
                    $keyTmp
                );
            } else {
                $node->addChild($key, $value);
            }
        }
    }

    
    /**
     * TODO BBA
     *  public static function array_to_xml($data, &$xml_data) {
            foreach( $data as $key => $value ) {
                if( is_array($value) ) {
                    if( is_numeric($key) ){
                        $key = $key; //dealing with <0/>..<n/> issues
                    }
                    $subnode = $xml_data->addChild($key);
                    \Helpers\Outil\Outils::array_to_xml($value, $subnode);
                } else {
                    $xml_data->addChild("$key",htmlspecialchars("$value"));
                }
             }

    }
     */
    
    public static function heureConverte(string $heure, bool $seconde = true) :string
    {
        $hour=substr($heure, 0, 2);
        $minute=substr($heure, 2, 2);
        
        if ($seconde) {
            $seconde=substr($heure, 4, 2);
        }
        
        $hourReturn = $hour.':'.$minute.($seconde? (':'.$seconde):'');
        
        return $hourReturn;
    }
    
    /**
     * @param mixed $body
     * @param mixed $arrayValue
     * @param string $modeSplit
     * @return mixed
     */
    public static function replaceVariable($body, $arrayValue, string $modeSplit = '[]')
    {

        if ($modeSplit == '[]') {
            $open = '[';
            $close = ']';
        } elseif ($modeSplit == '<>') {
            $open = '<';
            $close = '>';
        } elseif ($modeSplit == '{}') {
            $open = '{';
            $close = '}';
        } else {
            $open = '[';
            $close = ']';
        }

        while (1==1) {
            $start = strpos($body, $open);
            $end = strpos($body, $close);
            
            if ($start===false || $end===false) {
                break;
            }
            
            $replacement = $arrayValue[substr($body, $start+1, $end-$start-1)]??'';
            $body = substr_replace($body, $replacement, $start, $end-$start+1);
        }
        return $body;
    }
    
    /**
     * @param mixed $value
     */
    public static function isCheck(&$value) : bool
    {
        if (isset($value) && $value != '' && $value != '0') {
            $value = 1;
            return true;
        } else {
            $value = 0;
            return false;
        }
    }
    
    /**
     * Fonction twig permettant de convertir un code en libelle (code)
     * @param string $entity            : entity dans src\entity\...
     * @param string $libelle           : le nom de la colonne libelle (si elle n'est pas définie dans l'entity avec le getLibelle()
     * @param string $value             : code a convertir
     * @param boolean $afficherCode     : si on affiche le code ou pas
     * @param mixed $ajaxCode
     * @param array<mixed> $post
     * @param mixed $ajaxLibelle
     * @param mixed $convertAjax
     * @param mixed $pdo
     * @return string Libelle (Code)
     */
    // phpcs:ignore
    public static function convertLibelleGlobal(
        $pdo,
        $entity,
        $libelle = '',
        $value = null,
        $afficherCode = false,
        $convertAjax = false,
        $ajaxCode = null,
        $ajaxLibelle = null,
        $post = [],
        ?string $codeSte = null,
        ?string $tsDon = null,
    ) {
        $saveEntity = $entity;
        if ($entity == 'FournissPanier') {
            $entity = 'Fourniss';
        } elseif ($entity == 'CODGESTPANIER') {
            $entity = 'CODGEST';
        }

        $generatorEntity = "Entity\\Model\\".$entity;
        //TODO trad
        //TODO a corrigé les requete si trad = '' CF requete sous famille
        //if($entity == '')  MOTCLE / modeTransport

        $value = trim($value);
        
        if (empty($value)
            && $generatorEntity != TypeTVA::class // TypeTva can have '' as id
        ) {
            return '';
        }

        $valueTMP = $value;
        $value = strtoupper($value);
        
        if (strtoupper($entity) == 'ARTICLES') {
            $liste = new Listes($pdo, true);
            $Articles = $liste->listeArticles(['egal_CODE_ART' => $value]);
            
            $return = $Articles[0]['DESIGN']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($Articles[0]['CODE_ART']??'').')';
            } elseif ($convertAjax && $Articles) {
                $return = $Articles[0]['CODE_ART']."$$".$Articles[0]['DESIGN'];
            }
        } elseif (strtoupper($entity) == 'FAMILLE') {
            $liste = new Listes($pdo, true);
            $row = $liste->famille(['CODE_FAM' => $value]);
            
            $return = $row[0]['DESIGNAT']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['CODE_FAM']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['CODE_FAM']."$$".$row[0]['DESIGNAT'];
            }
        } elseif (strtoupper($entity) == 'SOUSFAMILLE') {
            $liste = new Listes($pdo, true);
            $row = $liste->Sousfamille(['egal_CODE_SFA' => $value]);
            
            $return = $row[0]['DESIGNAT']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['CODE_SFA']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['CODE_SFA']."$$".$row[0]['DESIGNAT'];
            }
        } elseif (strtoupper($entity) == 'MODELIVR') {
            $liste = new Listes($pdo, true);
            $row = $liste->modeLivraison(['CODE_MDL' => $value]);
            
            $return = $row[0]['LIBELLE']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['CODE_MDL']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['CODE_MDL']."$$".$row[0]['LIBELLE'];
            }
        } elseif (strtoupper($entity) == 'MODEPAIE') {
            $liste = new Listes($pdo, true);
            $row = $liste->modePaiement(['CODE_MDP' => $value]);
            
            $return = $row[0]['LIBELLE']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['CODE_MDP']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['CODE_MDP']."$$".$row[0]['LIBELLE'];
            }
        } elseif (strtoupper($entity) == 'TYPEACHAT') {
            $liste = new Listes($pdo, true);
            $row = $liste->typeAchat(['TYP_ACH' => $value]);
            
            $return = $row[0]['LIB_TAC']??'';
           
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['TYP_ACH']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['TYP_ACH']."$$".$row[0]['LIB_TAC'];
            }
        } elseif (strtoupper($entity) == 'MOD_TRS') {
            $liste = new Listes($pdo, true);
            $row = $liste->getModeTransportTrad($value);
            
            $return = $row[0]['MOD_TRS_TRAD']??'';
            
            if ($afficherCode && $return!='') {
                $return .= ' ('.($row[0]['MOD_TRS']??'').')';
            } elseif ($convertAjax && $row) {
                $return = $row[0]['MOD_TRS']."$$".$row[0]['MOD_TRS_TRAD'];
            }
        } elseif (strtoupper($entity) == 'CODGEST' || strtoupper($saveEntity) == 'CODGESTPANIER') {
            /** @var Entity $entity */
            $entity = new $generatorEntity($pdo);

            $filterFind = [];
            if ($post['SI']) {
                $filterFind = [
                    'CODE_SI' => $post['SI'],
                ];
            }

            $contents = $entity->find(['CODE_AFF' => $valueTMP]+$filterFind);

            if (!$contents) {
                $contents = $entity->find(['CODE_GES' => $valueTMP]+$filterFind);
            }

            $cgParId = \Helpers\Outil\Roles::droit($pdo, 'CODE_GESTION_PAR_ID')? 1:0;

            $return = ($cgParId && strtoupper($saveEntity) == 'CODGEST')?
                ($contents['CODE_GES']??'')."$$".($contents['LIB_GES'].'('.$contents['CODE_AFF'].')') :
                ($contents['CODE_AFF']??'')."$$".($contents['LIB_GES']??'');
        } elseif (strtoupper($entity) == 'CAMP_QST_Q') {
            $repo = new Question($pdo);
            $questionData = \explode('~~', $valueTMP);
            $label = $repo->getParentQuestionId((int)$questionData[0], $questionData[1], $questionData[2]);
            $return = $label['LIB_QUEST'] . ' (' . $label['LIB_THEME'] . ')';
        } else {
            $saveEntity = $entity;

            $arrayAxesSecto = [
                'SECTIMPU' => Roles::droit($pdo, 'SISECTOR', 'PARAMSTE')? 'CODE_STE':null,
                'SSCPTANA' => Roles::droit($pdo, 'SCASECTO', 'PARAMSTE')? 'CODE_STE':null,
                'CODECOMP' => Roles::droit($pdo, 'CDCSECTO', 'PARAMSTE')? 'CODE_STE':null,
            ];
            $rowSte = $arrayAxesSecto[strtoupper($entity)]??null;
            
            /** @var Entity $entity */
            $entity = new $generatorEntity($pdo);

            if ($rowSte && $codeSte) {
                $contents = $entity->find([
                    'UPPER_'.$entity->getPrimaryKey()    => $valueTMP,
                    $rowSte                     => $codeSte
                ]+($tsDon? ['TYPEDICO' => $tsDon]:[]));
            } else {
                $contents = $entity->find(['UPPER_'.$entity->getPrimaryKey() => $valueTMP], [], $tsDon? ['filter_egal_TYPEDICO' => $tsDon]:[]);
            }

            if ($saveEntity == 'TVA' && $contents[$entity->getPrimaryKey()] == '.00') {
                $contents[$entity->getPrimaryKey()] = '0.00';
            }
            
            $return = '';
            
            if ($convertAjax && $contents) {
                if ($entity->getLibelle() && $entity->getPrimaryKey()) {
                    $return = ($contents[$entity->getPrimaryKey()]??'')."$$".($contents[$entity->getLibelle()]??'');
                } else {
                    $return = ($contents[$ajaxCode]??'')."$$".($contents[$ajaxLibelle]??'');
                }
            } else {
                if ($entity->getLibelle()) {
                    $return =  $contents[$entity->getLibelle()] ?? '';
                }
                if ($libelle && ($contents[$libelle] ?? '')) {
                    $return =  $contents[$libelle];
                }
                
                if ($afficherCode && $entity->getPrimaryKey() && $contents) {
                    $return .= ' ('.$contents[$entity->getPrimaryKey()].')';
                }
            }
            
            if (!$contents) {
                $return = $valueTMP.'$$'.$valueTMP;
            }
        }

        return $return;
    }
    
    /**
     * getHeaderByFile
     *
     * @param  string $file
     * @return void
     */
    public static function getHeaderByFile(string $file)
    {
        
        $extention = strtoupper(pathinfo($file, PATHINFO_EXTENSION));

        switch ($extention) {
            case 'PDF':
                header('Content-Type: application/pdf');
                break;
            case 'PNG':
                header('Content-Type: image/png');
                break;
            case 'JPG':
                header('Content-Type: image/jpeg');
                break;
            case 'JPEG':
                header('Content-Type: image/jpeg');
                break;
            case 'HTML':
                header('Content-Type: text/html');
                break;
            default:
                header('Content-Type: application/x-download');
                break;
        }
    }

    /**
     * @return bool true is https is used by the main HTTP request
     */
    public static function isHttps() :bool
    {
        return (
            isset($_SERVER['HTTPS'])
            && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)
        ) || (
            isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
            && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
        );
    }

    /**
     * @return string enum 'https://' | 'http://'
     */
    public static function getPreferredProtocol() :string
    {
        if (self::isHttps()) {
            return 'https://';
        }
        return 'http://';
    }

    public static function getBrokerPrefix() :string
    {
        return (new ParseBase1())->getBroker()=='1' ? '' : ((new ParseBase1())->getBroker());
    }

    /**
     * @return string
     */
    public static function getHost(bool $modeCurl = false) :string
    {
        if (strpos((new ParseBase1())->getServer(), 'oxacloud.oxalys.fr') !== false && $modeCurl) {
            return (new ParseBase1())->getServer();
        }
        return $_SERVER['SERVER_NAME'];
    }

    /**
     * @return string
     */
    public static function getRootUrl(bool $modeCurl = false) :string
    {
        return self::getPreferredProtocol() . self::getHost($modeCurl);
    }

    /**
     * @param string|float|null $qte
     * @param string|null $unite
     */
    public static function qteByUnite(\PDO $pdo, $qte, $unite) : string
    {
        $value = '0';
        if (!empty($qte)) {
            $value = str_replace(',', '.', (string)$qte);

            if (!is_numeric($value)) {
                return (string)$qte;
            }
        }

        return number_format(
            (float)$value,
            self::getUniteDecimal($pdo, $unite),
            '.',
            ''
        );
    }

    public static function getUniteDecimal(\PDO $pdo, ?string $unite) :int
    {
        $decimal = Constante::qteDecimal;
        if (!empty($unite)) {
            return intval(
                (new Unites($pdo))->find($unite)['NB_DECIM'] ?? $decimal
            );
        }
        return $decimal;
    }

    /**
     * @param mixed $value
     */
    public static function formatMontant($value) :string
    {
        return FloatHelper::format($value, Constante::montantDecimal);
    }

    /**
     * @param mixed $value
     * @return float
     */
    public static function formatMontantExcel($value)
    {
        $prixDeBase = str_replace(',', '.', (string) $value);
        
        if (!is_numeric($prixDeBase)) {
            return 0.0;
        }
        if (! $prixDeBase) {
            return 0.0;
        }
        return floatval(number_format(
            (float)$prixDeBase,
            Constante::montantDecimal,
            '.',
            ''
        ));
    }

    /**
     * @param mixed $value
     * @return float
     */
    public static function formatPrixUnitaireExcel($value) :float
    {
        if (!$value) {
            return 0.0;
        }

        return floatval(number_format((float)$value, Constante::PUDECIMAL, '.', ''));
    }

    /**
     * @param mixed $value
     */
    public static function formatPrixUnitaire($value) :string
    {
        if (!$value) {
            $value = '0';
        }
        
        return number_format((float)$value, Constante::PUDECIMAL, '.', ' ');
    }

    /**
     * Destroy PHP (and its cookie)
     * @return void
     */
    public static function sessionDestroy()
    {
        $param = session_get_cookie_params();
        setcookie(
            (string)session_name(),
            "",
            0,
            $param['path'],
            $param['domain'],
            $param['secure'],
            $param['httponly']
        );
        session_destroy();
    }

    public static function buildPath(string $urlPDF):string
    {
        if (substr($urlPDF, -1) != '/') {
            $urlPDF .='/';
        }

        if (strpos($urlPDF, '%') !== false) {
            $img =  explode('%', $urlPDF);
            $imageACharger = ($_SESSION['base1'][$img[1]]??'') . str_replace("/", '\\', $urlPDF);
            $urlPDF = str_replace('%'.$img[1].'%', '', $imageACharger);
        }

        return $urlPDF;
    }
}
