<?php

namespace Modules\API\APIInterne\OxaMobility\Outil;

use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Fichier\Fichier;
use Helpers\Fichier\Gestion_Fic_PJ;
use Helpers\Trad\Trad;
use Modules\GlobalApplication\Repository\DocumentsRattaches;

class DocAtt
{
    /** @var mixed $trad */
    private $trad;

    /** @var DocumentsRattaches $documentsRattaches */
    private DocumentsRattaches $documentsRattaches;

    /**
     * @var bool $hasError
     */
    private bool $hasError;

    /**
     * @var \PDO $pdo
     */
    private \PDO $pdo;

    /**
     * @param mixed $trad
     * @param \PDO $pdo
     */
    public function __construct($trad, \PDO $pdo)
    {
        $this->trad                 = $trad;
        $this->documentsRattaches   = new DocumentsRattaches($pdo);
        $this->hasError             = false;
        $this->pdo                  = $pdo;
    }

    /**
     * @param array<mixed> $return
     * @param array<mixed> $post
     * @param array<mixed> $authorizedKey
     * @return array<mixed>
     */
    public function hydrateDocumentFromMobility(&$return, $post = [], $authorizedKey = [])
    {
        if (count($post['ListeCreate']) > 0) {
            $this->treatDocToAdd($post, $authorizedKey, $return);
        }

        if (count($post['ListeDelete']) > 0) {
            $this->treatDocToDel($post, $return);
        }

        return $return;
    }

    /**
     * @param array<mixed> $post
     * @param array<mixed> $authorizedKey
     * @param array<mixed> $return
     * @return void
     */
    private function treatDocToAdd($post, $authorizedKey, &$return)
    {
        $stmtToAdd  = '';
        $paramsAdd  = [];
        $iParamsAdd = 1;
        $noOrdre    = null;

        $gestionFileFicPij = new Gestion_Fic_PJ($this->pdo);

        // On récupère en premier les fichiers à créer
        if ($post['ListeCreate'] && count($post['ListeCreate']) > 0) {
            if (is_null($noOrdre)) {
                $noOrdre = $this->documentsRattaches->getMaxNoOrdre($post['CodeTable'], ChampSupp::autoCompletCodeEnr($post['NumDoc']));
            }

            foreach ($post['ListeCreate'] as $docToCreate) {
                $diff = array_diff_key(array_flip($authorizedKey), $docToCreate);
                // On vérifie l'existence des tags à avoir obligatoirement dans chaque fichier
                if (count($diff) === 0) {
                    // On vérifie l'existence du fichier dans le dossier tmp
                    if (Fichier::fileExisteTmp($docToCreate['NomFichier'])) {
                        $newName = $gestionFileFicPij->insertFichier($docToCreate['NomFichier']);

                        $stmtToAdd .=
                            "(:noDA{$iParamsAdd}, {$noOrdre}, :newName{$iParamsAdd}, :nomAff{$iParamsAdd},"
                             ." :numDoc{$iParamsAdd}, :typePJ{$iParamsAdd}, :titre{$iParamsAdd}, :dtParut{$iParamsAdd},"
                             ." :auteur{$iParamsAdd}, 0x54), "
                        ;
                        $paramsAdd = array_merge($paramsAdd, [
                            'newName'.$iParamsAdd   => $newName,
                            'nomAff'.$iParamsAdd    => $docToCreate['NomFichierAff'],
                            'numDoc'.$iParamsAdd    => ChampSupp::autoCompletCodeEnr($post['NumDoc']),
                            'noDA'.$iParamsAdd      => $post['CodeTable'],
                            'typePJ'.$iParamsAdd    => "PJ",
                            'titre'.$iParamsAdd     => $docToCreate['NomFichierAff'],
                            'dtParut'.$iParamsAdd   => date('Ymd'),
                            'auteur'.$iParamsAdd    => $post['Utilisateur'],
                        ]);
                        $noOrdre++;
                    } else {
                        $return['ListeCreate'][] = [
                            'NoLigne' => $iParamsAdd,
                            'LibErreur' => $this->trad->t('Impossible de créer le document.')
                                .' '.$this->trad->t('Le fichier envoyé n\'a pas été trouvé sur le serveur.'),
                        ];
                        $this->hasError = true;
                    }
                } else {
                    $missingTag = implode(', ', array_keys($diff));
                    $return['ListeCreate'][] = [
                        'NoLigne' => $iParamsAdd,
                        'LibErreur' => Trad::strBuild(
                            $this->trad->t('Le(s) tag(s) suivant(s) est/sont manquant(s) : @1@'),
                            $missingTag
                        ),
                    ];
                }
                $iParamsAdd++;
            }

            if ($stmtToAdd !== '') {
                $stmtToAdd = substr($stmtToAdd, 0, -2).';';
            }
        }

        $this->documentsRattaches->createDocumentRattachesFromMobility($stmtToAdd, $paramsAdd);
    }

    /**
     * @param array<mixed> $post
     * @param array<mixed> $return
     * @return void
     */
    private function treatDocToDel($post, &$return)
    {
        $stmtToDel = '';
        // On récupère la liste des fichiers à supprimer
        if ($post['ListeDelete'] && count($post['ListeDelete']) > 0) {
            foreach ($post['ListeDelete'] as $docToDelete) {
                $stmtToDel .= " {$docToDelete['NoOrdre']},";
            }

            $stmtToDel = substr($stmtToDel, 1, -1);
        }

        $paramsGetDocAtt = [
            'codeTable' => $post['CodeTable'],
            'numDoc'    => $post['NumDoc']
        ];

        $listeToDelete      = $this->documentsRattaches->getDocumentRattaches($stmtToDel, $paramsGetDocAtt);
        $stmtDeleteMemo     = '';
        $stmtDeleteDocAtt   = '';
        $paramsDeleteDocAtt = [];

        $iFile = 1;
        foreach ($listeToDelete as $item) {
            if (Fichier::fileExistPj($item['NOM_FIC'])) {
                if ($item['NM_COMM'] !== 0) {
                    $stmtDeleteMemo .= " {$item['NM_COMM']},";
                }

                $stmtDeleteDocAtt .= " OR (NO_DA = :noDa{$iFile} AND NO_ORDRE = :noOrdre{$iFile} AND cast(COD_ENR as int) = :codEnr{$iFile}) ";

                $paramsDeleteDocAtt = array_merge($paramsDeleteDocAtt, [
                    'noDa'.$iFile => $item['NO_DA'],
                    'noOrdre'.$iFile => $item['NO_ORDRE'],
                    'codEnr'.$iFile => ChampSupp::autoCompletCodeEnr($item['COD_ENR'])
                ]);

                Fichier::deleteFichierPj($item['NOM_FIC']);
            } else {
                $return['ListeDelete'][] = [
                    'NoLigne' => $iFile,
                    'LibErreur' => $this->trad->t('Impossible de supprimer le document : il n\'a pas été trouvé sur le serveur.'),
                ];
                $this->hasError = true;
            }
            $iFile++;
        }

        $stmtDeleteMemo     = !empty($stmtDeleteMemo) ? substr($stmtDeleteMemo, 1, -1).';' : $stmtDeleteMemo;
        $stmtDeleteDocAtt   = !empty($stmtDeleteDocAtt) ? substr($stmtDeleteDocAtt, 3, -1).';' : $stmtDeleteDocAtt;

        $this->documentsRattaches->deleteMemosAndDoc($stmtDeleteMemo, $stmtDeleteDocAtt, $paramsDeleteDocAtt);
    }

    /**
     * @return bool
     */
    public function hasError()
    {
        return $this->hasError;
    }
}
