<?php

/**
 * Copyright distrib (2018)
 *
 * contact@opendistrib.net
 *
 * 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 backend\controllers;

use common\models\DeliveryNote;
use common\models\PointSale;
use common\models\Product;
use common\models\User;
use common\models\Document;
use common\helpers\GlobalParam;
use common\models\Order;
use common\models\UserProducer;
use yii\base\UserException;
use yii;

class DocumentController extends BackendController
{
        public function behaviors()
        {
                return [
                        'verbs' => [
                                'class' => VerbFilter::className(),
                                'actions' => [
                                ],
                        ],
                        'access' => [
                                'class' => AccessControl::className(),
                                'rules' => [
                                        [
                                                'allow' => true,
                                                'roles' => ['@'],
                                                'matchCallback' => function ($rule, $action) {
                                                        return User::hasAccessBackend();
                                                }
                                        ]
                                ],
                        ],
                ];
        }

        public function actionCreate()
        {
                $class = $this->getClass();
                $model = new $class();

                if ($model->load(Yii::$app->request->post())) {

                        $model->id_producer = GlobalParam::getCurrentProducerId();

                        if ($model->save()) {

                                $this->processInvoiceViaDeliveryNotes($model) ;

                                Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('create', $model));
                                return $this->redirect(['/' . $this->getControllerUrl() . '/update', 'id' => $model->id]);
                        } else {
                                Yii::$app->getSession()->setFlash('error', 'Un problème est survenu lors de la création du document.');
                        }
                }

                return $this->render('/document/create', [
                        'title' => $this->getTitle('Ajouter'),
                        'typeDocument' => $this->getDocumentType(),
                        'model' => $model,
                ]);
        }

        public function processInvoiceViaDeliveryNotes($model)
        {
                if($model->getClass() == 'Invoice') {
                        if($model->deliveryNotes && is_array($model->deliveryNotes) && count($model->deliveryNotes)) {
                                foreach($model->deliveryNotes as $key => $idDeliveryNote) {
                                        Order::updateAll([
                                                'id_invoice' => $model->id
                                        ], [
                                                'id_delivery_note' => $idDeliveryNote
                                        ]) ;
                                }
                        }
                }
        }

        /**
         * Modifie un modèle Produit existant.
         * Si la modification réussit, le navigateur est redirigé vers la page 'index'.
         *
         * @param integer $id
         * @return mixed
         */
        public function actionUpdate($id)
        {
                $model = $this->findModel($id);

                if(!$model) {
                        throw new NotFoundHttpException('Le document n\'a pas été trouvé.');
                }

                if ($model && $model->load(Yii::$app->request->post()) && $model->save()) {
                        Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('update', $model));
                }

                return $this->render('/document/update', [
                        'title' => $this->getTitle('Modifier'),
                        'typeDocument' => $this->getDocumentType(),
                        'model' => $model,
                ]);
        }

        public function actionDelete($id)
        {
                $model = $this->findModel($id);

                if ($model->isStatusValid()) {
                        throw new UserException('Vous ne pouvez pas supprimer un document validé.');
                }

                $model->delete();

                if($this->getClass() == 'DeliveryNote') {
                        Order::updateAll([
                                'order.id_delivery_note' => null
                        ], [
                                'order.id_delivery_note' => $id
                        ]);
                }

                if($this->getClass() == 'Quotation') {
                        Order::updateAll([
                                'order.id_quotation' => null
                        ], [
                                'order.id_quotation' => $id
                        ]);
                }

                if($this->getClass() == 'Invoice') {
                        Order::updateAll([
                                'order.id_invoice' => null
                        ], [
                                'order.id_invoice' => $id
                        ]);
                }

                Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('delete', $model));
                $this->redirect([$this->getControllerUrl().'/index']);
        }

        public function actionDownload($id)
        {
                $document = $this->findModel($id);
                return $document->generatePdf(Pdf::DEST_BROWSER) ;
        }

        public function actionSend($id)
        {
                $document = $this->findModel($id) ;
                if($document->send()) {
                        Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('send', $document));
                }
                else {
                        Yii::$app->getSession()->setFlash('danger', $this->getFlashMessage('send', $document));
                }
                $this->redirect([$this->getControllerUrl().'/index']);
        }

        public function actionAjaxUserInfos($typeAction, $idUser, $classDocument, $idDocument = false)
        {
                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                if ($idUser > 0) {
                        $user = User::searchOne([
                                'id' => $idUser
                        ]);

                        if ($user) {

                                $document = null ;
                                if(Document::isValidClass($classDocument)) {
                                        $document = $classDocument::searchOne([
                                                'id' => $idDocument,
                                                'id_user' => $idUser
                                        ]) ;
                                }

                                if($document && $document->id_user == $user->id) {
                                        $address = $document->address ;
                                }
                                else {
                                        $address = $user->getFullAddress() ;
                                }

                                $json = [
                                        'return' => 'success',
                                        'address' => $address
                                ];

                                if($classDocument == 'Invoice') {
                                        if($typeAction == 'create') {
                                                $deliveryNotesArray = DeliveryNote::searchAll([
                                                        'id_user' => $user->id,
                                                        'status' => Document::STATUS_VALID
                                                ]) ;
                                        }
                                        elseif($typeAction == 'update' && $idDocument > 0) {
                                                $deliveryNotesArray = DeliveryNote::searchAll([
                                                        'id_user' => $user->id,
                                                        'status' => Document::STATUS_VALID,
                                                        'order.id_invoice' => $idDocument
                                                ]) ;
                                        }

                                        if(isset($deliveryNotesArray)) {
                                                $json['delivery_notes'] = [] ;

                                                foreach($deliveryNotesArray as $deliveryNote) {
                                                        $json['delivery_notes'][] = array_merge(
                                                                $deliveryNote->getAttributes(),
                                                                [
                                                                        'total' => $deliveryNote->getAmountWithTax(Order::INVOICE_AMOUNT_TOTAL)
                                                                ]
                                                        ) ;
                                                }
                                        }
                                }

                                return $json ;
                        }
                }

                return ['return' => 'error'];
        }

        public function actionValidate($id)
        {
                $classDocument = $this->getClass();

                if ($id > 0 && Document::isValidClass($classDocument)) {
                        $document = $classDocument::searchOne([
                                'id' => $id
                        ]);

                        if ($document) {
                                $document->changeStatus(Document::STATUS_VALID);
                                $document->save();
                                Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('validate', $document));
                                return $this->redirect([$this->getControllerUrl().'/index']);
                        }
                }

                Yii::$app->getSession()->setFlash('danger', 'Une erreur est survenue lors de la validation du document.');
                return $this->redirect([$this->getControllerUrl().'/index']);
        }

        public function actionAjaxValidateDocument($idDocument, $classDocument)
        {
                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                if ($idDocument > 0 && Document::isValidClass($classDocument)) {
                        $document = $classDocument::searchOne([
                                'id' => $idDocument
                        ]);

                        if ($document) {
                                $document->changeStatus(Document::STATUS_VALID);
                                $document->save();
                                return [
                                        'return' => 'success',
                                        'alert' => [
                                                'type' => 'success',
                                                'message' => 'Document validé'
                                        ]
                                ];
                        }
                }

                return [
                        'return' => 'error',
                        'alert' => [
                                'type' => 'danger',
                                'message' => 'Une erreur est survenue lors de la validation du document.'
                        ]
                ];
        }

        public function actionAjaxInit($idDocument, $classDocument)
        {
                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                if ($idDocument > 0 && Document::isValidClass($classDocument)) {

                        $document = $classDocument::searchOne([
                                'id' => $idDocument
                        ]);

                        if ($document) {

                                $productsArray = Product::searchAll();

                                $ordersArray = [];
                                foreach ($document->orders as $order) {
                                        $order->init();
                                        $productsOrderArray = [];
                                        foreach ($order->productOrder as $productOrder) {
                                                $productsOrderArray[$productOrder->id] = $productOrder->getAttributes();
                                        }
                                        $ordersArray[$order->id] = array_merge(
                                                $order->getAttributes(),
                                                [
                                                        'username' => $order->getUsername(),
                                                        'distribution_date' => isset($order->distribution) ? date('d/m/Y', strtotime($order->distribution->date)) : null,
                                                        'point_sale_name' => isset($order->pointSale) ? $order->pointSale->name : null,
                                                        'productOrder' => $productsOrderArray,
                                                ]
                                        );
                                }

                                $userProducer = UserProducer::searchOne([
                                        'id_user' => $document->user->id,
                                        'id_producer' => GlobalParam::getCurrentProducerId()
                                ]) ;
                                $pointSale = PointSale::searchOne([
                                        'id_user' => $document->user->id
                                ]) ;

                                return [
                                        'return' => 'success',
                                        'tax_rate_producer' => GlobalParam::getCurrentProducer()->taxRate->value,
                                        'document' => array_merge($document->getAttributes(), [
                                                'html_label' => $document->getHtmlLabel(),
                                                'class' => $document->getClass()
                                        ]),
                                        'id_user' => $document->user->id,
                                        'products' => ArrayHelper::map($productsArray, 'id', function ($product) use ($document, $userProducer, $pointSale) {
                                                return array_merge($product->getAttributes(), [
                                                        'price_with_tax' => $product->getPriceWithTax([
                                                                'user' => $document->user,
                                                                'user_producer' => $userProducer,
                                                                'point_sale' => $pointSale,
                                                        ]),
                                                        'wording_unit' => $product->wording_unit,
                                                        'tax_rate' => $product->taxRate->value
                                                ]);
                                        }),
                                        'orders' => $ordersArray,
                                        'total' => ($document->getClass() == 'Invoice' || $document->getClass() == 'DeliveryNote') ? $document->getAmount(Order::INVOICE_AMOUNT_TOTAL) : $document->getAmount(Order::AMOUNT_TOTAL),
                                        'total_with_tax' => ($document->getClass() == 'Invoice' || $document->getClass() == 'DeliveryNote') ? $document->getAmountWithTax(Order::INVOICE_AMOUNT_TOTAL) : $document->getAmountWithTax(Order::AMOUNT_TOTAL),
                                ];
                        }
                }

                return ['return' => 'error'];
        }

        public function actionAjaxAddProduct($idDocument, $classDocument, $idProduct, $quantity, $price)
        {

                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                if (Document::isValidClass($classDocument)) {
                        $document = $classDocument::searchOne([
                                'id' => $idDocument
                        ]);
                        $product = Product::searchOne([
                                'id' => $idProduct
                        ]);

                        if ($document && $product) {
                                if (count($document->orders) == 0) {
                                        $order = new Order;
                                        $order->id_user = $document->id_user;
                                        $order->id_point_sale = null;
                                        $order->id_distribution = null;
                                        $order->status = 'tmp-order' ;
                                        $order->origin = Order::ORIGIN_ADMIN;
                                        $order->date = date('Y-m-d H:i:s');
                                        $fieldIdDocument = 'id_' . $classDocument::tableName();
                                        $order->$fieldIdDocument = $document->id;
                                        $order->save();
                                } else {
                                        $order = $document->orders[0];
                                }

                                if ($order) {

                                        $productOrder = new ProductOrder;
                                        $productOrder->id_order = $order->id;
                                        $productOrder->id_product = $idProduct;
                                        $quantity = $quantity / Product::$unitsArray[$product->unit]['coefficient'];
                                        $productOrder->quantity = $quantity;
                                        $productOrder->price = (float)$price;
                                        $productOrder->unit = $product->unit;
                                        $productOrder->step = $product->step;
                                        $productOrder->id_tax_rate = $product->taxRate->id ;
                                        $productOrder->save();

                                        return [
                                                'return' => 'success',
                                                'alert' => [
                                                        'type' => 'success',
                                                        'message' => 'Produit ajouté'
                                                ]
                                        ];
                                }
                        }

                }

                return [
                        'return' => 'error',
                        'alert' => [
                                'type' => 'danger',
                                'message' => 'Une erreur est survenue lors de la suppression du produit.'
                        ]
                ];
        }

        public function actionAjaxDeleteProductOrder($idProductOrder)
        {
                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                $productOrder = ProductOrder::searchOne([
                        'id' => $idProductOrder
                ]);

                if ($productOrder) {
                        $productOrder->delete();

                        return [
                                'return' => 'success',
                                'alert' => [
                                        'type' => 'danger',
                                        'message' => 'Produit supprimé'
                                ]
                        ];
                }

                return [
                        'return' => 'error',
                        'alert' => [
                                'type' => 'danger',
                                'message' => 'Une erreur est survenue lors de la suppression du produit.'
                        ]
                ];
        }

        public function getClass()
        {
                $class = get_class($this);
                $class = str_replace('Controller', '', $class);
                $class = str_replace('backend\controllers\\', '', $class);
                return $class;
        }

        public function getDocumentType()
        {
                $class = $this->getClass();

                if ($class == 'Invoice') {
                        $documentType = 'Facture';
                } elseif ($class == 'DeliveryNote') {
                        $documentType = 'Bon de livraison';
                } elseif ($class == 'Quotation') {
                        $documentType = 'Devis';
                }

                if (isset($documentType)) {
                        return $documentType;
                }

                return '';
        }

        public function getFlashMessage($type = 'create', $model)
        {
                $class = $this->getClass();

                $message = $this->getDocumentType();
                $message .= ' <strong>' . Html::encode($model->name) . '</strong> ';

                if ($type == 'create') {
                        $message .= 'ajouté';
                } elseif ($type == 'update') {
                        $message .= 'modifié';
                } elseif ($type == 'delete') {
                        $message .= 'supprimé';
                } elseif ($type == 'validate') {
                        $message .= 'validé';
                } elseif ($type == 'send') {
                        $message .= 'envoyé';
                }

                if ($class == 'Invoice') {
                        $message .= 'e';
                }

                return $message;
        }

        protected function getTitle($prepend)
        {
                $class = $this->getClass();

                switch ($class) {
                        case 'Invoice' :
                                $title = $prepend . ' une facture';
                                break;
                        case 'DeliveryNote' :
                                $title = $prepend . ' un bon de livraison';
                                break;
                        case 'Quotation' :
                                $title = $prepend . ' un devis';
                                break;
                }

                return $title;
        }

        public function getControllerUrl()
        {
                $path = strtolower($this->getClass());
                $path = str_replace('deliverynote', 'delivery-note', $path);
                return $path;
        }

        /**
         * Recherche un Document en fonction de son ID.
         *
         * @param integer $id
         * @return Document
         * @throws NotFoundHttpException si le modèle n'est pas trouvé
         */
        protected function findModel($id)
        {
                $class = $this->getClass();

                $model = $class::searchOne([
                        'id' => $id
                ], [
                        'orderby' => 'teshtygjhtyt'
                ]);

                if ($model) {
                        return $model;
                } else {
                        throw new NotFoundHttpException('The requested page does not exist.');
                }
        }

}
