<?php declare(strict_types=1);

namespace Modules\TermeDePaiement\Service\Strategy;

use Helpers\Parametres\Constante;
use Modules\Panier\Service\ValidationPanierService;
use Modules\TermeDePaiement\Repository\TermPaieRepo;

class TPStrategyPanier implements TPStrategyInterface
{

    private bool|\SimpleXMLElement $panierXml;
    private string $module;
    public function __construct(
        private ValidationPanierService $validationPanierService,
        private TermPaieRepo $termPaieRepo
    ) {
    }

    /**
     * Summary of setPanierXml
     * @param string $module
     * @param string $critere
     * @return TPStrategyPanier
     */
    public function init(string $module, string $critere): TPStrategyPanier
    {
        $critereRegroup  = str_replace(Constante::oxaPipe, '|', $critere);
        $this->panierXml = $this->validationPanierService->getListe(
            $module == 'PanierDA' ? 'DA' : 'CDE',
            $module != 'PanierDA' ? (string) $critereRegroup : null
        );
        $this->module    = $module;
        return $this;
    }

    /**
     * Summary of getLignesTpPos
     * @param string $id
     * @return ?string
     */
    public function getDevise(string $id): ?string
    {
        return (string) $this->validationPanierService->getDeviseDoc();
    }

    /**
     * Summary of getLignesTpPos
     * @param string $id
     * @param array<mixed> $allTpPos
     * @return ?array<mixed>
     */
    public function getDetailLigneTpPos(string $id, array $allTpPos): ?array
    {
        $lignesTpPos = [];
        if (gettype($this->panierXml) != 'boolean') {
            foreach ($allTpPos as $ligne) {
                $lineNumber = 1;
                foreach ($this->panierXml->ListProduit->Produit as $art) {
                    if (intval($ligne['NUM_PO_CD']) == $lineNumber) {
                        $lignesTpPos[$lineNumber] = [
                            'CODE_ART' => $art?->CodeArticle ?? '',
                            'NO_PO' => $lineNumber,
                            'DES_SOMM' => $art?->DesArticle ?? '',
                            'QTE_COMM' => $art?->QteDemande ?? '',
                            'UNITE' => $art?->CodeUnit ?? '',
                            'PU' => $art?->PxDemande ?? '',
                        ] + $lignesTpPos;
                    }
                    $lineNumber++;
                }
            }
        }
        return (array) $lignesTpPos;
    }


    /**
     * Summary of getLignesSeuil
     * @param string $id
     * @param array<mixed> $allLignesOnEvent
     * @return ?array<mixed>
     */
    public function getDetailLigneSeuil(string $id, array $allLignesOnEvent): ?array
    {
        $lignesSeuil = [];
        if (gettype($this->panierXml) != 'boolean') {
            $lineNumber = 1;
            foreach ($allLignesOnEvent as $ligneOnEvent) {
                foreach ($this->panierXml->ListProduit->Produit as $art) {
                    if (intval($ligneOnEvent['NOPOCDE']) == $lineNumber) {
                        $lignesSeuil[$lineNumber] = [
                            'CODE_ART' => $art->CodeArticle,
                            'NO_PO' => $lineNumber,
                            'DES_SOMM' => $art->DesArticle,
                            'QTE_DEM' => $art->QteDemande,
                            'UNITE' => $art->CodeUnit,
                            'PU' => $art->PxDemande,
                        ] + $ligneOnEvent;
                        break;
                    }
                    $lineNumber++;
                }
            }
        }
        return $lignesSeuil;
    }

    /**
     * Summary of getAllDocArticles
     * @param string $id
     * @return ?array<mixed>
     */
    public function getAllDocArticles(string $id): ?array
    {
        $count = 1;
        $array = [];
        if ($this->panierXml instanceof \SimpleXMLElement) {
            foreach ($this->panierXml->ListProduit->Produit as $produit) {
                $array[] = ['NO_PO' => $count];
                $count++;
            }
        }
        return $array;
    }


    /**
     * Summary of getMontantTotal
     * @param string $id
     * @return string
     */
    public function getMontantTotal(string $id): string
    {
        return trim((string) ($this->panierXml->Montant ?? 0));
    }

    public function getCodeFou(string $id): string
    {
        // @phpstan-ignore-next-line
        return (string) $this->panierXml->CodeFourn;
    }

    /**
     * Summary of verifPourcTP
     * @param string $id
     * @param array<mixed> $tps
     * @return array<mixed>
     */
    public function verifPourcTP(string $id, array &$tps, array $evts, ?string $critere = null): array
    {
        if (count($tps) == 0) {
            return [];
        }

        $verifPourcTpGlobal = [];
        $noPo               = $this->getAllDocArticles($id) ?? [];

        $expectedPo            = array_map(fn($po) => (int) $po['NO_PO'], $noPo);
        $pourcentageParArticle = [];

        foreach ($tps as $tp) {
            foreach ($noPo as $po) {
                $verifPourcTp = $this->termPaieRepo->verifPourcTp($id, $tp['NUM_TP'], $this->module, $po['NO_PO'], $critere);
                foreach ($verifPourcTp as $ligne) {
                    if (!isset($pourcentageParArticle[$ligne['NO_PO']])) {
                        $pourcentageParArticle[$ligne['NO_PO']] = 0;
                    }
                    $pourcentageParArticle[$ligne['NO_PO']] += $ligne['total_pourc_tp'];
                }
            }
        }

        foreach ($expectedPo as $poIndex) {
            // @phpstan-ignore-next-line
            if (!isset($pourcentageParArticle[$poIndex])) {
                $verifPourcTpGlobal[] = [
                    'NO_PO' => $poIndex,
                    'total_pourc_tp' => 0,
                    'pourcentage_manquant' => 100,
                    'missing' => true
                ];
            } else {
                $pourcentageManquant  = 100 - $pourcentageParArticle[$poIndex];
                $verifPourcTpGlobal[] = [
                    'NO_PO' => $poIndex,
                    'total_pourc_tp' => $pourcentageParArticle[$poIndex],
                    'pourcentage_manquant' => abs($pourcentageManquant),
                    'missing' => false
                ];
            }
        }

        return $verifPourcTpGlobal;
    }
}
