<?php
namespace Modules\Fournisseur\Controller;

use Entity\Model\Fourniss;
use Entity\Model\Metadata\EntityMetaQb;
use Entity\Model\Metadata\PartnFournissDemModif;
use Entity\Model\WftDemEnt;
use GuzzleHttp\Psr7\Response;
use Helpers\Outil\ArrayHelper;
use Helpers\Validator\FormValidator;
use Modules\Fournisseur\Service\FormFounisseur;
use Skeleton\Controller\Controller;
use Modules\Fournisseur\WebService\Fournisseur as FournisseurWs;

class ModificationSourceExtController extends Controller
{
    /**
     * @return string|Response
     */
    public function formUpdateAction()
    {
        $fournissId = $this->request->getAttribute('id');

        $demModif = $this->getDemande($fournissId);
        if ($demModif == null) {
            return new Response(404, [], 'Invalid dem modif');
        }

        $fourniss = $this->getFicheFouniss($fournissId);

        $formService = new FormFounisseur($this->contenaire);
        

        $form = ArrayHelper::filterByKey(
            $formService->getFormModifPartn($fourniss),
            array_keys($demModif->listDelta()) // Filter input used by $demModif
        );

        $form = $formService->getFormView($form);

        $newFourniss = $this->mergeDelta($fourniss, $demModif->listDelta());
        
        $listFieldUpdate = [];
        foreach ($demModif->listDelta() as $field => $value) {
            $listFieldUpdate[] = [
                'current' => $fourniss[ $field ] ?? '',
                'new' => $newFourniss[ $field ] ?? '',
                'code' => $field,
                'input' => $form[ $field ]
            ];
        }

        return $this->renderer->render(
            '@Fournisseur/SourceExt/gestion',
            [
                'fourniss' => $fourniss,
                'listFieldUpdate' => $listFieldUpdate,
                'demandeWF' => (new WftDemEnt($this->pdo))->find([
                    'TYPE_ENT' => 'FOURNISS',
                    'CODE_ENREG' => $fourniss['CODE'],
                ]),
                'fourniss_new' => $newFourniss,
            ]
        );
    }

    public function updateAction() :Response
    {
        $post = $this->request->getParsedBody();
        $fournissId = $post['fournissId'] ?? '';
        $qb = new Fourniss($this->pdo);
        $fourniss = $qb->find($fournissId);
        if (empty($fourniss)) {
            return new Response(400, [], 'Invalid fournissId');
        }

        //____________

        if (($post['action'] ?? null) == 'refuse') {
            (new EntityMetaQb($this->pdo))->deleteByStruct(
                Fourniss::class,
                $fournissId,
                PartnFournissDemModif::class
            );
            return new Response(200);
        }

        //____________

        // Action is not available if a WftDem already exist
        $demandeWF = (new WftDemEnt($this->pdo))->find([
            'TYPE_ENT' => 'FOURNISS',
            'CODE_ENREG' => $fourniss['CODE'],
        ]);
        if ($demandeWF != null) {
            return new Response(400, [], 'LOCK DEM WORKFLOW'); // TODO : make message
        }

        //____________

        $demModif = $this->getDemande($fournissId);
        if ($demModif == null) {
            return new Response(404, [], 'Invalid dem modif');
        }

        $fourniss = $this->getFicheFouniss($fournissId);
       

        //_______________

        $formService = new FormFounisseur($this->contenaire);

         // Filter input used by $demModif
        $form = ArrayHelper::filterByKey(
            $formService->getFormModifPartn($fourniss),
            array_keys($demModif->listDelta())
        );

        // Filter input disabled by user
        $form = ArrayHelper::filterByKey(
            $form,
            array_keys($post)
        );
        $form = $formService->getFormView($form);

        $validator = new FormValidator($this->pdo, $this->getTranslationService());
        $post = $validator->validateForm($form, $post);

        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        //___________

        $newFourniss = array_merge($fourniss, $post);

        $reponse =
            (new \Modules\Fournisseur\WebService\CreationFournisseur($this->pdo))
            ->updateFourniss($newFourniss, $fourniss);

        if ($reponse->Statut != 'O') {
            return new Response(400, [], (string) $reponse->MsgErreur);
        }
        (new EntityMetaQb($this->pdo))->deleteByStruct(
            Fourniss::class,
            $fournissId,
            PartnFournissDemModif::class
        );

        //______________

        $codeFrs = strval($reponse->CODE);
        $demandeId = strval($reponse->CODE_DEMANDE);
        
        return $this->createJsonResponse([
            'goto' => $demandeId ?
                $this->router->generateUri(
                    'Fournisseur.Fournisseur.index',
                    ["id" => $codeFrs, 'codeDemande' => $reponse->CODE_DEMANDE]
                ) :
                $this->router->generateUri(
                    'Fournisseur.Fournisseur.index',
                    ["id" => $codeFrs]
                ),
        ]);
    }

//_____________________________________________________________________________
// Sub-routine

    /**
     * @param array<mixed> $fourniss
     * @param array<mixed> $delta
     * @return array<mixed>
     */
    private function mergeDelta(array $fourniss, array $delta)
    {
        foreach ($fourniss as $k => $v) {
            if (! array_key_exists($k, $delta)) {
                continue;
            }

            $value = $delta[ $k ] ?? null;
            if ($value === null) {
                continue;
            }

            if (is_array($v)) {
                $fourniss[ $k ] = array_merge(
                    $v,
                    array_map(function ($item) {
                        return $item;
                    }, $value)
                );
                continue;
            }

            $fourniss[ $k ] = $value;
        }
        return $fourniss;
    }

    private function getDemande(string $fournissId) :?PartnFournissDemModif
    {
        return (new EntityMetaQb($this->pdo))
            ->find(
                Fourniss::class,
                $fournissId,
                PartnFournissDemModif::class,
                0
            );
    }

    /**
     * @return array<mixed>
     */
    private function getFicheFouniss(string $fournissId)
    {
        $wsFourniss = new FournisseurWs();
        $ficheFourniss = $wsFourniss->ficheFournisseur([
            "no_ao" => $_SESSION["Session_SocUsr"],
            "codeFrs" => $fournissId,
            'codeDemande' => '',
            'affDemande' => '',
            'mode' => 'M',
        ]);
        $ficheFourniss = new \SimpleXMLElement($ficheFourniss->responseData);
        return $wsFourniss->normalizeFicheFourniss($ficheFourniss);
    }
}
