<?php

/**
 * Copyright Souke (2018)
 *
 * contact@souke.fr
 *
 * Ce logiciel est un programme informatique servant à aider les producteurs
 * à distribuer leur production en circuits courts.
 *
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
 * sur le site "http://www.cecill.info".
 *
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 *
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement,
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
 *
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 */

namespace producer\controllers;

use common\forms\SubscriptionForm;
use common\helpers\GlobalParam;
use domain\Config\Unit\UnitDefinition;
use domain\Subscription\ProductSubscription\ProductSubscription;
use domain\Subscription\Subscription\Subscription;
use domain\Subscription\Subscription\SubscriptionSearch;
use yii\base\UserException;
use yii\filters\AccessControl;
use yii\web\NotFoundHttpException;

class SubscriptionController extends ProducerBaseController
{
    var $enableCsrfValidation = false;

    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ]
                ],
            ],
        ];
    }

    /**
     * Liste les abonnements de l'utilisateur.
     */
    public function actionIndex()
    {
        if (\Yii::$app->user->isGuest) {
            $producer = $this->getProducerCurrent();
            return $this->redirect($this->getUrlManagerFrontend()->createAbsoluteUrl(['site/producer', 'id' => $producer->id]));
        }

        $searchModel = new SubscriptionSearch();
        $searchModel->id_user = GlobalParam::getCurrentUserId();
        $dataProvider = $searchModel->search(\Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider
        ]);
    }

    public function actionAjaxProcess()
    {
        $orderModule = $this->getOrderModule();
        $subscriptionModule = $this->getSubscriptionModule();
        $model = new SubscriptionForm();
        $model->id_producer = GlobalParam::getCurrentProducerId();
        $model->id_user = GlobalParam::getCurrentUserId();

        $posts = \Yii::$app->request->post();

        $idSubscription = (int)$posts['idSubscription'];
        $isUpdate = false;
        if ($idSubscription) {
            $subscription = $subscriptionModule->findOneSubscriptionById($idSubscription);

            if ($subscription) {
                $model->id = $idSubscription;
                $isUpdate = true;
            }
        }

        if ($model->load($posts) && $model->validate() && $model->save()) {

            $subscription = $subscriptionModule->getRepository()->findOneSubscriptionById($model->id);
            $orderModule->getManager()
                ->updateOrdersIncomingDistributionsFromSubscription($subscription, $this->getUserCurrent(), $isUpdate);

            if ($isUpdate) {
                $this->setFlash('success', "L'abonnement a bien été modifié");
            } else {
                $this->setFlash('success', "L'abonnement a bien été ajouté");
            }
        }
    }

    /**
     * Crée un abonnement
     */
    public function actionForm(int $id = 0)
    {
        if (\Yii::$app->user->isGuest) {
            $producer = $this->getProducerCurrent();
            return $this->redirect($this->getUrlManagerFrontend()->createAbsoluteUrl(['site/producer', 'id' => $producer->id]));
        }

        $subscriptionModule = $this->getSubscriptionModule();
        if($id) {
            $subscription = $subscriptionModule->getRepository()->findOneSubscriptionById($id);
            if(!$subscription) {
                $this->setFlash('error', "L'abonnement est introuvable");
                return $this->redirect(['subscription/index']);
            }
        }

        return $this->render('form', [
            'idSubscription' => $id
        ]);
    }

    /**
     * Modifie une commande récurrente.
     */
    public function actionUpdate(int $id)
    {
        if (\Yii::$app->user->isGuest) {
            $producer = $this->getProducerCurrent();
            return $this->redirect($this->getUrlManagerFrontend()->createAbsoluteUrl(['site/producer', 'id' => $producer->id]));
        }

        $subscriptionModule = $this->getSubscriptionModule();
        $model = new SubscriptionForm;
        $subscription = $subscriptionModule->findOneSubscriptionById($id);

        if ($subscription) {
            $model->id = $id;
            $model->id_producer = $subscription->id_producer;
            $model->id_user = $subscription->id_user;
            $model->username = $subscription->username;
            $model->id_point_sale = $subscription->id_point_sale;
            $model->date_begin = date('d/m/Y', strtotime($subscription->date_begin));
            if (strlen($subscription->date_end)) {
                $model->date_end = date('d/m/Y', strtotime($subscription->date_end));
            }

            $model->monday = $subscription->monday;
            $model->tuesday = $subscription->tuesday;
            $model->wednesday = $subscription->wednesday;
            $model->thursday = $subscription->thursday;
            $model->friday = $subscription->friday;
            $model->saturday = $subscription->saturday;
            $model->sunday = $subscription->sunday;
            $model->auto_payment = Subscription::AUTO_PAYMENT_DEDUCTED;
            $model->week_frequency = $subscription->week_frequency;

            // produits
            $arrayProductsSubscription = ProductSubscription::searchAll([
                'id_subscription' => $model->id
            ]);

            foreach ($arrayProductsSubscription as $productSubscription) {
                $model->products['product_' . $productSubscription->id_product] = $productSubscription->quantity;
            }
        } else {
            throw new NotFoundHttpException('L\'abonnement est introuvable.', 404);
        }

        $productsArray = $this->getProductModule()->findProducts();

        if ($model->load(\Yii::$app->request->post()) && $model->validate()) {
            if (!strlen($model->date_end)) {
                $model->date_end = null;
            }
            if ($model->save()) {
                $this->setFlash('success', 'Abonnement modifié');

                $subscription = $subscriptionModule->findOneSubscriptionById($model->id);
                $matchedDistributionsArray = $this-> getDistributionModule()->findDistributionsIncomingMatchWithSubscrtiption($subscription);

                if (count($matchedDistributionsArray)) {
                    return $this->redirect(
                        [
                            'subscription/update-distributions',
                            'idSubscription' => $subscription->id,
                            'update' => true
                        ]
                    );
                } else {
                    return $this->redirect(['subscription/index']);
                }
            }
        }

        return $this->render('update', [
            'model' => $model,
            'productsArray' => $productsArray
        ]);
    }

    /**
     * Supprime un abonnement.
     */
    public function actionDelete($id)
    {
        if (\Yii::$app->user->isGuest) {
            $producer = $this->getProducerCurrent();
            return $this->redirect($this->getUrlManagerFrontend()->createAbsoluteUrl(['site/producer', 'id' => $producer->id]));
        }

        $subscriptionModule = $this->getSubscriptionModule();
        $subscription = $subscriptionModule->getRepository()->findOneSubscriptionById($id);

        if($subscription) {
            $subscriptionModule->getBuilder()->deleteSubscription($subscription);
            // @TODO : gérer via événements
            $this->getOrderModule()->getManager()
                ->deleteOrdersIncomingDistributionsFromSubscription($subscription, $this->getUserCurrent());

            $this->setFlash('success', "L'abonnement a bien été modifié");
        }
        else {
            $this->setFlash('error', 'Abonnement introuvable');
        }


        return $this->redirect(['subscription/index']);
    }

    public function actionAjaxInfos($idSubscription = 0)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $params = [];
        $productModule = $this->getProductModule();
        $subscriptionModule = $this->getSubscriptionModule();
        $user = $this->getUserCurrent();
        $userProducer = $this->getUserProducerModule()->findOneUserProducer($this->getUserCurrent());
        $pointSale = null;

        if ($idSubscription > 0) {
            $arrayProductsSubscription = ProductSubscription::searchAll([
                'id_subscription' => $idSubscription
            ]);

            $subscription = $subscriptionModule->findOneSubscriptionById($idSubscription);
            if ($subscription && $subscription->id_point_sale) {
                $pointSale = $this->getPointSaleModule()->findOnePointSaleById($subscription->id_point_sale);
            }
        }

        // Produits
        $productsArray = $productModule->findProducts();
        $indexProduct = 0;
        foreach ($productsArray as &$product) {
            $quantity = 0;
            $coefficientUnit = $productModule->getSolver()->getUnitCoefficient($product);
            if (isset($arrayProductsSubscription) && count($arrayProductsSubscription)) {
                foreach ($arrayProductsSubscription as $productSubscription) {
                    if ($product->id == $productSubscription->id_product) {
                        $coefficientUnit = $productModule->getSolver()->getUnitCoefficient($productSubscription->product);
                        $quantity = $productSubscription->quantity * $coefficientUnit;
                    }
                }
            }

            $productPointSaleArray = [];
            foreach($product->productPointSale as $productPointSale) {
                $productPointSaleArray[] = $productPointSale->id_point_sale;
            }

            $product = array_merge(
                $product->getAttributes(),
                [
                    'index' => $indexProduct++,
                    'quantity_form' => $quantity,
                    'coefficient_unit' => $coefficientUnit,
                    'wording_unit' => $productModule->getSolver()->strUnit($product, UnitDefinition::WORDING_UNIT, true),
                    'wording_short' => $productModule->getSolver()->strUnit($product),
                    'price_with_tax' => $productModule->getPriceWithTax($product, [
                        'user' => $user,
                        'user_producer' => $userProducer,
                        'point_sale' => $pointSale
                    ]),
                    'product_point_sale_array' => $productPointSaleArray
                ]
            );

            if($product['unit'] == 'piece' && is_null($product['step'])) {
                $product['step'] = 1;
            }
        }

        $params['products'] = $productsArray;
        
        $pointsSaleArray = $this->getPointSaleModule()->findPointSalesByUserAccess($user);
        foreach ($pointsSaleArray as &$pointSale) {
            $pointSale = array_merge($pointSale->getAttributes(), [
                'userPointSale' => ($pointSale->userPointSale ? $pointSale->userPointSale[0] : '')
            ]);
            if ($pointSale['code'] && strlen($pointSale['code'])) {
                $pointSale['code'] = '***';
            }
        }

        $params['points_sale'] = $pointsSaleArray;

        if ($idSubscription > 0) {
            $subscription = $subscriptionModule->findOneSubscriptionById($idSubscription);

            if (!$subscription || $subscription->id_user != GlobalParam::getCurrentUserId()) {
                throw new UserException('Abonnement introuvable');
            } else {
                $params = array_merge($params, $subscription->getAttributes());
            }
        }

        return $params;
    }

    /**
     * Vérifie le code saisi pour un point de vente.
     */
    public function actionAjaxValidateCodePointSale($idPointSale, $code)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $pointSaleModule = $this->getPointSaleModule();
        $pointSale = $pointSaleModule->findOnePointSaleById($idPointSale);

        if ($pointSale && $pointSaleModule->validateCode($pointSale, $code)) {
            return 1;
        }

        return 0;
    }
}