<?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\forms\SubscriptionForm;
use common\helpers\CSV;
use common\helpers\GlobalParam;
use common\helpers\Price;
use domain\Distribution\Distribution\Distribution;
use domain\Distribution\PointSaleDistribution\PointSaleDistribution;
use domain\Distribution\ProductDistribution\ProductDistribution;
use domain\Order\Order\Order;
use domain\Order\OrderStatus\OrderStatus;
use domain\Order\ProductOrder\ProductOrder;
use domain\Payment\Payment;
use domain\PointSale\PointSale\PointSale;
use domain\Product\Product\Product;
use domain\User\User\User;
use domain\User\UserProducer\UserProducer;
use yii\filters\AccessControl;
use yii\helpers\Html;

class OrderController extends BackendController
{
    var $enableCsrfValidation = false;

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

    /**
     * Traite le formulaire d'ajout/modification de commande.
     */
    /*public function processOrderForm(
        Distribution $distribution,
        string $date,
        array $pointsSale,
        array $products,
        array $users
    )
    {
        $orderModule = $this->getOrderModule();
        $pointSaleModule = $this->getPointSaleModule();

        if ($date != '') {
            $orders = $orderModule->findOrdersByDistribution($distribution);

            foreach ($pointsSale as $point) {
                $orderModule->initPointSaleOrders($point, $orders);

                if (isset($_POST['submit_pv']) && $_POST['submit_pv']) {
                    // modifs
                    foreach ($point->orders as $order) {

                        // suppression des product_order
                        ProductOrder::deleteAll(['id_order' => $order->id]);

                        // création des commande_produit modifiés
                        foreach ($products as $product) {
                            $quantity = \Yii::$app->getRequest()->post('product_' . $point->id . '_' . $product->id, 0);
                            if ($quantity) {
                                $productOrder = new ProductOrder;
                                $productOrder->id_order = $order->id;
                                $productOrder->id_product = $product->id;
                                $productOrder->quantity = $quantity;
                                $productOrder->price = $p->price;
                                $productOrder->unit = $p->unit;
                                $productOrder->step = $p->step;
                                $productOrder->id_tax_rate = $p->taxRate->id;
                                $productOrder->save();
                            }
                        }
                    }

                    $username = \Yii::$app->getRequest()->post('username_point_sale_' . $point->id, 0);
                    $date = \Yii::$app->getRequest()->post('date_order_point_sale_' . $point->id, 0);
                    $oneProduct = false;
                    foreach ($products as $product) {
                        $quantity = \Yii::$app->getRequest()->post('product_point_sale_' . $point->id . '_' . $product->id, 0);
                        if ($quantity) {
                            $oneProduct = true;
                        }
                    }

                    if (strlen($username) && $date && $oneProduct) {
                        $order = new Order();
                        $order->id_point_sale = $point->id;
                        $order->id_production = $distribution->id;
                        $order->id_user = 0;
                        $order->username = $username;
                        $arrayDate = explode('/', $date);
                        $order->date = $arrayDate[2] . '-' . $arrayDate[1] . '-' . $arrayDate[0] . ' 00:00:00';
                        $order->save();

                        foreach ($products as $product) {
                            $quantity = \Yii::$app->getRequest()->post('product_point_sale_' . $point->id . '_' . $product->id, 0);
                            if ($quantity) {
                                $productOrder = new ProductOrder();
                                $productOrder->id_order = $order->id;
                                $productOrder->id_product = $product->id;
                                $productOrder->quantity = $quantity;
                                $productOrder->price = $p->price;
                                $productOrder->unit = $p->unit;
                                $productOrder->step = $p->step;
                                $productOrder->id_tax_rate = $p->taxRate->id;
                                $productOrder->save();
                            }
                        }

                        $orderModule->generateOrderReference($order);
                    }
                }
            }
        }
    }*/

    /**
     * Page principale de la gestion des commandes.
     */
    /*public function actionIndex($date = '', $returnData = false)
    {
        $distributionModule = $this-> getDistributionModule();
        $productModule = $this->getProductModule();
        $pointSaleModule = $this->getPointSaleModule();
        $orderModule = $this->getOrderModule();
        $productDistributionModule = $this->getProductDistributionModule();

        if (!Product::searchCount() || !PointSale::searchCount()) {
            $this->redirect(['dashboard/index', 'error_products_points_sale' => 1]);
        }

        $orders = [];

        // users
        $arrayUsers = [0 => '--'];
        $users = User::searchAll([], ['orderby' => 'lastname, name ASC']);

        foreach ($users as $user) {
            $arrayUsers[$user->id] = $user->name . ' ' . $user->lastname;
        }

        $distribution = $distributionModule->createDistributionIfNotExist($date);

        if ($distribution) {
            $arrayPointsSale = PointSale::find()
                ->joinWith(['pointSaleDistribution' => function ($q) use ($distribution) {
                    $q->where(['id_distribution' => $distribution->id]);
                }])
                ->where([
                    'id_producer' => GlobalParam::getCurrentProducerId(),
                ])
                ->all();
        } else {
            $arrayPointsSale = $pointSaleModule->findPointSales();
        }

        $arrayProducts = $productModule->findProducts();

        $this->processOrderForm($distribution, $date, $arrayPointsSale, $arrayProducts, $users);

        // commandes
        $arrayOrders = $orderModule->findOrdersByDistribution($distribution);
        $revenues = 0;
        $weight = 0;
        $revenuesDelivered = 0;

        if ($arrayOrders) {
            foreach ($arrayOrders as $order) {
                if (is_null($order->date_delete)) {
                    $revenues += $order->amount;
                    if ($order->id_point_sale != 1) {
                        $revenuesDelivered += $order->amount;
                    }
                    $weight += $order->weight;
                }
            }
        }

        $revenues = number_format($revenues, 2);

        // init commandes point de vente
        foreach ($arrayPointsSale as $pointSale) {
            $orderModule->initPointSaleOrders($pointSale, $arrayOrders);

            $dataSelectOrders = [];
            $dataOptionsOrders = [];
            foreach ($pointSale->orders as $order) {
                if ($order->user) {
                    $dataSelectOrders[$order->id] = $order->user->name . ' ' . $order->user->lastname;
                } else {
                    $dataSelectOrders[$order->id] = $order->username;
                }

                $dataOptionsOrders[$order->id] = [];
                $arrayOptions = [];
                $arrayOptions[$order->id]['amount'] = $order->amount;
                $arrayOptions[$order->id]['str_amount'] = number_format($order->amount, 2, ',', '') . ' €';
                $arrayOptions[$order->id]['paid_amount'] = $order->paid_amount;
                $arrayOptions[$order->id]['products'] = [];
                $arrayOptions[$order->id]['comment'] = Html::encode($order->comment);
                foreach ($order->productOrder as $productOrder) {
                    $arrayOptions[$order->id]['products'][$productOrder->id_product] = $productOrder->quantity;
                }

                $dataOptionsOrders[$order->id]['data-order'] = json_encode($arrayOptions[$order->id]);
                $dataOptionsOrders[$order->id]['value'] = $order->id;
            }
            $pointSale->data_select_orders = $dataSelectOrders;
            $pointSale->data_options_orders = $dataOptionsOrders;
        }

        // gestion produits selec
        if (isset($_POST['valider_produit_selec'])) {

            if (isset($_POST['Product'])) {

                foreach ($arrayProducts as $product) {

                    $productDistribution = $productDistributionModule->findOneProductDistribution($distribution, $product);

                    if (!$productDistribution) {
                        $productDistribution = new ProductDistribution();
                        $productDistribution->id_distribution = $distribution->id;
                        $productDistribution->id_product = $product->id;
                        $productDistribution->active = 0;

                        if (isset($product->quantity_max)) {
                            $productDistribution->quantity_max = $product->quantity_max;
                        } else {
                            $productDistribution->quantity_max = null;
                        }

                        $productDistributionModule->saveCreate($productDistribution);
                    }

                    if (isset($_POST['Product'][$product->id]['active'])) {
                        $productDistribution->active = 1;
                    } else {
                        $productDistribution->active = 0;
                    }

                    if ((isset($_POST['Product'][$product->id]['quantity_max']) && $_POST['Product'][$product->id]['quantity_max'] != '')) {
                        $productDistribution->quantity_max = (int)$_POST['Product'][$product->id]['quantity_max'];
                    } else {
                        $productDistribution->quantity_max = null;
                    }

                    $productDistributionModule->saveUpdate($productDistribution);
                }
            }
        }

        $arrayProductsSelected = [];
        if ($distribution) {
            $arrayProductsSelected = $productDistributionModule->findProductDistributionsByDistribution($distribution);
            $arrayProducts = $productModule->findProductsByDistribution($distribution);
        }

        // poids total de la production et CA potentiel
        $potentialTurnover = 0;
        $totalWeight = 0;
        foreach ($arrayProductsSelected as $idSelectedProduct => $selectedProduct) {
            if ($selectedProduct['active']) {
                foreach ($arrayProducts as $product) {
                    if ($product->id == $idSelectedProduct) {
                        $potentialTurnover += $selectedProduct['quantity_max'] * $product->price;
                        $totalWeight += $selectedProduct['quantity_max'] * $product->weight / 1000;
                    }
                }
            }
        }

        $arrayDistributionDays = $distributionModule->findDistributionsActive();

        // commandes auto
        $subscriptionForm = new SubscriptionForm();

        // productions point vente
        $pointSaleDistribution = new PointSaleDistribution();
        $oointsSaleDistribution = [];

        if ($distribution) {
            $pointsSaleDistribution = PointSaleDistribution::searchAll([
                'id_distribution' => $distribution->id
            ]);
        }

        $arrayPointsSaleDistribution = [];

        if (isset($pointsSaleDistribution)) {
            foreach ($pointsSaleDistribution as $pointSaleDistrib) {
                $key = $pointSaleDistrib->id_distribution . '-' . $pointSaleDistrib->id_point_sale;
                if ($pointSaleDistrib->delivery == 1) {
                    $pointSaleDistribution->points_sale_distribution[] = $key;
                }
                if (isset($pointSaleDistrib->pointSale) && strlen($pointSaleDistrib->pointSale->name)) {
                    $arrayPointsSaleDistribution[$key] = Html::encode($pointSaleDistrib->pointSale->name);
                }
            }
        }

        // une production de la semaine activée ou non
        $oneDistributionWeekActive = false;
        $week = sprintf('%02d', date('W', strtotime($date)));
        $start = strtotime(date('Y', strtotime($date)) . 'W' . $week);
        $dateMonday = date('Y-m-d', strtotime('Monday', $start));
        $dateTuesday = date('Y-m-d', strtotime('Tuesday', $start));
        $dateWednesday = date('Y-m-d', strtotime('Wednesday', $start));
        $dateThursday = date('Y-m-d', strtotime('Thursday', $start));
        $dateFriday = date('Y-m-d', strtotime('Friday', $start));
        $dateSaturday = date('Y-m-d', strtotime('Saturday', $start));
        $dateSunday = date('Y-m-d', strtotime('Sunday', $start));

        $weekDistribution = Distribution::find()
            ->andWhere([
                'id_producer' => GlobalParam::getCurrentProducerId(),
                'active' => 1,
            ])
            ->andWhere(['or',
                ['date' => $dateMonday],
                ['date' => $dateTuesday],
                ['date' => $dateWednesday],
                ['date' => $dateThursday],
                ['date' => $dateFriday],
                ['date' => $dateSaturday],
                ['date' => $dateSunday],
            ])
            ->one();
        if ($weekDistribution) {
            $oneDistributionWeekActive = true;
        }

        $datas = [
            'arrayProducts' => $arrayProducts,
            'arrayPointsSale' => $arrayPointsSale,
            'arrayOrders' => $arrayOrders,
            'date' => $date,
            'distribution' => $distribution,
            'arrayDistributionDays' => $arrayDistributionDays,
            'selectedProducts' => $arrayProductsSelected,
            'users' => $arrayUsers,
            'revenues' => $revenues,
            'revenuesDelivered' => $revenuesDelivered,
            'weight' => $weight,
            'potentialTurnover' => $potentialTurnover,
            'totalWeight' => $totalWeight,
            'subscriptionForm' => $subscriptionForm,
            'pointSaleDistribution' => $pointSaleDistribution,
            'arrayPointsSaleDistribution' => $arrayPointsSaleDistribution,
            'oneDistributionWeekActive' => $oneDistributionWeekActive
        ];

        if ($returnData) {
            return $datas;
        } else {
            return $this->render('index', $datas);
        }
    }*/

    /**
     * Génère un fichier d'export des commandes au format CSV.
     *
     * @param string $date
     * @param integer $id_point_vente
     * @param boolean $global
     */
    public function actionDownload($date = '', $idPointSale = 0, $global = 0)
    {
        $orderModule = $this->getOrderModule();
        $distributionModule = $this-> getDistributionModule();
        $pointSaleModule = $this->getPointSaleModule();
        $productModule = $this->getProductModule();
        $productDistributionModule = $this->getProductDistributionModule();

        $distribution = $distributionModule->findOneDistribution($date);
        $selectedProductsArray = $productDistributionModule->findProductDistributionsByDistribution($distribution);
        $productsArray = $productModule->findProducts();
        $ordersArray = $orderModule->findOrdersByDistributionDate($date);

        $pointsSaleArray = $pointSaleModule->findPointSales();
        foreach ($pointsSaleArray as $pointSale) {
            $pointSaleModule->initOrders($pointSale, $ordersArray);
        }

        /*
         * export global
         */
        if ($global) {

            $data = [];
            $filename = 'export_' . $date . '_global';

            $dayWeek = date('w', strtotime($date));
            $dayWeekArray = [0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday'];
            $fieldsHoursPointSale = 'infos_' . $dayWeekArray[$dayWeek];

            // par point de vente
            foreach ($pointsSaleArray as $pointSale) {
                if (count($pointSale->orders) && strlen($pointSale->$fieldsHoursPointSale)) {

                    $line = [$pointSale->name, 'Produits', 'Montant', 'Commentaire'];

                    $data[] = $line;

                    $res = $this->contentPointSaleCSV($date, $productsArray, $pointsSaleArray, $pointSale->id);
                    foreach ($res['data'] as $line) {
                        $data[] = $line;
                    }
                }

                if (count($pointSale->orders) && strlen($pointSale->$fieldsHoursPointSale)) {

                    $line = ['Total'];
                    $strProducts = '';
                    foreach ($productsArray as $product) {
                        if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                            $quantity = $orderModule->getProductQuantity($product, $pointSale->orders);
                            $strQuantity = '';
                            if ($quantity) {
                                $strQuantity = $quantity;
                                $strProducts .= $strQuantity . ', ';
                            }
                        }
                    }
                    $line[] = substr($strProducts, 0, strlen($strProducts) - 2);
                    $line[] = number_format($pointSale->revenues, 2) . ' €';
                    $data[] = $line;

                    $data[] = [];
                }
            }

            $line = ['Total'];
            $strProducts = '';
            foreach ($productsArray as $product) {
                if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                    $quantity = $orderModule->getProductQuantity($product, $ordersArray);
                    $strQuantity = '';
                    if ($quantity) {
                        $strQuantity = $quantity;
                        $strQuantity .= $strQuantity . ', ';
                    }
                }
            }
            $line[] = substr($strProducts, 0, strlen($strProducts) - 2);

            $data[] = $line;


            $infos = $this->actionIndex($date, true);

            CSV::downloadSendHeaders($filename . '.csv');
            echo CSV::array2csv($data);
            die();
        } /*
         * export individuel
         */
        else {
            if ($ordersArray && count($ordersArray)) {

                $data = [];

                // par point de vente
                if ($idPointSale) {
                    $res = $this->contentPointSaleCSV($date, $productsArray, $pointsSaleArray, $idPointSale);
                    $data = $res['data'];
                    $filename = $res['filename'];
                } // récapitulatif
                else {
                    $res = $this->contentRecapCSV($date, $productsArray, $pointsSaleArray, $ordersArray);
                    $filename = 'summary_' . $date;
                    $data = $res['data'];
                }

                CSV::downloadSendHeaders($filename . '.csv');
                echo CSV::array2csv($data);
                die();
            }
        }
    }

    /**
     * Génère le contenu nécessaire aux exports au format CSV.
     *
     * @param string $date
     * @param array $products
     * @param array $pointsSale
     * @param array $orders
     * @return array
     * @see OrderController::actionDownload()
     */
    public function contentRecapCSV(string $date, array $products, array $pointsSale, array $orders)
    {
        $orderModule = $this->getOrderModule();
        $distributionModule = $this-> getDistributionModule();
        $productDistributionModule = $this->getProductDistributionModule();

        $data = [];
        $filename = 'summary_' . $date;

        $distribution = $distributionModule->findOneDistribution($date);
        $selectedProductsArray = $productDistributionModule->findProductDistributionsByDistribution($distribution);

        // head
        $data[0] = ['Lieu'];
        foreach ($products as $product) {
            if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                $data[0][] = $product->description;
            }
        }

        $dayWeek = date('w', strtotime($date));
        $dayWeekArray = [0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday'];
        $fieldHoursPointSale = 'infos_' . $dayWeekArray[$dayWeek];


        // datas
        foreach ($pointsSale as $pointSale) {
            if (count($pointSale->orders) && strlen($pointSale->$fieldHoursPointSale)) {
                $dataAdd = [$pointSale->name];
                foreach ($products as $product) {
                    if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                        $dataAdd[] = $orderModule->getProductQuantity($product, $pointSale->orders);
                    }
                }
                $data[] = $dataAdd;
            }
        }

        $dataAdd = ['Total'];
        foreach ($products as $product) {
            if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                $dataAdd[] = $orderModule->getProductQuantity($product, $orders);
            }
        }
        $data[] = $dataAdd;

        return [
            'data' => $data,
            'filename' => $filename
        ];
    }

    /**
     * Génère le contenu relatif aux points de vente nécessaires aux exports au
     * format CSV.
     *
     * @param string $date
     * @param array $produits
     * @param array $points_vente
     * @param integer $id_point_vente
     * @return array
     */
    public function contentPointSaleCSV($date, $products, $pointsSale, $idPointSale)
    {
        $distributionModule = $this-> getDistributionModule();
        $productDistributionModule = $this->getProductDistributionModule();

        $data = [];
        $distribution = $distributionModule->findOneDistribution($date);
        $selectedProductsArray = $productDistributionModule->findProductDistributionsByDistribution($distribution);

        // datas
        foreach ($pointsSale as $pointSale) {
            if ($pointSale->id == $idPointSale) {

                $filename = 'export_' . $date . '_' . strtolower(str_replace(' ', '-', $pointSale->name));

                foreach ($pointSale->orders as $order) {
                    $strUser = '';
                    // username
                    if ($order->user) {
                        $strUser = $order->user->name . " " . $order->user->lastname;
                    } else {
                        $strUser = $order->username;
                    }

                    // téléphone
                    if (isset($order->user) && strlen($order->user->phone)) {
                        $strUser .= ' (' . $order->user->phone . ')';
                    }

                    $dataAdd = [$strUser];

                    // produits
                    $strProducts = '';
                    foreach ($products as $product) {
                        if (isset($selectedProductsArray[$product->id]['active']) && $selectedProductsArray[$product->id]['active']) {
                            $add = false;
                            foreach ($product->productOrder as $productOrder) {
                                if ($product->id == $productOrder->id_product) {
                                    $strProducts .= $productOrder->quantity;
                                    $add = true;
                                }
                            }
                        }
                    }

                    $dataAdd[] = substr($strProducts, 0, strlen($strProducts) - 2);
                    $dataAdd[] = number_format($order->amount, 2) . ' €';
                    $dataAdd[] = $order->comment;

                    $data[] = $dataAdd;
                }
            }
        }

        return [
            'data' => $data,
            'filename' => $filename
        ];
    }

    /**
     * Change l'état d'un jour de distribution (activé, désactivé).
     */
    public function actionChangeState(string $date, bool $active, bool $redirect = true)
    {
        $distributionModule = $this-> getDistributionModule();
        $distribution = $distributionModule->createDistributionIfNotExist($date);
        $distributionModule->activeDistribution($distribution, $active);

        if ($redirect) {
            $this->redirect(['index', 'date' => $date]);
        }
    }

    /**
     * Change l'état d'une semaine de production (activé, désactivé).
     */
    public function actionChangeStateWeek(string $date, bool $active)
    {
        $pointSaleModule = $this->getPointSaleModule();

        $pointsSaleArray = $pointSaleModule->findPointSales();

        $week = sprintf('%02d', date('W', strtotime($date)));
        $start = strtotime(date('Y', strtotime($date)) . 'W' . $week);
        $dateMonday = date('Y-m-d', strtotime('Monday', $start));
        $dateTuesday = date('Y-m-d', strtotime('Tuesday', $start));
        $dateWednesday = date('Y-m-d', strtotime('Wednesday', $start));
        $dateThursday = date('Y-m-d', strtotime('Thursday', $start));
        $dateFriday = date('Y-m-d', strtotime('Friday', $start));
        $dateSaturday = date('Y-m-d', strtotime('Saturday', $start));
        $dateSunday = date('Y-m-d', strtotime('Sunday', $start));

        $activeMonday = false;
        $activeTuesday = false;
        $activeWednesday = false;
        $activeThursday = false;
        $activeFriday = false;
        $activeSaturday = false;
        $activeSunday = false;

        foreach ($pointsSaleArray as $pointSale) {
            if ($pointSale->delivery_monday) $activeMonday = true;
            if ($pointSale->delivery_tuesday) $activeTuesday = true;
            if ($pointSale->delivery_wednesday) $activeWednesday = true;
            if ($pointSale->delivery_thursday) $activeThursday = true;
            if ($pointSale->delivery_friday) $activeFriday = true;
            if ($pointSale->delivery_saturday) $activeSaturday = true;
            if ($pointSale->delivery_sunday) $activeSunday = true;
        }

        if ($activeMonday || !$active) $this->actionChangeState($dateMonday, $active, false);
        if ($activeTuesday || !$active) $this->actionChangeState($activeTuesday, $active, false);
        if ($activeWednesday || !$active) $this->actionChangeState($activeWednesday, $active, false);
        if ($activeThursday || !$active) $this->actionChangeState($activeThursday, $active, false);
        if ($activeFriday || !$active) $this->actionChangeState($activeFriday, $active, false);
        if ($activeSaturday || !$active) $this->actionChangeState($activeSaturday, $active, false);
        if ($activeSunday || !$active) $this->actionChangeState($activeSunday, $active, false);

        $this->redirect(['index', 'date' => $date]);
    }

    /**
     * Supprime une commande via une requête AJAX.
     */
    public function actionAjaxDelete(int $idOrder)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $orderModule = $this->getOrderModule();

        $order = $orderModule->findOneOrderById($idOrder);
        if ($order) {
            $orderModule->getManager()->deleteOrder($order, $this->getUserCurrent());
        }

        return ['success'];
    }


    /**
     * Supprime une commande.
     */
    public function actionDelete(string $date, int $idOrder)
    {
        $orderModule = $this->getOrderModule();
        $order = $orderModule->findOneOrderById($idOrder);
        if ($order) {
            $orderModule->getManager()->deleteOrder($order, $this->getUserCurrent());
        }

        $this->redirect(['index', 'date' => $date]);
    }

    /**
     * Crée une commande via une requête AJAX.
     *
     * @param string $date
     * @param integer $idPointSale
     * @param integer $idUser
     * @param string $username
     * @param array $produits
     * @param string $commentaire
     */
    public function actionAjaxCreate(
        $date, $idPointSale, $idUser, $username, $meanPayment = '', $products, $comment, $debitCredit = false)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $distributionModule = $this-> getDistributionModule();
        $pointSaleModule = $this->getPointSaleModule();
        $userPointSaleModule = $this->getUserPointSaleModule();
        $userModule = $this->getUserModule();
        $userProducerModule = $this->getUserProducerModule();
        $producerModule = $this->getProducerModule();
        $productModule = $this->getProductModule();
        $orderModule = $this->getOrderModule();

        $products = json_decode($products);
        $pointSale = $pointSaleModule->findOnePointSaleById($idPointSale);
        $distribution = $distributionModule->findOneDistribution($date);
        $producerCurrent = $this->getProducerCurrent();
        $userCurrent = $this->getUserCurrent();

        if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $date)
            && ($idUser || strlen($username))
            && $pointSale
            && count(get_object_vars($products))
            && $distribution) {

            $order = new Order;
            $order->date = date('Y-m-d H:i:s');
            $order->id_point_sale = $idPointSale;
            $order->mean_payment = $meanPayment;
            $order->id_distribution = $distribution->id;
            $order->origin = Order::ORIGIN_ADMIN;
            $order->comment = $comment;

            if ($idUser) {
                $order->id_user = $idUser;

                // commentaire du point de vente
                $userPointSale = $userPointSaleModule->findOneUserPointSale($userModule->findOneUserById($idUser), $pointSale);

                if ($userPointSale && strlen($userPointSale->comment)) {
                    $order->comment_point_sale = $userPointSale->comment;
                }
            } else {
                $order->username = $username;
                $order->id_user = 0;
            }

            $order->save();

            $orderModule->getManager()->changeOrderStatus($order, OrderStatus::ALIAS_ORDERED, $userCurrent);

            $user = false;
            $userProducer = false;
            if (isset($order->user) && $order->user) {
                $user = $order->user;

                $userProducer = $userProducerModule->findOneUserProducer($user);
            }

            foreach ($products as $key => $dataProductOrder) {
                $product = $productModule->findOneProductById($key);
                if(isset(Product::$unitsArray[$dataProductOrder->unit]) && Product::$unitsArray[$dataProductOrder->unit]['coefficient']) {
                    $quantity = $dataProductOrder->quantity / Product::$unitsArray[$dataProductOrder->unit]['coefficient'];
                    if ($product && $quantity) {
                        $productOrder = new ProductOrder;
                        $productOrder->id_order = $order->id;
                        $productOrder->id_product = $key;
                        $productOrder->quantity = $quantity;
                        $productOrder->unit = $product->unit;
                        $productOrder->step = $product->step;
                        if ($dataProductOrder->price) {
                            $productOrder->price = $dataProductOrder->price;
                        } else {
                            $productOrder->price = $productModule->getPrice($product, [
                                'user' => $user,
                                'user_producer' => $userProducer,
                                'point_sale' => $order->pointSale,
                                'quantity' => $productOrder->quantity
                            ]);
                        }
                        $productOrder->id_tax_rate = $product->taxRate->id;
                        $productOrder->save();
                    }
                }
            }

            $order = $orderModule->findOneOrderById($order->id);
            $orderModule->initOrder($order);
            if ($order && $orderModule->isCreditAutoPayment($order, $debitCredit)) {
                $orderModule->processCredit($order);
            }

            $order = $orderModule->findOneOrderById($order->id);
            $orderModule->initOrder($order);
            if ($order) {
                $orderModule->generateOrderReference($order);
                $orderModule->updateOrderTillerSynchronization($order);
            }

            // lien utilisateur / point de vente
            if ($idUser && $pointSale) {
                $pointSaleModule->addUser($user, $pointSale);
            }
        }

        return ['success'];
    }

    /**
     * Met à jour une commande via une requête AJAX.
     *
     * @param integer $idOrder
     * @param array $products
     * @param string $date
     * @param string $comment
     */
    public function actionAjaxUpdate()
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $orderModule = $this->getOrderModule();
        $userModule = $this->getUserModule();
        $pointSaleModule = $this->getPointSaleModule();
        $userPointSaleModule = $this->getUserPointSaleModule();
        $paymentManager = $this->getPaymentModule();
        $productModule = $this->getProductModule();

        $request = \Yii::$app->request;
        $date = $request->post('date');
        $idOrder = $request->post('idOrder');
        $idPointSale = $request->post('idPointSale');
        $idUser = $request->post('idUser');
        $username = $request->post('username');
        $meanPayment = $request->post('meanPayment');
        $products = $request->post('products');
        $comment = $request->post('comment');
        $debitCredit = $request->post('debitCredit');

        $order = $orderModule->findOneOrderById($idOrder);
        $orderModule->initOrder($order);

        $user = $userModule->findOneUserById($idUser);
        $pointSale = $pointSaleModule->findOnePointSaleById($idPointSale);

        if ($order
            && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) {

            // Si changement d'user : on rembourse l'ancien user
            $oldIdUser = $order->id_user;
            $amountPaid = $orderModule->getOrderAmountWithTax($order, Order::AMOUNT_PAID);
            if ($oldIdUser != $idUser && $amountPaid > 0) {
                $paymentManager->refundOrderCredit($order, $this->getUserCurrent());
                $order = $orderModule->findOneOrderById($idOrder);
                $orderModule->initOrder($order);
            }

            if ($idUser) {
                $order->username = '';
                $order->id_user = $idUser;

                // commentaire du point de vente
                $userPointSale = $userPointSaleModule->findOneUserPointSale($user, $pointSale);
                if ($userPointSale && strlen($userPointSale->comment)) {
                    $order->comment_point_sale = $userPointSale->comment;
                }
            } else {
                $order->username = $username;
                $order->id_user = 0;
            }

            $user = User::searchOne(['id' => $order->id_user]);
            $userProducer = false;
            if ($user) {
                $userProducer = UserProducer::searchOne([
                    'id_user' => $user->id,
                    'id_producer' => $order->distribution->id_producer
                ]);
            }

            $products = json_decode($products);
            foreach ($products as $key => $dataProductOrder) {
                $productOrder = ProductOrder::findOne([
                    'id_order' => $idOrder,
                    'id_product' => $key
                ]);

                $quantity = $dataProductOrder->quantity
                    / Product::$unitsArray[$dataProductOrder->unit]['coefficient'];

                if ($quantity) {
                    if ($productOrder) {
                        $productOrder->quantity = $quantity;
                        $productOrder->price = $dataProductOrder->price;

                        if(isset($dataProductOrder->invoice_price) && $dataProductOrder->invoice_price) {
                            $productOrder->invoice_price = $dataProductOrder->invoice_price;
                        }
                    } else {
                        $product = Product::findOne($key);

                        if ($product) {
                            $productOrder = new ProductOrder;
                            $productOrder->id_order = $idOrder;
                            $productOrder->id_product = $key;
                            $productOrder->quantity = $quantity;
                            $productOrder->unit = $product->unit;
                            $productOrder->step = $product->step;
                            $productOrder->id_tax_rate = $product->taxRate->id;

                            if ($dataProductOrder->price) {
                                $productOrder->price = $dataProductOrder->price;
                            } else {
                                $productOrder->price = $productModule->getPrice($product, [
                                    'user' => $user,
                                    'user_producer' => $userProducer,
                                    'point_sale' => $order->pointSale,
                                    'quantity' => $productOrder->quantity
                                ]);
                            }
                        }
                    }

                    $productOrder->save();
                } else {
                    if ($productOrder) {
                        $productOrder->delete();
                    }
                }
            }

            $order->id_point_sale = $idPointSale;
            $order->mean_payment = $meanPayment;
            $order->comment = $comment;

            $order->save();

            $orderModule->getManager()->changeOrderStatus($order, OrderStatus::ALIAS_UPDATED, $this->getUserCurrent());

            $order = Order::searchOne(['id' => $order->id]);
            $orderModule->initOrder($order);
            if ($order && $orderModule->isCreditAutoPayment($order, $debitCredit)) {
                $orderModule->processCredit($order);
            }
        }
    }

    /**
     * Retourne l'état du paiement (historique, cagnotte) d'une commande donnée.
     */
    public function actionPaymentStatus(int $idOrder)
    {
        $orderModule = $this->getOrderModule();
        $paymentManager = $this->getPaymentModule();

        $order = $orderModule->findOneOrderById($idOrder);

        if ($order) {
            $html = '';

            if ($order->id_user) {
                $userProducer = UserProducer::find()
                    ->where([
                        'id_user' => $order->id_user,
                        'id_producer' => $order->distribution->id_producer
                    ])
                    ->one();

                $amountPaid = $orderModule->getOrderAmount($order, Order::AMOUNT_PAID);

                if (abs($order->amount - $amountPaid) < 0.0001) {
                    $html .= '<span class="label label-success">Payé</span>';
                    $buttonsCredit = Html::a('Rembourser ' . $orderModule->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL, true), 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $order->amount, 'data-type' => 'refund']);
                } elseif ($order->amount > $amountPaid) {
                    $amountToPay = $order->amount - $amountPaid;
                    $html .= '<span class="label label-danger">Non payé</span> reste <strong>' . number_format($amountToPay, 2) . ' €</strong> à débiter';
                    $buttonsCredit = Html::a('Débiter ' . number_format($amountToPay, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs payer', 'data-montant' => $amountToPay, 'data-type' => 'payment']);
                } elseif ($order->amount < $amountPaid) {
                    $amountToRefund = $amountPaid - $order->amount;
                    $html .= ' <span class="label label-success">Payé</span> <strong>' . number_format($amountToRefund, 2) . ' €</strong> à rembourser';
                    $buttonsCredit = Html::a('Rembourser ' . number_format($amountToRefund, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $amountToRefund, 'data-type' => 'refund']);
                }

                $html .= '<span class="buttons-credit">'
                    . 'Cagnotte : <strong>' . number_format($userProducer->credit, 2) . '  €</strong><br />'
                    . $buttonsCredit
                    . '</span>';

                // historique
                $history = Payment::find()
                    ->with('userAction')
                    ->where(['id_order' => $idOrder])
                    ->all();

                $html .= '<br /><br /><strong>Historique</strong><br /><table class="table table-condensed table-bordered">'
                    . '<thead><tr><th>Date</th><th>Utilisateur</th><th>Action</th><th>- Débit</th><th>+ Crédit</th></tr></thead>'
                    . '<tbody>';

                if ($history && is_array($history) && count($history)) {
                    foreach ($history as $creditHistory) {
                        $html .= '<tr>'
                            . '<td>' . date('d/m/Y H:i:s', strtotime($paymentManager->getDate($creditHistory))) . '</td>'
                            . '<td>' . Html::encode($this->getUserModule()->getSolver()->getPaymentUsernameUserAction($creditHistory)) . '</td>'
                            . '<td>' . $paymentManager->getStrWording($creditHistory) . '</td>'
                            . '<td>' . ($paymentManager->isTypeDebit($creditHistory) ? '- ' . Price::getPriceWithTax($creditHistory->amount) : '') . '</td>'
                            . '<td>' . ($paymentManager->isTypeCredit($creditHistory) ? '+ ' . Price::getPriceWithTax($creditHistory->amount) : '') . '</td>'
                            . '</tr>';
                    }
                } else {
                    $html .= '<tr><td colspan="4">Aucun résultat</td></tr>';
                }

                $html .= '</tbody></table>';
            } else {
                $html .= '<div class="alert alert-warning">Pas de gestion de crédit pain pour cette commande car elle n\'est pas liée à un compte utilisateur.</div>';
            }

            echo json_encode([
                'html_payment_status' => $html,
                'json_order' => $order->getDataJson()
            ]);
        }

        die();
    }

    /**
     * Effectue le paiement/remboursement d'une commande.
     */
    public function actionAjaxPayment(int $idOrder, string $type, string $meanPayment): array
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $orderModule = $this->getOrderModule();
        $paymentManager = $this->getPaymentModule();
        $order = $orderModule->findOneOrderById($idOrder);
        $orderModule->initOrder($order);

        if ($order) {
            $paymentManager->payOrRefundOrder($type, $order, $meanPayment, $this->getUserCurrent());
        }

        return ['success'];
    }

    /**
     * Modifie l'état de la synchronisation Tiller d'une commande.
     */
    public function actionAjaxChangeSynchroTiller(int $idOrder, bool $boolSynchroTiller): array
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $orderModule = $this->getOrderModule();

        $order = $orderModule->findOneOrderById($idOrder);
        if ($order) {
            $orderModule->updateOrderTillerSynchronization($order, (int) $boolSynchroTiller);
            return ['success'];
        }

        return ['error'];
    }

}