<?php
namespace Modules\API\APIExterne\Controller;

use API\GovZaCsd\GovZaCsdPartenaire;
use Entity\Model\Fourniss;
use Entity\Model\WftDemEnt;
use Entity\Model\WftDemLig;
use GuzzleHttp\Psr7\Response;
use Helpers\Ariane\ArianeSub;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Log\LogSysteme;
use Helpers\Outil\ArrayHelper;
use Modules\Fournisseur\Service\FormFounisseur;
use Modules\GlobalApplication\Repository\Workflow;
use Skeleton\Controller\Controller;

class GovZaCsdController extends Controller
{

    private function getPartenaire() :GovZaCsdPartenaire
    {
        /** @phpstan-ignore-next-line */
        return $this->getPartenaireService()->getByCode('CSD');
    }

    public function supplierDetailAction() :string
    {
        $fournissId = $this->request->getAttribute('fournissId');

        $fourniss = (new Fourniss($this->pdo))->find($fournissId);
        if (empty($fourniss)) {
            return 'Invalid fourniss id #'.$fournissId;
        }

        return $this->supplierDetailRender($fourniss);
    }

    public function supplierDemDetailAction() :string
    {
        $demId = $this->request->getAttribute('demId');

        $fourniss = (new Workflow($this->pdo))->getFournissDemande($demId);
        if (empty($fourniss)) {
            return 'Invalid fourniss id #'.$demId;
        }
        return $this->supplierDetailRender($fourniss);
    }

    /**
     * @param array<mixed> $fourniss
     */
    private function supplierDetailRender(array $fourniss) :string
    {
        try {
            $partn = $this->getPartenaire();
            $info = $partn->getWs()->companyInfo(
                $fourniss[ $partn->getFournissCsdField() ]
            );
            $info = GovZaCsdPartenaire::resolveReference($info);
        } catch (\Exception $e) {
            LogSysteme::prefixErrorLog((string) $e);
            $info = (object) [];
        }

        ArianeSub::refreshActive();

        
        return $this->renderer->render(
            '@API/GovZaCsd/detail',
            [
                'fourniss' => $fourniss,
                'info' => $info,
            ]
        );
    }

    public function formDemCompareAction() :string
    {
        $demId = $this->request->getAttribute('demId');
        $fourniss = (new Workflow($this->pdo))->getFournissDemande($demId);
        
        $partn = $this->getPartenaire();
        $csdId = $fourniss[ $partn->getFournissCsdField() ];
        $delta = $partn->getDetail(Fourniss::class, [
            'CODE_PAYS' => $fourniss['CODE_PAYS'],
            '_csdId' => $csdId,
        ]);
        
        // Get Fourniss from Dem with Csd data
        $newFourniss = ArrayHelper::mergeDelta($fourniss, $delta);

        $formService = new FormFounisseur($this->contenaire);
        $form = $formService->getFormView($formService->getFormModifPartn($fourniss));
        
        return $this->renderer->render(
            '@API/GovZaCsd/formDemCompare',
            [
                'demId' => $demId,
                'fourniss' => $fourniss,
                'listFieldUpdate' => array_map(
                    fn($field) => [
                        'current' => $fourniss[ $field ] ?? '',
                        'new' => $newFourniss[ $field ] ?? '',
                        'code' => $field,
                        'input' => $form[ $field ]
                    ],
                    array_intersect(array_keys($delta), array_keys($fourniss))
                ),
                'fourniss_new' => $newFourniss,
                'errorCode' => $delta['err'],
                'csdId' => $csdId,
            ]
        );
    }

    public function updateDemAction() :Response
    {
        $demId = $this->request->getAttribute('demId');
        $post = $this->request->getParsedBody();
        $dem = (new WftDemEnt($this->pdo))->find([
            'TYPE_ENT' => 'FOURNISS',
            'CODE_DEMANDE' => $demId,
        ]);
        if (empty($dem)) {
            return new Response(404, [], 'Dem not found');
        }

        $fourniss = (new Workflow($this->pdo))->getFournissDemande($dem['CODE_DEMANDE']);
        $newFourniss = ArrayHelper::mergeDelta($fourniss, $post);

        $formService = new FormFounisseur($this->contenaire);
        $form = $formService->getFormView($formService->getFormModifPartn($fourniss));

        // Validate only what has been posted (ignore the rest of Fourniss)
        $form = ArrayHelper::filterByKey($form, array_keys($post));

        $validator = $this->createFormValidator();
        $newFourniss = $validator->validateForm($form, $newFourniss);
        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        //___________________________

        $qbDemLig = new WftDemLig($this->pdo);
        $listDemLig = $qbDemLig->findAll([
            'CODE_DEMANDE' => $dem['CODE_DEMANDE']
        ]);

        // Since fourniss is not complete we must "mix" payload with DB current state
        // Currently only root field and Champ sup are supported

        // TODO : change ariane

        foreach ($listDemLig as &$demLig) {
            $field = $demLig['CODE_CHAMP'];
            if ($demLig['CODE_STRUCT'] == ''
                && array_key_exists($field, $newFourniss)
            ) {
                $demLig['VALEUR_CHAMP'] = $newFourniss[ $field ];
                continue;
            }
            if ($demLig['CODE_STRUCT'] == 'CHPSUPFOU'
                && array_key_exists($csKey = ChampSupp::getCsExtKey(
                    'FOURNISS',
                    $demLig['ID_RECORD_STRUCT']
                ), $newFourniss)
            ) {
                $demLig['VALEUR_CHAMP'] = $newFourniss[ $csKey ];
                continue;
            }
        }
        unset($demLig);

        $this->pdo->beginTransaction();
        foreach ($listDemLig as $demLig) {
            $qbDemLig->merge($demLig);
        }
        $this->pdo->commit();

        return new Response(200);
    }
}
