<?php

require_once __DIR__ . '/../../classes/Animal.php';
require_once __DIR__ . '/../../classes/Recommandation.php';
require_once __DIR__ . '/../../class/CricCrocApi.php';
require_once __DIR__ . '/../../Service/RecommandationManagerApi/RecommandationController.php';

class MyvetshopcliniqueMyRecoModuleFrontController extends ModuleFrontController
{
    /**
     * @var bool
     */
    public $display_column_left = false;

    /**
     * @throws PrestaShopException
     */
    public function init(): void
    {
        global $smarty;

        parent::init();

        $this->context->smarty = $smarty;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function initContent(): void
    {
        // Par défaut : aucune erreur
        $this->context->smarty->assign(
            [
                'errorCodeReco' => null,
            ]
        );

        parent::initContent();

        $userLogged = (bool) $this->context->customer->id;

        // GET && POST
        //Accessible connecté ou non, c'est le meme formulaire
        if (Tools::getValue('code')) {
            try {
                $this->processAssign();
            } catch (Exception $e) {
                // Par défaut : aucune erreur
                $this->context->smarty->assign(
                    [
                        'errorCodeReco' => $e->getMessage(),
                    ]
                );
            }
        }

        if ('GET' == $_SERVER['REQUEST_METHOD'] && isset($_GET['action'], $_GET['id'])) {
            switch ($_GET['action']) {
                case 'delete':
                    if (!$userLogged) {
                        Tools::redirect((new Link())->getPageLink('my-account', true));
                    }

                    $this->processDelete();

                    return;
                default:
                    // Rien
            }
        }

        if ('POST' == $_SERVER['REQUEST_METHOD'] && isset($_GET['action'], $_GET['id']) && (isset($_POST['animal']) || isset($_POST['product']))) {
            switch ($_GET['action']) {
                case 'update':
                    if (!$userLogged) {
                        Tools::redirect((new Link())->getPageLink('my-account', true));
                    }

                    $this->processUpdate();

                    return;
                default:
                    // Rien
            }
        }

        if ('GET' == $_SERVER['REQUEST_METHOD'] && isset($_GET['action'])) {
            switch ($_GET['action']) {
                case 'pdf':
                    if (!$userLogged) {
                        Tools::redirect((new Link())->getPageLink('my-account', true));
                    }

                    $this->processPdf();

                    return;
                default:
                    // Rien
            }
        }

        $result = Db::getInstance(false)
            ->executeS(
                'SELECT `a`.*'
                . ' FROM `' . _DB_PREFIX_ . 'animal` a'
                . ' INNER JOIN `' . _DB_PREFIX_ . 'recommandation` r ON `r`.`id_animal` = `a`.`id_animal`'
                . ' WHERE `a`.`id_customer` = ' . (int) $this->context->customer->id
                . ' AND `a`.`deleted` = false'
                . ' GROUP BY `a`.`id_animal`'
            );

        if (!is_array($result)) {
            $result = [];
        }

        $animaux = ObjectModel::hydrateCollection(
            Animal::class, $result
        );

        $result = Db::getInstance(false)
            ->executeS(
                'SELECT `a`.*'
                . ' FROM `' . _DB_PREFIX_ . 'animal` a'
                . ' WHERE `a`.`id_customer` = ' . (int) $this->context->customer->id
                . ' AND `a`.`deleted` = false'
                . ' GROUP BY `a`.`id_animal`'
            );

        if (!is_array($result)) {
            $result = [];
        }

        $allAnimalsForCustomer = ObjectModel::hydrateCollection(
            Animal::class,
           $result
        );

        $this->context->smarty->assign(
            [
                'animaux' => $animaux,
                'allAnimals' => $allAnimalsForCustomer,
            ]
        );

        $this->context->smarty->assign(['meta_title' => 'MyVetShop - Recommandation nutritionnelle vétérinaire']);
        $this->setTemplate('my_reco.tpl');
    }

    public function processDelete(): void
    {
        try {
            $context = Context::getContext();
            $customer = $context->customer;

            $idReco = Tools::getValue('id');

            $recommandation = new Recommandation($idReco);
            if ($recommandation->id_customer != $customer->id) {
                throw new Exception('Il n\'est pas possible de supprimer cette recommandation.');
            }

            $recommandation->deleted = true;

            $recommandation->update();

            Tools::redirect($this->context->link->getModuleLink('myvetshopclinique', 'myreco', ['delete' => 'true']));
        } catch (Exception $exception) {
            Tools::redirect($this->context->link->getModuleLink('myvetshopclinique', 'myreco', ['delete' => 'false']));
        }
    }

    public function processUpdate(): void
    {
        try {
            $context = Context::getContext();
            $customer = $context->customer;
            $idReco = Tools::getValue('id');
            $productNumber = Tools::getValue('product');
            $animalId = Tools::getValue('animal');

            $recommandation = new Recommandation($idReco);
            if ($recommandation->id_customer != $customer->id) {
                throw new Exception('Il n\'est pas possible de modifier cette recommandation.');
            }

            $animal = new Animal($animalId);
            if (!$animal->id || $animal->id_customer != $customer->id) {
                throw new Exception('Il n\'est pas possible de modifier cette recommandation.');
            }

            if ($animal->espece !== $recommandation->espece) {
                throw new Exception('L\'espèce de la recommandation et de l\'animal ne correspondent pas.');
            }

            $recommandation->id_animal = $animal->id;

            // Modification de la ration
            switch ($productNumber) {
                case 1:
                    $animal->ration = (int) $recommandation->qte_aliment1;
                    $animal->id_product = (int) $recommandation->product_id_mvs1;
                    break;
                case 2:
                    $animal->ration = (int) $recommandation->qte_aliment2;
                    $animal->id_product = (int) $recommandation->product_id_mvs2;
                    break;
                case 3:
                    $animal->ration = (int) $recommandation->qte_aliment3;
                    $animal->id_product = (int) $recommandation->product_id_mvs3;
                    break;
                default:
                    $animal->ration = (int) $recommandation->qte_aliment1;
                    if (!$recommandation->transition12 && $recommandation->qte_aliment2) {
                        $animal->ration += (int) $recommandation->qte_aliment2;
                    }
                    if (!$recommandation->transition23 && $recommandation->qte_aliment3) {
                        $animal->ration += (int) $recommandation->qte_aliment3;
                    }
                    break;
            }

            $recommandation->update();
            $animal->update();

            Tools::redirect($this->context->link->getModuleLink('myvetshopclinique', 'myreco', ['update' => 'true']));
        } catch (Exception $exception) {
            Tools::redirect($this->context->link->getModuleLink('myvetshopclinique', 'myreco', ['update' => 'false']));
        }
    }

    public function processAssign(): void
    {
        $error = null;
        $reco = null;
        $codeReco = null;

        try {
            // Vérifie qu'un code a bien été rentré
            $codeReco = Tools::getValue('code', null);

            if (!$codeReco) {
                throw new Exception('Le code reco est invalide.');
            }

            // Check si le client n'a pas déjà importé ce code sur son compte
            $db = Db::getInstance(false);
            $sql = 'SELECT COUNT(id_recommandation) as numberOfReco
             FROM `' . _DB_PREFIX_ . 'recommandation` `r`
             WHERE `r`.`id_customer` = ' . (int) $this->context->customer->id . ' AND `r`.`deleted` = 0 AND `r`.`code_reco` = "' . $db->escape($codeReco) . '"';

            $result = $db->getRow($sql);

            if (!is_array($result) || !isset($result['numberOfReco']) || $result['numberOfReco'] > 0) {
                throw new Exception('Le code fourni a déjà été importé.');
            }

            $api = new CricCrocApi();

            $recoJson = $api->getRecoJson($codeReco);
            $reco = $api->parseRecoJson($recoJson);
            $reco->code_reco = trim(strtoupper($codeReco));
            $reco->id_customer = $this->context->customer->id;

            if (is_null($reco->code_reco)) {
                throw new Exception("Cette recommandation n'est plus disponible.");
            }

            $group = new Group($this->context->customer->id_default_group);
            $groupName = $group->name[$this->context->language->id];
            if (false === strpos($reco->code_clinique, $groupName)) {
                throw new Exception('Cette recommandation a été réalisée par une clinique vétérinaire qui ne correspond pas à votre code privilège actuel.');
            }

            // Association avec l'animal
            $id_animal = Tools::getValue('id_animal', null);
            if (!is_null($id_animal) && is_null($error)) {
                $userLogged = (bool) $this->context->customer->id;

                if (!$userLogged) {
                    Tools::redirect((new Link())->getPageLink('my-account', true));
                }

                try {
                    $recommandationManagerAPi = new RecommandationController($this->context->customer);
                    $result = $recommandationManagerAPi->actionCricCrocImport($codeReco, $id_animal);

                    if (isset($result['error'])) {
                        throw new Exception(isset($result['error']) ? $result['error'] : 'Une erreur s\'est produite.');
                    }

                    $linkMyReco = ((new Link())->getModuleLink('myvetshopclinique', 'myreco'));
                    Tools::redirect($linkMyReco . '?add=true#anchor-reco-' . $result['id']);
                } catch (Exception $exception) {
                    $linkMyReco = ((new Link())->getModuleLink('myvetshopclinique', 'myreco'));
                    Tools::redirect($linkMyReco . '?add=false#header');
                }
            }

            // Liste des animaux si le code est ok
            assert($reco instanceof Recommandation);

            $result = Db::getInstance(false)
                ->executeS(
                    'SELECT a.*'
                    . ' FROM `' . _DB_PREFIX_ . 'animal` a'
                    . ' WHERE `a`.`id_customer` = ' . (int) $this->context->customer->id
                    . ' AND `a`.`deleted` = 0'
                    . ' AND `a`.`espece` = "' . strtolower($reco->espece) . '"'
                );

            if (!is_array($result)) {
                $result = [];
            }

            $animaux = ObjectModel::hydrateCollection(
                Animal::class, $result
            );

            // Cheche si un animal correspond à la reco
            $animalDefaultSelected = array_values(array_filter(
                $animaux,
                function ($animal) use ($reco) {
                    return ($animal->nom === $reco->petname) && ($animal->espece === $reco->espece);
                }
            ));

            // Création d'un animal pour le choix "création d'une nouvelle fiche"
            $newAnimal = new Animal();

            $newAnimal->id = '_new';
            $newAnimal->nom = $reco->petname;
            $newAnimal->espece = strtolower($reco->espece);
            $animaux = array_merge([$newAnimal], $animaux);

            $animalDefaultSelected = count($animalDefaultSelected) > 0 ? $animalDefaultSelected[0] : $newAnimal;

            $this->context->smarty->assign(
                [
                    'animalDefaultSelected' => $animalDefaultSelected,
                    'animals' => $animaux,
                    'errorCodeReco' => $error,
                    'reco' => $reco,
                    'codeReco' => $codeReco,
                ]
            );
        } catch (Exception $exception) {
            $this->context->smarty->assign(
                [
                    'errorCodeReco' => $exception->getMessage(),
                    'reco' => $reco,
                    'codeReco' => $codeReco,
                ]);
        }

        $this->setTemplate('my_reco.tpl');
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function processPdf(): void
    {
        // Vérifie qu'un code a bien été rentré
        $idReco = Tools::getValue('id_reco', null);

        if (!$idReco) {
            Tools::redirect((new Link())->getPageLink('my-account', true));
        }

        $recomandation = new Recommandation($idReco);

        if ($recomandation->id_customer != $this->context->customer->id) {
            Tools::redirect((new Link())->getPageLink('my-account', true));
        }

        $api = new CricCrocApi();
        $pdf = $api->getPdf($recomandation->code_reco);

        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename=' . (int) $recomandation->id . '.pdf;');
        echo $pdf;
        exit();
    }
}
