<?php
namespace Modules\EtatStatistiques\Controller;

use Entity\Model\EtatEtTh;
use Entity\Model\EtatGroupEtat;
use Entity\Model\EtatGroupUtil;
use Entity\Model\EtatGrp;
use Entity\Model\EtatStat;
use Entity\Model\EtatUser;
use Entity\Model\EtatUtil;
use Entity\Model\Hastutil;
use GuzzleHttp\Psr7\Response;
use Helpers\Form\FormBuilder;
use Helpers\Trad\Trad;
use Modules\EtatStatistiques\Repository\EtatStatDataRepo;
use Modules\EtatStatistiques\Repository\EtatStatTypeRepo;
use Modules\EtatStatistiques\Service\EtatStatForm;
use Skeleton\Controller\Controller;

class EditEtatStatTypeController extends Controller
{
    public function formCreateAction() :string
    {
        return $this->renderer->render('@EtatStatistiques/Edit/formCreate', [
            'form' => $this->getForm(),
            'subject' => [],
        ]);
    }
    
    public function createAction() :Response
    {
        $trad = $this->getTranslationService();
        $post =
            $this->request->getParsedBody()
            + $this->request->getUploadedFiles();
        $form = $this->getForm();

        $validator = $this->createFormValidator();
        $post = $validator->validateForm($form, $post);

        // Case : has duplicate
        if ((new EtatStat($this->pdo))->find($post['CODETAT'])) {
            $validator->setError(Trad::strBuild(
                $trad->t('Le code @1@ existe déjà.'),
                $post['CODETAT']
            ));
        }

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

        //_____________________________
        // Update DB
        

        (new EtatStatTypeRepo($this->pdo))->create($post);

        return new Response(200);
    }

    public function formUpdateAction() :string
    {
        $code = $this->request->getAttribute('id');

        $etat = (new EtatStatTypeRepo($this->pdo))->getEtatDetail($code);
        // TODO : handle 404

        return $this->renderer->render('@EtatStatistiques/Edit/formUpdate', [
            'form' => $this->getForm($etat),
            'subject' => $etat,
        ]);
    }

    public function updateAction() :Response
    {
        $id = $this->request->getAttribute('id');
        $post =
            $this->request->getParsedBody()
            + $this->request->getUploadedFiles();

        $etat = (new EtatStatTypeRepo($this->pdo))->getEtatDetail($id);
        if (empty($etat)) {
            return new Response(404, [], 'EtatStat not found');
        }
        $post['Source'] = $etat['Source'];

        $form = $this->getForm($etat);
        $validator = $this->createFormValidator();
        $post = $validator->validateForm($form, $post);

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

        (new EtatStatTypeRepo($this->pdo))->update(
            ['CODETAT' => $etat['CODETAT']]
            + $post
            + ['Source' => $etat['Source']]
        );

        return new Response(200);
    }

    public function deleteAction() :Response
    {
        $id = $this->request->getAttribute('id');

        $etatstat = (new EtatStat($this->pdo))->find($id);
        if (empty($etatstat)) {
            return new Response(404);
        }
        if (in_array($etatstat['SOURCE'], ['OXACHARTS_INT', 'OXACHARTS'])) {
            return new Response(400, [], 'This state is not deletable');
        }

        (new EtatStatTypeRepo($this->pdo))->delete($id);

        return new Response(200);
    }

    public function popupPreviewSqlAction() :string
    {
        $post = $this->request->getParsedBody();

        // TODO : handle updateAction specific ?

        $post['Source'] = 'Requeteur';

        $form = $this->getForm([1/* Force retrieval of FormUpdate */]);
        $validator = $this->createFormValidator();
        $post = $validator->validateForm($form, $post);
        
        if (! $validator->isValid()) {
            return $this->renderer->render('@popup-erreur/ErreurCreation', [
                'ErreurValid' => $validator->getError(),
            ]);
        }
        
        // Transform post into Etats details
        // TODO : factorize with EtatStatTypeRpo::create/update
        $post = (new EtatStatTypeRepo($this->pdo))->formatPostIntoEntity($post);
        $post['Requete']['REQ_ID'] = 1;
        $post['Requete']['Where'] = implode(' ', $post['Requete']['WherePillable'] ?? []);
        $post['Requete']['ListSelect'] = array_map(function ($item, $index) {
            return $item + ['ELEM_NORD' => $index, 'ORDRE_TRI' => $index];
        }, $post['Requete']['ListSelect'] ?? [], array_keys($post['Requete']['ListSelect'] ?? []));
        $post['Requete']['ListJoin'] = array_map(function ($item, $index) {
            return $item + ['RFRO_NO_ORDRE' => $index];
        }, $post['Requete']['ListJoin'] ?? [], array_keys($post['Requete']['ListJoin'] ?? []));
        if ($post['Requete']['Rupture']) {
            $rup = &$post['Requete']['Rupture'];
            $rup['NUM_ORD'] = 1;
            $rup['ListJoin'] = array_map(function ($item, $index) {
                return $item + ['NUM_ORD' => $index];
            }, $rup['ListJoin'] ?? [], array_keys($rup['ListJoin'] ?? []));
        }
        
        return $this->renderer->render('@EtatStatistiques/Edit/popupPreviewSql', [
            'sql' => (new EtatStatDataRepo($this->mustGetPdoOxaDw()))->getSql($post, [])->query,
        ]);
    }

//_____________________________________________________________________________
// Sub-routine

    /**
     * @param ?array<mixed> $etat
     * @return \stdClass[]
     */
    private function getForm(?array $etat = null)
    {
        $trad = $this->getTranslationService();
        $pdoDw = $this->getPdoOxaDw();
        if ($pdoDw == false) {
            throw new \Exception('OWADW required');
        }
        $service = new EtatStatForm($trad, $etat);
        return $service->getFormView($trad);
    }
    
    // protected function getDwRepo() :EtatStatDataRepo
    // {
    //     $pdo = $this->getPdoOxaDw();
    //     if ($pdo === false) {
    //         throw new \Exception('DW is required');
    //     }
    //     return new EtatStatDataRepo($pdo);
    // }
    


//______________________________________________________________________________
// Update EtatStat.listTheme

    /**
     * @return Response|string
     */
    public function formEtatThemeUpdateAction()
    {
        $code = $this->request->getAttribute('id');

        $etat = (new EtatStat($this->pdo))->find($code);
        if (empty($etat)) {
            return new Response(404, [], 'Invalid code "'.$code.'"');
        }

        return $this->renderer->render('@EtatStatistiques/Edit/formEtatThemeUpdate', [
            'form' => $this->getThemeForm(),
            'subject' =>
                $etat
                + [
                    'listTheme' =>
                        (new EtatStatTypeRepo($this->pdo))
                        ->listEtatStatTheme($etat['CODETAT']),
                ],
        ]);
    }

    public function themeUpdateAction() :Response
    {
        $code = $this->request->getAttribute('id');
        $post = $this->request->getParsedBody();

        $validator = $this->createFormValidator();

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

        //_______________________

        $etat = (new EtatStat($this->pdo))->find($code);
        if (empty($etat)) {
            return new Response(404, [], 'Invalid code "'.$code.'"');
        }

        $this->pdo->beginTransaction();

        $qbAssoc = new EtatEtTh($this->pdo);
        $qbAssoc->delete(['CODETAT' => $etat['CODETAT']]);
        foreach ($post['listTheme'] as $entityId) {
            $qbAssoc->insert([
                'CODETAT' => $etat['CODETAT'],
                'CODTHEM' => $entityId,
            ]);
        }

        $this->pdo->commit();

        return new Response(200);
    }

    /**
     * @return \stdClass[]
     */
    private function getThemeForm()
    {
        return (new FormBuilder())
            ->addCustomInput('listTheme', 'MULTIPICK', [
                'zoom_path' => 'Ajax.liste.etatStatTheme',
                'template' => '@GlobalApplication/Input/inputMultipick',
            ])
            ->build();
    }

//______________________________________________________________________________
// Update Visi
    
    /**
     * @return string|Response
     */
    public function formVisiEtatAction()
    {
        $id = $this->request->getAttribute('id');
        $etat = (new EtatStat($this->pdo))->find($id);
        if (empty($etat)) {
            return $this->create404Response();
        }
        $listEtUser = (new EtatUser($this->pdo))->findAll([
            'CODETAT' => $id,
        ]);
        $listEtGrp = (new EtatGroupEtat($this->pdo))->findAll([
            'CODETAT' => $id,
        ]);
        return $this->renderer->render('@EtatStatistiques/Edit/formVisiEtatUpdate', [
            'post' => $this->request->getParsedBody(),
            'form' => $this->getVisiEtatForm(),
            'subject' => $etat + [
                'listAssocUtil' => !empty($listEtUser) ? (new Hastutil($this->pdo))->findAll([
                    'CODE' => array_column($listEtUser, 'CODUSR'),
                ]) : [],
                'listAssocGroup' => !empty($listEtGrp) ? (new EtatGrp($this->pdo))->findAll([
                    'CODGRP' => array_column($listEtGrp, 'CODGRP'),
                ]) : [],
            ],
        ]);
    }

    public function visiEtatAction() :Response
    {
        $id = $this->request->getAttribute('id');
        $post = $this->request->getParsedBody();

        $etat = (new EtatStat($this->pdo))->find($id);
        if (empty($etat)) {
            return $this->create404Response();
        }
        
        $validator = $this->createFormValidator();
        $post = $validator->validateForm($this->getVisiEtatForm(), $post);
        if (! $validator->isValid()) {
            return new Response(400, [], $validator->getError());
        }

        //___________________________
        // Update DB

        $this->pdo->beginTransaction();
        
        $qbUtil = new EtatUtil($this->pdo);
        $qbUtil->delete(['CODETAT' => $id]);
        foreach ($post['listAssocUtil'] as $util) {
            $qbUtil->insert(['CODETAT' => $id, 'CODUSR' => $util]);
        }
        $qbEtat = new EtatGroupEtat($this->pdo);
        $qbEtat->delete(['CODETAT' => $id]);
        foreach ($post['listAssocGroup'] as $etat) {
            $qbEtat->insert(['CODETAT' => $id, 'CODGRP' => $etat]);
        }

        $this->pdo->commit();

        return new Response(200);
    }

    /**
     * @return \stdClass[]
     */
    private function getVisiEtatForm()
    {
        $trad = $this->getTranslationService();
        return (new FormBuilder())
            ->addMultipick('listAssocGroup', 'Ajax.liste.etatGroupe', [
                'label' => $trad->t('Liste des groupes d’utilisateurs'),
            ])
            ->addMultipick('listAssocUtil', 'Ajax.liste.hastutil', [
                'label' => $trad->t('Liste des utilisateurs'),
            ])
            ->build();
    }
}
