<?php

namespace Paheko;
session_start();

use Paheko\Files\Files;
use Paheko\Entities\Files\File;
use Paheko\UserTemplate\UserTemplate;

use Paheko\Plugin\RecusFiscaux\Utils;
use Paheko\Plugin\RecusFiscaux\Personne;

// forcer mode dialog pour ouvrir le squelette des reçus dans un nouvel onglet
// à combiner avec target="_blank" ou target="_dialog" dans le fichier tpl
$_GET['_dialog'] = true;

// signature
$signature =
    (null !== $config->fileURL('signature')) ?
    $config->fileURL('signature') :
    ((null !== $plugin->getConfig('signature')) ?
     \KD2\HTTP::getScheme() . '://' . \KD2\HTTP::getHost() . WWW_URI . $plugin->getConfig('signature') :
     "");

// http://test.paheko.bzh/config/cavalier.png
error_log('signature = ' . $signature);
// logo
$config = Config::getInstance();
$logo_asso =
    (null !== $config->fileURL('logo')) ?
    $config->fileURL('logo') :
    "";

// articles du CGI
$articlesCGI = array();
foreach ($plugin->getConfig('articlesCGI') as $article) {
    if ($article->valeur == 1) {
        $articlesCGI[] = $article->titre;
    }
}
$nbArticles = count($articlesCGI);
if ($nbArticles == 1) {
    $texteArticles = 'à l’article ' . $articlesCGI[0];
} elseif ($nbArticles > 1) {
    $texteArticles = 'aux articles ';
    for ($i = 0; $i < $nbArticles; ++$i) {
        $texteArticles .= $articlesCGI[$i];
        if ($i < $nbArticles - 2) {
            $texteArticles .= ", ";
        } else if ($i == $nbArticles - 2) {
            $texteArticles .= " et ";
        }
    }
}

// libellés pour les taux de réduction
$libelles_taux = Utils::getLignesReduction($plugin->getConfig('reduction'));

// numérotation des reçus
$configNum = $plugin->getConfig('numerotation');

// filtrer les versements sélectionnés
$lesLignes = f('selected');
$versementsSelectionnes = array();
foreach ($lesLignes as $ligne) {
    $versementsSelectionnes[] = $_SESSION['lesVersements'][$ligne];
}

// cumuler les versements
if ($_GET['type'] == 'personne') {
    $totalPersonnes = cumulerVersementsPersonne($versementsSelectionnes);
} elseif ($_GET['type'] == 'activite') {
    $totalPersonnes = cumulerVersementsTarif($versementsSelectionnes);
}

// générer les reçus
if ($_GET['format'] == 'pdf') {
    genererRecusPDF($totalPersonnes,
                    $signature,
                    $logo_asso,
                    $texteArticles,
                    $plugin,
                    $configNum,
                    $libelles_taux
    );
} else if ($_GET['format'] == 'print') {
    generererRecusHTML($tpl,
                       $totalPersonnes,
                       $signature,
                       $logo_asso,
                       $texteArticles,
                       $plugin,
                       $configNum,
                       $libelles_taux
    );
} else {
    // Erreur : format inconnu ; ne devrait pas se produire
}

function genererRecusPDF($totalPersonnes,
                         $signature,
                         $logo_asso,
                         $texteArticles,
                         $plugin,
                         $configNum,
                         $libelles_taux
)
{
    // <TEST>
    $fichierHTML = sprintf('%s/print-%s.html', CACHE_ROOT, md5(random_bytes(16)));
    // </TEST>
    $listeFichiersPDF = array();
    $fmt = new \NumberFormatter('fr_FR', \NumberFormatter::SPELLOUT);
    $prefixeNum = getNumPrefixe($configNum);
    $numero_sequentiel = getNumSequentiel($configNum);
    foreach ($totalPersonnes as $idPersonne => $personne) {
        $tpl = new UserTemplate(null);
        /* $tpl->setSource(PLUGIN_ROOT . '/templates/recu.skel'); */
        $tpl->setSourcePath(PLUGIN_ROOT . '/templates/recu.skel');

        $tpl->assignArray(compact('signature', 'logo_asso', 'texteArticles'));
        $tpl->assign('objet_asso', $plugin->getConfig('objet_asso'));
        $tpl->assign('nom_responsable', $plugin->getConfig('nom_responsable'));
        $tpl->assign('fonction_responsable', $plugin->getConfig('fonction_responsable'));
        $tpl->assign('ville_asso', $plugin->getConfig('ville_asso'));
        $tpl->assign('nom', $personne->nomPrenom);
        $tpl->assign('adresse', $personne->adresse);
        $tpl->assign('code_postal', $personne->codePostal);
        $tpl->assign('ville', $personne->ville);
        $tpl->assign('date', date("j/m/Y"));

        // numéro de reçu
        $tpl->assign('numero',
                     faireNumeroRecu($prefixeNum,
                                     $configNum->membre,
                                     $personne->numero,
                                     $numero_sequentiel));

        // adresse de courriel
        if ($plugin->getConfig('imprimerCourriel')) {
            $courriel = $personne->courriel;
        } else {
            $courriel = "";
        }
        $tpl->assign('courriel', $courriel);

        // les versements
        $tpl->registerSection(
            'versements',
            function () use ($personne, $libelles_taux, $fmt) {
                foreach ($personne->versements as $taux => $versement) {
                    $ligne['montant'] = $versement->montant;
                    $ligne['euros'] = $fmt->format((int)($versement->montant / 100));
                    if ($versement->montant % 100 != 0) {
                        $ligne['cents'] = $fmt->format($versement->montant % 100);
                    } else {
                        $ligne['cents'] = "";
                    }
                    $ligne['libelle'] = $libelles_taux[$taux];
                    $ligne['dateMin'] = date("d/m/Y", $versement->dateMin);
                    $ligne['dateMax'] = date("d/m/Y", $versement->dateMax);
                    yield $ligne;
                }
            }
        );

        // mentions complémentaires
        $complements = mentionsComplémentaires();

        $tpl->registerSection(
            'informations',
            function () use ($complements) {
                foreach ($complements as $elem) {
                    yield (array) $elem;
                }
            }
        );

        // <TEST>
        // récupérer les reçus au format html
        $recuHTML = $tpl->fetch();
        // enregistrer dans le fichier
        file_put_contents($fichierHTML, $recuHTML, FILE_APPEND);
        // </TEST>

        // fabriquer le fichier PDF
        genererPDF($tpl->fetch(), $personne->nomPrenom, $listeFichiersPDF);
    }

    // afficher dans un dialog
    //marche pas
    // printf('
    //         <dialog id="dialog" open="" style="" class="loaded">
    //           <button class="icn-btn closeBtn" data-icon="✘" type="button">Fermer
    //           </button>
    //           <iframe src="%s" name="dialog" id="frameDialog" scrolling="yes" data-height="%s" style="height: %s;" width="0" height="0">
    //           </iframe>
    //         </dialog>
    //     ', $fichierHTML, "90%", "90%");

    // affiche une page vide
    // $link = "<script>window.open('$fichierHTML', '_blank')</script>";
    // echo $link;

    // faire une archive zip
    $fichierZip = Utils::makeArchive(
        $listeFichiersPDF,
        $_SESSION['annee_recu'],
        PLUGIN_ROOT . "/zip"
    );

    //supprimer les fichiers pdf
    // foreach ($listeFichiersPDF as $f) {
    //     \Paheko\Utils::safe_unlink($f);
    // }
} // genererRecusPDF

function generererRecusHTML($tpl,
                            $totalPersonnes,
                            $signature,
                            $logo_asso,
                            $texteArticles,
                            $plugin,
                            $configNum,
                            $libelles_taux
)
{
    $tpl->register_function('afficher_numero_recu', function($params)
    {
        $prefixeNum = $params['prefixe'];
        $membre = $params['membre'];
        $numero_personne = $params['numero_personne'];
        $numero_sequentiel = $params['numero_sequentiel'];
        $numero = faireNumeroRecu($prefixeNum,
                                  $membre,
                                  $numero_personne,
                                  $numero_sequentiel);
        $out = sprintf('
            <p class="important">Reçu %s</p>',
                       $numero
        );
        return $out;
    });

    $tpl->assign(compact(
        'totalPersonnes',
        'logo_asso',
        'signature',
        'libelles_taux',
        'texteArticles'
    ));
    $tpl->assign('prefixeNum', getNumPrefixe($configNum));
    $tpl->assign('membre', $configNum->membre);
    $tpl->assign('numero_sequentiel', getNumSequentiel($configNum));
    $tpl->assign('org_name', Config::getInstance()->get('org_name'));
    $tpl->assign('org_address', Config::getInstance()->get('org_address'));
    $tpl->assign('objet_asso', $plugin->getConfig('objet_asso'));
    $tpl->assign('courriel', $plugin->getConfig('imprimerCourriel'));
    $tpl->assign('complements', mentionsComplémentaires());
    $tpl->assign('ville_asso', $plugin->getConfig('ville_asso'));
    $tpl->assign('date', date("j/m/Y"));
    $tpl->assign('nom_responsable', $plugin->getConfig('nom_responsable'));
    $tpl->assign('fonction_responsable', $plugin->getConfig('fonction_responsable'));

    $tpl->assign('plugin_css', ['previs_recu.css', 'imprimer_recu.css']);
    $tpl->display(PLUGIN_ROOT . '/templates/recu_html.tpl');
} // generererRecusHTML

/**
 * Cumuler les versements de chaque personne
 * @param tableau des versements triés par idUser, date
 * @return tableau des versements cumulés : id => Personne
 */
function cumulerVersementsPersonne($versements)
{
    $totalPersonnes = array();
    $idPersonneCourant = -1;
    $dateMin = PHP_INT_MAX;
    $dateMax = -1;
    $totalVersements = 0;
    foreach ($versements as $ligne) {
        if ($ligne->idUser != $idPersonneCourant) {
            // changement de personne
            if ($idPersonneCourant != -1) {
                $totalPersonnes[$idPersonneCourant]->ajouterVersement(
                    $_SESSION['taux_reduction'],
                    $totalVersements,
                    $dateMin,
                    $dateMax
                );
            }
            $dateMin = strtotime($ligne->date);
            $dateMax = strtotime($ligne->date);
            $idPersonneCourant = $ligne->idUser;
            $totalVersements = $ligne->versement;
            // créer les infos de la personne, sauf si elle est déjà présente
            if (!array_key_exists($idPersonneCourant, $totalPersonnes)) {
                $totalPersonnes[$idPersonneCourant] = $_SESSION['membresDonateurs'][$ligne->idUser]->clone();
            }
        } else {
            // même personne : cumuler versements et mettre à jour les dates
            $totalVersements += $ligne->versement;
            if (strtotime($ligne->date) < $dateMin) {
                $dateMin = strtotime($ligne->date);
            }
            if (strtotime($ligne->date) > $dateMax) {
                $dateMax = strtotime($ligne->date);
            }
        }
    }
    // et le dernier
    $totalPersonnes[$idPersonneCourant]->ajouterVersement(
        $_SESSION['taux_reduction'],
        $totalVersements,
        $dateMin,
        $dateMax
    );
    return $totalPersonnes;
} // cumulerVersementsPersonne

/**
 * Cumuler les versements de chaque personne par tarif
 * @param tableau des versements triés par idTarif, idUser, date
 * @return tableau des versements cumulés : id => Personne
 */
function cumulerVersementsTarif($versements)
{
    $totalPersonnes = array();
    $idTarifCourant = -1;
    $idPersonneCourant = -1;
    $idCompteCourant = -1;
    $dateMin = PHP_INT_MAX;
    $dateMax = -1;
    $totalVersements = 0;
    foreach ($versements as $ligne) {
        if (
            $ligne->idTarif  != $idTarifCourant ||
            $ligne->idUser   != $idPersonneCourant ||
            $ligne->idCompte != $idCompteCourant
        ) {
            if ($idTarifCourant != -1) {
                // changement de tarif, de personne ou de compte
                $tarifCompte = ($idTarifCourant == 0) ?
                    $idCompteCourant :
                    $idTarifCourant . "_" . $idCompteCourant;
                $totalPersonnes[$idPersonneCourant]->ajouterVersement(
                    $_SESSION['tauxSelectionnes'][$tarifCompte],
                    $totalVersements,
                    $dateMin,
                    $dateMax
                );
            }
            $dateMin = strtotime($ligne->date);
            $dateMax = strtotime($ligne->date);
            $idTarifCourant    = $ligne->idTarif;
            $idPersonneCourant = $ligne->idUser;
            $idCompteCourant   = $ligne->idCompte;
            $totalVersements   = $ligne->versement;
            // créer les infos de la personne, sauf si elle est déjà présente
            if (!array_key_exists($idPersonneCourant, $totalPersonnes)) {
                $totalPersonnes[$idPersonneCourant] = $_SESSION['membresDonateurs'][$ligne->idUser]->clone();
            }
        } else {
            // même personne : cumuler versements et mettre à jour les dates
            $totalVersements += $ligne->versement;
            if (strtotime($ligne->date) < $dateMin) {
                $dateMin = strtotime($ligne->date);
            }
            if (strtotime($ligne->date) > $dateMax) {
                $dateMax = strtotime($ligne->date);
            }
        }
    }
    // et le dernier
    $tarifCompte = ($idTarifCourant == 0) ?
        $idCompteCourant :
        $idTarifCourant . "_" . $idCompteCourant;
    $totalPersonnes[$idPersonneCourant]->ajouterVersement(
        $_SESSION['tauxSelectionnes'][$tarifCompte],
        $totalVersements,
        $dateMin,
        $dateMax
    );
    return $totalPersonnes;
} // cumulerVersementsTarif

/**
 * génère un fichier PDF à partir d'un document html
 * ajoute son nom à la liste de fichiers
 */
function genererPDF($docHTML, $nomPersonne, &$listeFichiersPDF)
{
    // fabriquer le fichier PDF
    $nomPDF = \Paheko\Utils::filePDF($docHTML);
    // changer le nom du fichier
    $nom = str_replace(' ', '_', $nomPersonne);
    $nom = str_replace("'", "", $nom);
    $nomFichier = sprintf(
        '%s/recu_%s_%s.pdf',
        dirname($nomPDF),
        $_SESSION['annee_recu'],
        $nom
    );
    rename($nomPDF, $nomFichier);
    // ajouter le nom du fichier à la liste pour mettre dans une archive
    $listeFichiersPDF[] = $nomFichier;
} // genererPDF

function faireNumeroRecu($prefixeNum, $membre, $numero, &$numero_sequentiel)
{
    if (isset($membre) && $membre) {
        if ($prefixeNum != "") {
            $prefixeNum .= "-";
        }
        $prefixeNum .= $numero;
    }
    if ($numero_sequentiel) {
        if ($prefixeNum != "") {
            $prefixeNum .= "-";
        }
        $prefixeNum .= $numero_sequentiel;
        ++$numero_sequentiel;
    }
    return $prefixeNum;
}

/**
 * renvoyer le préfixe du numéro de reçu
 */
function getNumPrefixe($configNum)
{
    $prefixeNum = "";
    if (isset($configNum->prefixe) && $configNum->prefixe != "") {
        $prefixeNum = $configNum->prefixe;
    }
    if (isset($configNum->annee) && $configNum->annee) {
        if ($prefixeNum != "") {
            $prefixeNum .= "-";
        }
        $prefixeNum .= $_SESSION['annee_recu'];
    }
    return $prefixeNum;
}

/**
 * renvoyer le premier numéro de la numérotation séquentielle
 * renvoie false si pas de numérotation séquentielle
 */
function getNumSequentiel($configNum)
{
    if (isset($configNum->sequentiel) && $configNum->sequentiel) {
        if (isset($configNum->valeur_init) && $configNum->valeur_init != "") {
            $numero_sequentiel = $configNum->valeur_init;
        } else {
            $numero_sequentiel = 1;
        }
    }
    return isset($numero_sequentiel) ? $numero_sequentiel : false;
}

function mentionsComplémentaires()
{
    $donnees = array(
        'Nature du don : ' => "Numéraire",
        'Mode de versement : ' => "chèque et/ou virement"
    );
    $complements = array();
    foreach ($donnees as $titre => $libelle) {
        $elem = new \stdClass();
        $elem->titre = $titre;
        $elem->libelle = $libelle;
        $complements[] = $elem;
    }
    return $complements;
}