<?php

namespace Modules\DemandeAchat\Service;

use Entity\Model\Acccadre;
use Entity\Model\Centre;
use Entity\Model\Codgest;
use Entity\Model\Contfour;
use Entity\Model\CtcCtr;
use Entity\Model\DaEntet;
use Entity\Model\DaEvent;
use Entity\Model\Fourniss;
use Entity\Model\Hastutil;
use Entity\Model\Langues;
use Entity\Model\Marches;
use Entity\Model\Paramnum;
use Entity\Model\Paravrac;
use Entity\Model\Sectimpu;
use Exception;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Trad\ITrad;
use Modules\Ajax\Repository\Listes;
use Modules\DemandeAchat\Outil\CalculDateLivraison;
use Modules\DemandeAchat\Repository\CreationDemandeAchat;
use Modules\GlobalApplication\Repository\LicenceOxalys;
use Modules\GlobalApplication\Repository\Numerotation;
use Skeleton\Router;

class CreationDemandeAchatService
{
    private \PDO $pdo;
    private ITrad $trad;

    /**
     * __construct
     *
     * @param  \PDO $pdo
     * @param  ITrad $trad
     * @return void
     */
    public function __construct(\PDO $pdo, ITrad $trad)
    {
        $this->pdo = $pdo;
        $this->trad = $trad;
    }

    /**
     * getCreationParams
     *
     * @param  array<mixed> $post
     * @return array<mixed>
     */
    public function getCreationParams(array &$post): array
    {
        $params = [];
        $paramNum = new Paramnum($this->pdo);
        $params['SECTNUMDA'] = Roles::droit($this->pdo, 'SECTNUMDA');
        if ($params['SECTNUMDA'] == 'O') {
            $paramNum = $paramNum->find([
                'CLE' => 'DA',
                'CODE_STE' => $post['CODE_STE'] ?? $_SESSION['Session_SocUsr'],
            ])['MODE_NUM'] ?? null;
        } else {
            $paramNum = $paramNum->getNodeNum('DA');
        }

        $params['NO_DA_ACTIF'] = ($paramNum == 'M' || $paramNum == 'I');
        $params['NO_DA_OBLIG'] = ($paramNum == 'M');

        /* affichage type d'achat marchés publics */
        $params['TYPEACHAT_ACTIF'] = (Sql::paravrac($this->pdo, 'PARAMGEN', 'CTRLSEUILPARSFA') == 'O');

        /* affichage Notation commande */
        $params['NOCDISDA_ACTIF'] = (new LicenceOxalys($this->pdo))->noteFourActive();

        /* affichage des langues de la DA */
        $params['LANGUE_ACTIF'] = (Sql::paravrac($this->pdo, 'PARAMOXA', 'MULTILNGACTIF') == 'O');

        $params['LOCK_CTR_LIV'] = false;
        $params['CTR_EMET_LOCK'] = false;

        /* affichage Mode de transport */
        $params['MOD_TRS_ACTIF'] = (new LicenceOxalys($this->pdo))->expeditionActive();
        $params['OBLIG_MODTRS'] = false;
        
        $this->initTransport($post, $params);
        /* controle afin de voir si le champ mode transport est modifiable et mettre un mode de transport par defaut s'il n'existe pas */
        if ($post['CTR_LIV'] ?? '') {
            $deliveryCenter = (new Centre($this->pdo))
                ->find([
                    'LIVRAISON' => 'T',
                    'CODE_CTR' => $post['CTR_LIV'],
                    'CODE_STE' => $post['CODE_STE']
                ]);

            if (Sql::boolSql($deliveryCenter['TRS_INTER'])) {
                $params['MODIF_MODTRS'] = true;
                $params['OBLIG_MODTRS'] = true;

                if (empty($post['MOD_TRS']) || $post['MOD_TRS'] == '') {
                    $post['MOD_TRS'] = $deliveryCenter['MOD_TRS'];
                }
            } else {
                $post['MOD_TRS'] = '';
            }
        } else {
            $post['MOD_TRS'] = '';
        }

        /* affichage et contrôles des axes d'imputations */
        $impConfig = (new Paravrac($this->pdo))
            ->getDemandeAxeImpConfig();
        $params['SI_ACTIF'] = $impConfig->SectImp->isActive;
        $params['CDC_ACTIF'] = $impConfig->CodeCompl->isActive;
        $params['SCA_ACTIF'] = $impConfig->SousCompteAna->isActive;

        $parametr = (new \Entity\Model\Parametr($this->pdo))->get();
        $params['MIN_SI_BLOQUANT'] = $parametr->CMIN_SIDA == 'B'
            ? 1
            : 0;
        $params['MAX_SI_BLOQUANT'] = $parametr->CMAX_SIDA == 'B'
            ? 1
            : 0;
        $params['MIN_CDC_BLOQUANT'] = $parametr->CMIN_CDDA == 'B'
            ? 1
            : 0;
        $params['MAX_CDC_BLOQUANT'] = $parametr->CMAX_CDDA == 'B'
            ? 1
            : 0;
        $params['MIN_SCA_BLOQUANT'] = $parametr->CMIN_SCDA == 'B'
            ? 1
            : 0;
        $params['MAX_SCA_BLOQUANT'] = $parametr->CMAX_SCDA == 'B'
            ? 1
            : 0;

        /* affichage du code gestion si actif pour le SI */
        $params['OBLIG_CODGES'] = false;

        if ($post['SECTIMP'] ?? '') {
            $codeSteSI = Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE')
                ? $post['CODE_STE']
                : '';

            $si = (new Sectimpu($this->pdo))
                ->find([
                    'CODE_SI' => $post['SECTIMP'],
                    'CODE_STE' => $codeSteSI
                ]);
            $params['MODIF_CODGES'] = Sql::boolSql($si['SICODG']);
            $params['OBLIG_CODGES'] = Sql::boolSql($si['IMPCODG']);
        }


        /* paramétrage nécessaire pour fournisseur */
        $params['OBLIG_FOU'] = false;
        if ($post['ACD'] ?? '') {
            $acd = (new Acccadre($this->pdo))
                ->find($post['ACD']);

            if ($acd['TYPE_FG'] == 'F') {
                $params['LOCK_FOU'] = true;
                $post['FOU'] = $acd['CODE_FOUR'];
                // vérification validité fournisseur
                $fourniss = (new Listes($this->pdo))
                    ->Fournisseur([
                        'filter_egal_CODE' => $acd['CODE_FOUR'],
                        'valide' => 1,
                        'filter_egal_PROSPECT' => $post['CHIF_EXEC'] == 'E'
                            ? 'F'
                            : ''
                    ]);

                if (count($fourniss) == 0) {
                    $post['FOU'] = '';
                }
            } else {
                $post['FOU'] = '';
                $params['ACD_FG'] = $post['ACD'];
            }
            $params['OBLIG_FOU'] = true;
            $params['messageCompl'] = ' ' . $this->trad->t('pour cet accord-cadre');
        }

        return $params;
    }
    
    /**
     * initTransport
     *
     * @param  array<mixed> $post
     * @param  array<mixed> $params
     * @return void
     */
    public function initTransport(&$post, &$params) : void
    {
        /* controle afin de voir si le champ mode transport est modifiable et mettre un mode de transport par defaut s'il n'existe pas */
        if ($post['CTR_LIV'] ?? '') {
            $deliveryCenter = (new Centre($this->pdo))
                ->find([
                    'LIVRAISON' => 'T',
                    'CODE_CTR' => $post['CTR_LIV'],
                    'CODE_STE' => $post['CODE_STE']
                ]);

            if (Sql::boolSql($deliveryCenter['TRS_INTER'])) {
                $params['MODIF_MODTRS'] = true;
                $params['OBLIG_MODTRS'] = true;
                $params['MOD_TRS_ACTIF'] = true;

                if (empty($post['MOD_TRS']) || $post['MOD_TRS'] == '') {
                    $post['MOD_TRS'] = $deliveryCenter['MOD_TRS'];
                }
            } else {
                $post['MOD_TRS'] = '';
            }
        } else {
            $post['MOD_TRS'] = '';
        }
    }

    /**
     * initPurchaseRequest
     *
     * @return array<mixed>
     */
    public function initPurchaseRequest() : array
    {
        $user = (new Hastutil($this->pdo))
            ->find($_SESSION['Session_Login']);

        $typDaDef = Sql::paravrac($this->pdo, 'PARAMGEN', 'TYPDADEF');

        $post = [
            'CODE_STE' => $_SESSION['Session_SocUsr'],
            'TYP_DOC' => Sql::paravrac($this->pdo, 'PARAMGEN', 'TYP_DOC_DEF'),
            'CHIF_EXEC' => ($typDaDef != '') ? $typDaDef : 'E',
            'TYPNMP' => Sql::paravrac($this->pdo, 'CTRLSESFA', 'TYPACHDEF'),
            'COD_LNG' => $user['COD_LNG'],
            'NO_DEM' => Sql::toBool($user['DEMAND'])
                ? $_SESSION['Session_Login']
                : '',
            'MODIF_STE' => 1,
        ];

        $impConfig = (new Paravrac($this->pdo))
            ->getDemandeAxeImpConfig();

        if ($impConfig->SectImp->isActive) {
            $post['SECTIMP'] = $user['SI'];
        }

        if ($impConfig->CodeCompl->isActive) {
            $post['CODECOMP'] = $user['CDC'];
        }

        if ($impConfig->SousCompteAna->isActive) {
            $post['SSCPTEANA'] = $user['SCA'];
        }

        return $post;
    }

    /**
     * getLanguages
     *
     * @return array<mixed>
     */
    public function getLanguages(): array
    {
        $data = (new Langues($this->pdo))
            ->fetchAll();

        $languages = [];

        foreach ($data as $value) {
            $languages[(string) str_replace(' ', '', $value['COD_LNG'])] = str_replace(' ', '', $value['LIBELLE']);
        }

        return $languages;
    }

    /**
     * getTransportOptions
     *
     * @return array<mixed>
     */
    public function getTransportOptions(): array
    {
        $transport = ['' => ''];

        $data = (new Listes($this->pdo, true))
            ->getModeTransportTrad();

        foreach ($data as $value) {
            $transport[$value['MOD_TRS']] = $value['MOD_TRS_TRAD'];
        }

        return $transport;
    }

    /**
     * createPurchaseRequestHeading
     *
     * @param  array<mixed> $post
     * @return array<mixed>
     */
    public function createPurchaseRequestHeading(array $post): array
    {
        // Suivant type de numérotation, si le N° est saisi sur l'écran de création, il est repris, sinon, appel à la fonction donne moi un numéro
        $params['SECTNUMDA'] = Roles::droit($this->pdo, 'SECTNUMDA');
        $paramNum = new Paramnum($this->pdo);
        if ($params['SECTNUMDA'] == 'O') {
            $paramNum = $paramNum->getNodeNum('DA', $post['CODE_STE'] ?? $_SESSION['Session_SocUsr']);
        } else {
            $paramNum = $paramNum->getNodeNum('DA');
        }

        $insertParams = [
            'NO_DA' => $post['NO_DA'] ?? '',
            'NO_DEM' => $post['NO_DEM'],
            'SECTIMP' => $post['SECTIMP'] ?? '',
            'CODECOMP' => $post['CODECOMP'] ?? '',
            'SSCPTEANA' => $post['SSCPTEANA'] ?? '',
            'FOU' => $post['FOU'],
            'DEVISE' => $_SESSION['parametrage']['DEVISE_BASE'],
            'DTE_EMISS' => date('Ymd'),
            'CTR_LIV' => $post['CTR_LIV'],
            'COND_PAIE' => '',
            'MODE_PAIE' => '',
            'MODE_LIV' => '',
            'CHIF_EXEC' => $post['CHIF_EXEC'],
            'TYP_DOC' => $post['TYP_DOC'],
            'CODE_STE' => $post['CODE_STE'],
            'ACD' => $post['ACD'],
            'MOD_TRS' => $post['MOD_TRS'] ?? '',
            'NOCDISDA' => $post['NOCDISDA'] ?? 'off' == 'on' ? Sql::boolSql2(true) : Sql::boolSql2(false),
            'ADRFOU' => '',
            'VILFOU' => '',
            'PAYSFOU' => '',
            'CTCT_FOU' => '',
            'TEL_CTCT' => '',
            'FAX_CTCT' => '',
            'POR_CTCT' => '',
            'EMA_CTCT' => '',
            'COD_LNG' => $post['COD_LNG'],
            'CODGES' => '',
            'LIBGES' => '',
            'CPFOU' => '',
            'VILLEFOU' => '',
            'ID_CG' => '',
            'NMCTC1L' => '',
            'FTCTC1L' => '',
            'TLCTC1L' => '',
            'FXCTC1L' => '',
            'PRCTC1L' => '',
            'MLCTC1L' => '',
            'ADRLIV' => '',
            'VILLIV' => '',
            'PAYSLIV' => '',
            'CPLIV' => '',
            'VILLELIV' => '',
            'DAENT_CENTRE_EMETTEUR' => $post['DAENT_CENTRE_EMETTEUR'],
            'UO_DEM' => (new Hastutil($this->pdo))
                ->find([
                    'CODE' => $post['NO_DEM']
                ], ['CODE_UO'])['CODE_UO']
        ];

        if ($paramNum == 'A'
            || ($paramNum == 'I' && empty($post['NO_DA']))
        ) {
            $insertParams['NO_DA'] = Numerotation::getNumeroReserver(
                $this->pdo,
                $post['CODE_STE'],
                'DA'
            );
        }

        if ($post['FOU']) {
            $supplierData = (new Fourniss($this->pdo))
                ->find([
                    'CODE' => $post['FOU']
                ]);

            $insertParams['ADRFOU'] = $supplierData['ADR'];
            $insertParams['VILFOU'] = $supplierData['VILLE'];
            $insertParams['PAYSFOU'] = $supplierData['CODE_PAYS'];
            $insertParams['CPFOU'] = $supplierData['CPOSTAL'];
            $insertParams['VILLEFOU'] = $supplierData['VILLE1'];
            $insertParams['DEVISE'] = $supplierData['DEVISE'];
            $insertParams['COND_PAIE'] = $supplierData['COND_PAIE'];
            $insertParams['MODE_PAIE'] = $supplierData['MODE_PAIE'];
            $insertParams['MODE_LIV'] = $supplierData['LIV'];

            $supplierContactData = (new Contfour($this->pdo))
                ->find([
                    'CODE_FOU' => $post['FOU']
                ]);

            if (!is_null($supplierContactData)) {
                $insertParams['CTCT_FOU'] = $supplierContactData['NOM'];
                $insertParams['TEL_CTCT'] = $supplierContactData['TEL'];
                $insertParams['FAX_CTCT'] = $supplierContactData['FAX'];
                $insertParams['POR_CTCT'] = $supplierContactData['TELPORT'];
                $insertParams['EMA_CTCT'] = $supplierContactData['EMAIL'];
            }
        }

        if ($post['ACD']) {
            $acdData = (new Acccadre($this->pdo))
                ->find([
                    'CODE_ACD' => $post['ACD']
                ])['MARCHE'];

            if ($marketData =
                (new Marches($this->pdo))
                    ->find([
                        'CODE' => $acdData['MARCHE'] ?? ''
                    ])
            ) {
                $insertParams['COND_PAIE'] = $marketData['CONDPAI'];
                $insertParams['MODE_PAIE'] = $marketData['MODEPAI'];
                $insertParams['MODE_LIV'] = $marketData['MODELIV'];
            }
        }

        if ($post['CODGES'] && $post['SECTIMP']) {
            $config = (new Paravrac($this->pdo))
                ->getDemandeAxeImpConfig($post['CODE_STE']);
            $codGestData = (new Codgest($this->pdo))
                ->find([
                    'CODE_SI' => $post['SECTIMP'],
                ] + (Roles::droit($this->pdo, 'CODE_GESTION_PAR_ID') ? [
                    'CODE_GES' => $post['CODGES']
                ] : [
                    'CODE_AFF' => $post['CODGES']
                ]) + ($config->SectImp->isSecto ? [
                    'CODE_STE' => $post['CODE_STE']
                ] : []));
            if (! empty($codGestData)) {
                $insertParams['LIBGES'] = $codGestData['LIB_GES'];
                $insertParams['ID_CG'] = $codGestData['CODE_GES'];
                $insertParams['CODGES'] = $codGestData['CODE_AFF'];
            }
        }

        $deliveryCenterData = (new Centre($this->pdo))
            ->find([
                'CODE_CTR' => $post['CTR_LIV']
            ]);

        $insertParams['ADRLIV'] = $deliveryCenterData['ADRESSE'];
        $insertParams['VILLIV'] = $deliveryCenterData['VILLE'];
        $insertParams['PAYSLIV'] = $deliveryCenterData['PAYS'];
        $insertParams['CPLIV'] = $deliveryCenterData['CPOSTAL'];
        $insertParams['VILLELIV'] = $deliveryCenterData['VILLE1'];

        $deliveryCenterContactData = (new CtcCtr($this->pdo))
            ->find([
                'COD_CTR' => $post['CTR_LIV'],
                'CTC_IND' => 0
            ]);

        $insertParams['NMCTC1L'] = $deliveryCenterContactData['CTC_NOM'] ?? '';
        $insertParams['FTCTC1L'] = $deliveryCenterContactData['CTC_FCT'] ?? '';
        $insertParams['TLCTC1L'] = $deliveryCenterContactData['CTC_TEL'] ?? '';
        $insertParams['FXCTC1L'] = $deliveryCenterContactData['CTC_FAX'] ?? '';
        $insertParams['PRCTC1L'] = $deliveryCenterContactData['CTC_GSM'] ?? '';
        $insertParams['MLCTC1L'] = $deliveryCenterContactData['CTC_MAIL'] ?? '';

        if ($post['ZONELIB'] != '') {
            $insertParams['ZONELIB'] = $post['ZONELIB'];
        }

        try {
            (new DaEntet($this->pdo))
                ->insert($insertParams);
        } catch (Exception $e) {
            return [
                'status' => 'E',
                'error' => $e->getMessage()
            ];
        }

        // Initialisation des champs supplémentaires d'entête de DA à partir du fournisseur, du type de document, du demandeur, du centre de livraison, en fonction des règles trouvées dans la table select * from CSPARINI where TAB_DESTI='DA_ENTET'
        $cs = new ChampSupp($this->pdo);
        $cs->copyDefault('DA_ENTET', $insertParams['NO_DA'], 'FOURNISS', $insertParams['FOU']);
        $cs->copyDefault('DA_ENTET', $insertParams['NO_DA'], 'TYPDOC', $insertParams['TYP_DOC']);
        $cs->copyDefault('DA_ENTET', $insertParams['NO_DA'], 'HASTUTIL', $insertParams['NO_DEM']);
        $cs->copyDefault('DA_ENTET', $insertParams['NO_DA'], 'CENTRE', $insertParams['CTR_LIV']);

        // on enregistre l'évènement de création dans les table évènement des CA
        (new DaEvent($this->pdo))->insertEntity(
            (int) $insertParams['NO_DA'],
            'DAC',
            $_SESSION['Session_Login'],
            // est-ce qu'on met un commentaire sur l'event de création de DA ?
            // ($type == 'A' ?
            //     $this->sql->updateMemo(
            //         $this->pdo,
            //         '',
            //         Trad::strBuild($this->trad->t('Annulation réception @1@'), $cancelledBrNumber)
            //     ) : '0'
            // )
        );

        Numerotation::deleteReserver($this->pdo, 'DA', $insertParams['NO_DA']);

        return [
            'status' => 'O',
            'NO_DA' => $insertParams['NO_DA']
        ];
    }
}
