<?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 backend\controllers;

use common\helpers\Ajax;
use common\helpers\CSV;
use common\helpers\GlobalParam;
use common\helpers\MeanPayment;
use common\helpers\Price;
use domain\Document\DeliveryNote\DeliveryNote;
use domain\Document\Document\Document;
use domain\Document\Invoice\Invoice;
use domain\Document\Quotation\Quotation;
use domain\Feature\Feature\Feature;
use domain\Order\Order\Order;
use domain\Order\OrderStatus\OrderStatus;
use domain\Order\ProductOrder\ProductOrder;
use domain\Payment\Payment;
use kartik\mpdf\Pdf;
use domain\Product\Product\Product;
use yii;
use yii\base\UserException;
use yii\filters\AccessControl;
use yii\helpers\Html;
use yii\web\NotFoundHttpException;

class DocumentController extends BackendController
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                        'matchCallback' => function ($rule, $action) {
                            return $this->getUserModule()
                                ->getAuthorizationChecker()
                                ->isGrantedAsProducer($this->getUserCurrent());
                        }
                    ]
                ],
            ],
        ];
    }

    public function actionGeneratePdfValidatedDocuments()
    {
        set_time_limit(0);

        $validatedDocumentsArray = array_merge(
            Quotation::find()->where(['status' => Document::STATUS_VALID])->all(),
            DeliveryNote::find()->where(['status' => Document::STATUS_VALID])->all(),
            Invoice::find()->where(['status' => Document::STATUS_VALID])->all()
        );

        foreach ($validatedDocumentsArray as $document) {
            if (!file_exists($document->getFilenameComplete())) {
                $document->generatePdf(Pdf::DEST_FILE);
            }
        }
    }

    public function actionCreate()
    {
        $documentModule = $this->getDocumentModule();

        $class = $this->getClass();
        $class = 'domain\\Document\\'.$class.'\\'.$class;
        $model = new $class();

        $documentModule->initTaxCalculationMethod($model);

        if ($model->load(\Yii::$app->request->post())) {
            $model->id_producer = GlobalParam::getCurrentProducerId();

            if ($model->save()) {
                $this->processInvoiceViaDeliveryNotes($model);
                $this->processInvoiceViaOrders($model);

                $this->setFlash('success', $this->getFlashMessage('create', $model));
                return $this->redirect(['/' . $this->getControllerUrl() . '/update', 'id' => $model->id]);
            } else {
                $this->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)
    {
        $orderModule = $this->getOrderModule();
        $documentModule = $this->getDocumentModule();
        $deliveryNoteModule = $this->getDeliveryNoteModule();
        if ($documentModule->getClass($model) == 'Invoice') {
            if ($model->deliveryNotes && is_array($model->deliveryNotes) && count($model->deliveryNotes)) {
                foreach ($model->deliveryNotes as $key => $idDeliveryNote) {
                    $deliveryNote = $deliveryNoteModule->findOneDeliveryNoteById($idDeliveryNote);
                    $orderModule->assignAllOrdersInvoiceByDeliveryNote($model, $deliveryNote);
                }
            }
        }
    }

    public function processInvoiceViaOrders($model)
    {
        $orderModule = $this->getOrderModule();
        $documentModule = $this->getDocumentModule();
        if ($documentModule->getClass($model) == 'Invoice') {
            if ($model->ordersOnCreate && is_array($model->ordersOnCreate) && count($model->ordersOnCreate)) {
                foreach ($model->ordersOnCreate as $key => $idOrder) {
                    $order = $orderModule->findOneOrderById($idOrder);
                    $orderModule->updateOrderInvoice($order, $model);
                    $orderModule->getBuilder()->updateOrderInvoicePrices($order,
                        [
                            'user' => $model->user,
                            'user_producer' => $this->getUserProducerModule()->getRepository()
                                ->findOneUserProducer($model->user),
                            'point_sale' => $order->pointSale
                        ]);
                }
            }
        }
    }

    public function actionUpdate($id)
    {
        $documentModule = $this->getDocumentModule();
        $paymentManager = $this->getPaymentModule();
        $document = $this->findModel($id);

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

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

        $payment = null;
        if($documentModule->isDocumentInvoice($document) && $documentModule->isStatusValid($document)) {
            $payment = $paymentManager->instanciatePayment(
                Payment::TYPE_PAYMENT,
                number_format($documentModule->getAmountWithTax($document, Order::INVOICE_AMOUNT_TOTAL), 2),
                $this->getProducerCurrent(),
                null,
                null,
                MeanPayment::TRANSFER,
                null,
                null,
                null,
                $document
            );
            $payment->amount = number_format($payment->amount, 2);

            $posts = \Yii::$app->request->post();
            if(isset($posts['Payment']['date_transaction']) && $posts['Payment']['date_transaction']) {
                $posts['Payment']['date_transaction'] = date('Y-m-d', strtotime(str_replace('/', '-', $posts['Payment']['date_transaction'])));
            }

            if ($payment->load($posts) && $payment->save()) {
                $this->setFlash('success', 'Le règlement a bien été ajouté.');
                return $this->redirect(['invoice/update', 'id' => $document->id]);
            }
            else {
                if($payment->date_transaction) {
                    $payment->date_transaction = date('d/m/Y', strtotime($payment->date_transaction));
                }
            }
        }

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

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

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

        $documentModule->delete($model);

        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
            ]);
        }

        $this->setFlash('success', $this->getFlashMessage('delete', $model));

        $this->redirect([$this->getControllerUrl() . '/index']);
    }

    public function actionExportCsvEvoliz(int $id)
    {
        if(!$this->getFeatureModule()->getChecker()->isEnabled(Feature::ALIAS_BRIDGE_EVOLIZ)) {
            throw new yii\web\UnauthorizedHttpException("Vous n'êtes pas autorisé à effectuer cette action.");
        }

        $documentModule = $this->getDocumentModule();
        $productOrderModule = $this->getProductOrderModule();

        $datas = [];
        $document = $this->findModel($id);

        // données
        $datas[] = [
            'N° facture externe *',
            'Date facture *',
            'Client',
            'Code client *',
            'Total TVA',
            'Total HT',
            'Total TTC',
            'Total réglé',
            'Etat',
            'Date Etat',
            'Date de création',
            'Objet',
            'Date d\'échéance',
            'Date d\'exécution',
            'Taux de pénalité',
            'Frais de recouvrement',
            'Taux d\'escompte',
            'Conditions de règlement *',
            'Mode de paiement',
            'Remise globale',
            'Acompte',
            'Nombre de relance',
            'Commentaires',
            'N° facture',
            'Annulé',
            'Catalogue',
            'Réf.',
            'Désignation *',
            'Qté *',
            'Unité',
            'PU HT *',
            'Remise',
            'TVA',
            'Total TVA',
            'Total HT',
            'Classification vente',
            'Code Classification vente',
        ];

        foreach ($documentModule->getProductsOrders($document, true) as $productOrderArray) {
            foreach ($productOrderArray as $productOrder) {

                $price = $productOrder->getPrice();
                if ($documentModule->isInvoicePrice($document) && $productOrder->getInvoicePrice()) {
                    $price = $productOrder->getInvoicePrice();
                }

                $typeTotal = $documentModule->isInvoicePrice($document) ? Order::INVOICE_AMOUNT_TOTAL : Order::AMOUNT_TOTAL;
                $priceTotal = $productOrderModule->getPriceByTypeTotal($productOrder, $typeTotal) * $productOrder->quantity;
                $tva = Price::getVat(
                    $priceTotal,
                    $productOrder->taxRate->value,
                    $document->tax_calculation_method
                );

                $datas[] = [
                    $document->reference,   // N° facture externe *
                    date('d/m/Y', strtotime($document->date)),        // Date facture *
                    '', // Client
                    $document->user->evoliz_code, // Code client *
                    '', // Total TVA
                    '', // Total HT
                    '', // Total TTC
                    '', // Total réglé
                    '', // Etat
                    '', // Date Etat
                    '', // Date de création
                    $document->name, // Objet
                    '', // Date d'échéance
                    '', // Date d'exécution
                    '', // Taux de pénalité
                    '', // Frais de recouvrement
                    '', // Taux d\'escompte
                    'A réception', // Conditions de règlement *
                    '', // Mode de paiement
                    '', // Remise globale
                    '', // Acompte
                    '', // Nombre de relance
                    '', // Commentaires
                    '', // N° facture
                    '', // Annulé
                    'Non', // Catalogue
                    '', // Réf.
                    $productOrder->product->name, // Désignation *
                    $productOrder->quantity, // Qté *
                    '', // Product::strUnit($productOrder->unit, 'wording'), // Unité
                    $price, // PU HT *
                    '', // Remise
                    $productOrder->taxRate->value * 100, // TVA
                    $tva, // Total TVA
                    $priceTotal, // Total HT
                    '', // Classification vente
                    '01', // Code Classification vente
                ];
            }
        }

        // nom fichier
        $reference = $document->id;
        if ($document->reference && strlen($document->reference)) {
            $reference = $document->reference;
        }

        // status
        $status = '';
        if ($documentModule->isStatusDraft($document)) {
            $status = 'brouillon_';
        }

        CSV::downloadSendHeaders(strtolower($this->getDocumentType()) . '_' . $status . $reference . '.csv');
        echo CSV::array2csv($datas);
        die();
    }

    public function actionDownload($id)
    {
        $documentModule = $this->getDocumentModule();
        $document = $this->findModel($id);

        return $documentModule->downloadPdf($document);
    }

    public function actionRegenerate($id)
    {
        $documentModule = $this->getDocumentModule();
        $document = $this->findModel($id);
        $documentModule->downloadPdf($document, true);
        $this->setFlash('success', 'Le document PDF a bien été regénéré.');

        return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]);
    }

    public function actionSend(int $id, $backUpdateForm = false)
    {
        $documentModule = $this->getDocumentModule();
        $document = $this->findModel($id);
        if ($documentModule->sendDocument($document)) {
            $this->setFlash('success', $this->getFlashMessage('send', $document));
        } else {
            $this->setFlash('danger', $this->getFlashMessage('send', $document));
        }

        if ($backUpdateForm) {
            return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]);
        } else {
            return $this->redirectReferer();
        }
    }

    public function actionAjaxUserInfos($typeAction, $idUser, $classDocument, $idDocument = false)
    {
        $userModule = $this->getUserModule();
        $documentModule = $this->getDocumentModule();
        $orderModule = $this->getOrderModule();
        $producerModule = $this->getProducerModule();
        $invoiceModule = $this->getInvoiceModule();
        $deliveryNoteModule = $this->getDeliveryNoteModule();

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

        if ($idUser > 0) {
            $user = $userModule->findOneUserById($idUser);

            if ($user) {
                $document = null;
                if ($documentModule->isValidClass($classDocument) && $idDocument) {
                    $document = $this->findModel($idDocument, $classDocument);
                }

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

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

                if ($classDocument == 'Invoice') {
                    $deliveryNotesCreateArray = DeliveryNote::searchAll([
                        'id_user' => $user->id,
                        'status' => Document::STATUS_VALID,
                        'ignore_when_invoicing' => null
                    ], [
                        'orderby' => 'distribution.date ASC',
                        'join_with' => ['user AS user_delivery_note', 'orders', 'producer']
                    ]);
                    $invoice = $idDocument ? $invoiceModule->getRepository()->findOneInvoiceById($idDocument) : null;
                    $deliveryNotesUpdateArray = $invoice ? $deliveryNoteModule->getRepository()->findDeliveryNotesByInvoice($invoice) : null;
                    $json['delivery_note_create_array'] = $this->initDeliveryNoteArray('create', $deliveryNotesCreateArray);
                    $json['delivery_note_update_array'] = $this->initDeliveryNoteArray('update', $deliveryNotesUpdateArray);

                    $json['orders_create_array'] = [];
                    $json['orders_update_array'] = [];
                    if(!$producerModule->getConfig('option_invoice_only_based_on_delivery_notes')) {
                        $json['orders_create_array'] = $this->initOrdersArray($orderModule->findOrdersByUserNotInvoiced($user));
                        $json['orders_update_array'] = $document ? $this->initOrdersArray($orderModule->findOrdersByUserAndInvoice($user, $document)) : [];
                    }
                }

                if ($classDocument == 'DeliveryNote') {
                    $json['orders_create_array'] = $this->initOrdersArray($orderModule->findOrdersByUserNotLinkedDeliveryNote($user));
                    $json['orders_update_array'] = $document ? $this->initOrdersArray($orderModule->findOrdersByUserAndDeliveryNote($user, $document)) : [];
                }

                return $json;
            }
        }

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

    public function initOrdersArray(array $ordersArray)
    {
        $orderModule = $this->getOrderModule();
        $ordersReturnArray = [];

        foreach($ordersArray as &$order) {
            $orderModule->initOrder($order);
            $ordersReturnArray[] = [
                'id' => $order->id,
                'date' => $order->distribution->date,
                'name' => date('d/m/Y', strtotime($order->distribution->date)),
                'amount_with_tax' => $orderModule->getOrderAmountWithTax($order, Order::INVOICE_AMOUNT_TOTAL)
            ];
        }

        return $ordersReturnArray;
    }

    public function initDeliveryNoteArray($type, $deliveryNoteArrayResults)
    {
        $deliveryNoteArray = [];
        $isCreate = false;
        if ($type == 'create') {
            $isCreate = true;
        }

        if ($deliveryNoteArrayResults) {
            foreach ($deliveryNoteArrayResults as $deliveryNote) {
                $deliveryNoteData = $this->addDeliveryNoteToArray($deliveryNote, $isCreate);
                if ($deliveryNoteData) {
                    $deliveryNoteArray[] = $deliveryNoteData;
                }
            }
        }

        return $deliveryNoteArray;
    }

    public function addDeliveryNoteToArray($deliveryNote, $isCreate = true)
    {
        $deliveryNoteModule = $this->getDeliveryNoteModule();

        $deliveryNoteData = array_merge(
            $deliveryNote->getAttributes(),
            [
                'url' => $this->getUrlManagerBackend()->createUrl(['delivery-note/update', 'id' => $deliveryNote->id]),
                'total' => $deliveryNoteModule->getAmountWithTax($deliveryNote, Order::INVOICE_AMOUNT_TOTAL)
            ]
        );

        if (($isCreate && !$deliveryNoteModule->isInvoiced($deliveryNote)) || !$isCreate) {
            return $deliveryNoteData;
        }

        return false;
    }

    public function actionValidate($id, $backUpdateForm = false)
    {
        $documentModule = $this->getDocumentModule();
        $classDocument = $this->getClass();

        if ($id > 0 && $documentModule->isValidClass($classDocument)) {
            $document = $this->findModel($id);

            if ($document) {
                $documentModule->getManager()->validateDocument($document);

                // @TODO : gérer via un événement
                $documentModule->generatePdf($document, Pdf::DEST_FILE);

                $this->setFlash('success', $this->getFlashMessage('validate', $document));

                if ($backUpdateForm) {
                    return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]);
                } else {
                    return $this->redirect([$this->getControllerUrl() . '/index']);
                }
            }
        }

        $this->setFlash('danger', 'Une erreur est survenue lors de la validation du document.');

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

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

        $orderModule = $this->getOrderModule();
        $productModule = $this->getProductModule();
        $documentModule = $this->getDocumentModule();
        $deliveryNoteModule = $this->getDeliveryNoteModule();
        $userProducerModule = $this->getUserProducerModule();
        $pointSaleModule = $this->getPointSaleModule();

        if ($idDocument > 0 && $documentModule->isValidClass($classDocument)) {

            $document = $this->findModel($idDocument, $classDocument);

            if ($document) {
                $ordersArray = [];
                $productsArray = $productModule->getRepository()->findProducts(true);

                foreach ($document->orders as $order) {
                    $orderModule->initOrder($order);
                    $productsOrderArray = [];

                    foreach ($order->productOrder as $productOrder) {
                        $productsOrderArray[$productOrder->id] = array_merge($productOrder->getAttributes(), [
                            'url_product' => $this->getUrlManagerBackend()->createUrl(['product/update', 'id' => $productOrder->id_product]),
                            'url_order' => $this->getUrlManagerBackend()->createUrl(['distribution/index', 'idOrderUpdate' => $productOrder->id_order])
                        ]);
                    }
                    $ordersArray[$order->id] = array_merge(
                        $order->getAttributes(),
                        [
                            'username' => $orderModule->getOrderUsername($order),
                            '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 = $userProducerModule->findOneUserProducer($document->user);
                $pointSale = $pointSaleModule->findOnePointSaleByIdUser($document->user->id);

                $productsArray = yii\helpers\ArrayHelper::map(
                    $productsArray,
                    'order',
                    function ($product) use ($document, $userProducer, $pointSale, $productModule) {
                        return array_merge($product->getAttributes(), [
                            'unit_coefficient' => $productModule->getSolver()->getUnitCoefficient($product),
                            'prices' => $productModule->getPriceArray($product, $userProducer->user, $pointSale),
                            'wording_unit' => $product->wording_unit,
                            'tax_rate' => $product->taxRate->value
                        ]);
                    }
                );

                return [
                    'return' => 'success',
                    'tax_rate_producer' => GlobalParam::getCurrentProducer()->taxRate->value,
                    'document' => array_merge($document->getAttributes(), [
                        'html_label' => $documentModule->getHtmlLabel($document),
                        'class' => $documentModule->getClass($document)
                    ]),
                    'id_user' => $document->user->id,
                    'products' => $productsArray,
                    'orders' => $ordersArray,
                    'total' => ($documentModule->getClass($document) == 'Invoice' || $documentModule->getClass($document) == 'DeliveryNote') ? $documentModule->getAmount(
                        $document,
                        Order::INVOICE_AMOUNT_TOTAL
                    ) : $documentModule->getAmount($document, Order::AMOUNT_TOTAL),
                    'total_with_tax' => ($documentModule->getClass($document) == 'Invoice' || $documentModule->getClass($document) == 'DeliveryNote') ? $documentModule->getAmountWithTax(
                        $document,
                        Order::INVOICE_AMOUNT_TOTAL
                    ) : $documentModule->getAmountWithTax($document, Order::AMOUNT_TOTAL),
                    'invoice_url' => ($documentModule->getClass($document) == 'DeliveryNote' && $deliveryNoteModule->getInvoice($document)) ? $this->getUrlManagerBackend()->createUrl(['invoice/update', 'id' => $deliveryNoteModule->getInvoice($document)->id]) : null
                ];
            }
        }

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

    public function actionAjaxAddProduct($idDocument, $classDocument, $idProduct, $quantity, $price)
    {
        $orderModule = $this->getOrderModule();
        $documentModule = $this->getDocumentModule();
        $productModule = $this->getProductModule();
        $userCurrent = $this->getUserCurrent();

        if ($documentModule->isValidClass($classDocument)) {
            $document = $this->findModel($idDocument, $classDocument);
            $classDocumentComplete = $documentModule->getClass($document, true);
            $product = $productModule->findOneProductById($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->origin = Order::ORIGIN_ADMIN;
                    $order->date = date('Y-m-d H:i:s');
                    $fieldIdDocument = 'id_' . $classDocumentComplete::tableName();
                    $order->$fieldIdDocument = $document->id;
                    $order->save();
                    $orderModule->getManager()->changeOrderStatus($order, OrderStatus::ALIAS_ORDERED, $userCurrent);

                } 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 Ajax::responseSuccess('Produit ajouté');
                }
            }
        }

        return Ajax::responseError('Une erreur est survenue lors de la suppression du produit.');
    }

    public function actionAjaxDeleteProductOrder($idProductOrder)
    {
        $productOrderModule = $this->getProductOrderModule();
        $productOrder = $productOrderModule->findOneProductOrderById($idProductOrder);

        if ($productOrder) {
            $productOrderModule->delete($productOrder);
            return Ajax::responseSuccess('Produit supprimé');
        }

        return Ajax::responseError('Une erreur est survenue lors de la suppression du produit.');
    }

    public function actionAjaxAddOrder($idDocument, $classDocument, $idOrder)
    {
        $documentModule = $this->getDocumentModule();
        $orderModule = $this->getOrderModule();

        $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument);
        $order = $orderModule->findOneOrderById($idOrder);

        if ($document && $documentModule->isStatusDraft($document) && $order) {
            $orderModule->updateOrderDocument($order, $document);

            return Ajax::responseSuccess("Commande ajoutée à la facture.");
        }
        else {
            return Ajax::responseError("Une erreur est survenue lors de l'ajout de la commande.");
        }
    }

    public function actionAjaxDeleteOrder($idDocument, $classDocument, $idOrder)
    {
        $documentModule = $this->getDocumentModule();
        $orderModule = $this->getOrderModule();

        $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument);
        $order = $orderModule->findOneOrderById($idOrder);

        if ($document && $documentModule->isStatusDraft($document)) {
            if($documentModule->isDocumentDeliveryNote($document)) {
                $orderModule->updateOrderDeliveryNote($order, null);
            }
            elseif($documentModule->isDocumentInvoice($document)) {
                $orderModule->updateOrderInvoice($order, null);
            }

            return Ajax::responseSuccess('Commande supprimée de la facture.');
        }
        else {
            return Ajax::responseError('Une erreur est survenue lors de la suppression de la commande.');
        }
    }

    public function actionAjaxIgnoreOrderWhenInvoicing($idDocument, $classDocument, $idOrder)
    {
        $documentModule = $this->getDocumentModule();
        $orderModule = $this->getOrderModule();

        $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument);
        $order = $orderModule->findOneOrderById($idOrder);

        if ($document && $documentModule->isStatusDraft($document) && $order) {
            $orderModule->updateOrderIgnoreWhenInvoicing($order, true);
            return Ajax::responseSuccess("La commande sera maintenant ignorée au moment de la facturation.");
        }
        else {
            return Ajax::responseError("Une erreur est survenue.");
        }
    }

    public function actionAjaxUpdateProductOrderInvoicePrice($idProductOrder, $invoicePrice)
    {
        $productOrderModule = $this->getProductOrderModule();
        $productOrder = $productOrderModule->getRepository()->findOneProductOrderById((int) $idProductOrder);
        if($productOrder) {
            $productOrderModule->getBuilder()->updateProductOrderInvoicePriceByValue($productOrder, (float) $invoicePrice);
            return Ajax::responseSuccess("Prix mis à jour", [
                'invoice_price' => $productOrder->invoice_price
            ]);
        }

        return Ajax::responseError("Une erreur est survenue.");
    }

    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(string $type, $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($idDocument, $classDocument = null)
    {
        $documentModule = $this->getDocumentModule();
        $model = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument ?? $this->getClass());

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