<?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 common\models;

use common\helpers\GlobalParam;
use Yii;
use common\components\ActiveRecordCommon;
use common\models\Order;
use common\models\Distribution;

/**
 * This is the model class for table "production".
 *
 * @property integer $id
 * @property string $date
 * @property integer $active
 */
class Distribution extends ActiveRecordCommon
{
        /**
         * @inheritdoc
         */
        public static function tableName()
        {
                return 'distribution';
        }

        public function getProducer()
        {
                return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
        }

        /**
         * @inheritdoc
         */
        public function rules()
        {
                return [
                        [['date'], 'required'],
                        [['date'], 'safe'],
                        [['active'], 'integer']
                ];
        }

        /**
         * @inheritdoc
         */
        public function attributeLabels()
        {
                return [
                        'id' => 'ID',
                        'date' => 'Date',
                        'active' => 'Actif',
                ];
        }

        /*
         * Relations
         */

        public function getOrder()
        {
                return $this->hasMany(Order::className(), ['id_distribution' => 'id']);
        }

        public function getProductDistribution()
        {
                return $this->hasMany(ProductDistribution::className(), ['id_distribution' => 'id']);
        }

        /**
         * Retourne les options de base nécessaires à la fonction de recherche.
         *
         * @return array
         */
        public static function defaultOptionsSearch()
        {
                return [
                        'with' => [],
                        'join_with' => [],
                        'orderby' => 'date ASC',
                        'attribute_id_producer' => 'distribution.id_producer'
                ];
        }

        /**
         * Retourne si un produit est actif ou non.
         *
         * @param integer $idProduit
         * @return boolean
         */
        public function isActiveProduct($idProduit)
        {
                if ($idProduit &&
                        isset($this->productDistribution) &&
                        count($this->productDistribution) > 0) {

                        foreach ($this->productDistribution as $productDistribution) {
                                if ($productDistribution['id_product'] == $idProduit &&
                                        $productDistribution['active']) {
                                        return true;
                                }
                        }
                }

                return false;
        }

        /**
         * Initialise un jour de production.
         *
         * @param string $date
         * @return Production
         */
        public static function initDistribution($date, $idProducer = 0)
        {
                $distribution = null;
                if ($date != '') {

                        $paramsDistribution = [
                                'date' => $date
                        ];
                        if ($idProducer) {
                                $paramsDistribution['distribution.id_producer'] = (int)$idProducer;
                        } else {
                                $idProducer = GlobalParam::getCurrentProducerId();
                        }

                        $distribution = Distribution::searchOne($paramsDistribution);

                        if (!$distribution) {
                                $distribution = new Distribution;
                                $distribution->date = $date;
                                $distribution->delivery = 1;
                                $distribution->id_producer = $idProducer;
                                $distribution->save();
                        }
                }

                // point_sale_distribution à définir s'ils ne sont pas initialisés
                if ($distribution) {

                        $countPointSaleDistribution = PointSaleDistribution::searchCount([
                                'id_distribution' => $distribution->id
                        ]);

                        if (!$countPointSaleDistribution) {
                                PointSaleDistribution::setAll($distribution->id, true);
                        }
                }

                // init produits sélectionnés pour cette production
                $products = Product::searchAll();

                if ($distribution) {
                        $productsDistribution = ProductDistribution::searchAll([
                                'id_distribution' => $distribution->id
                        ]);
                        if (!count($productsDistribution)) {
                                foreach ($products as $product) {
                                        $distribution->linkProduct($product);
                                }
                        }
                        $distribution->linkProductGift();
                }

                return $distribution;
        }

        /**
         * Retourne les distributions futures.
         *
         * @return array
         */
        public static function getIncomingDistributions()
        {
                $distributionsArray = Distribution::find()
                        ->where('date > \'' . date('Y-m-d') . '\'')
                        ->andWhere([
                                'id_producer' => GlobalParam::getCurrentProducerId(),
                                'active' => 1
                        ])
                        ->orderBy('date ASC')
                        ->all();

                return $distributionsArray;
        }

        public static function filterDistributionsByDateDelay($distributionsArray)
        {
                $producer = GlobalParam::getCurrentProducer() ;
                $dateToday = date('Y-m-d') ;

                foreach($distributionsArray as $keyDistribution => $distribution) {

                        $dateDistribution = $distribution->date ;
                        $dayDistribution = strtolower(date('l', strtotime($dateDistribution))) ;
                        $fieldDayDistributionDelay = 'order_delay_'.$dayDistribution ;
                        $fieldDayDistributionDeadline = 'order_deadline_'.$dayDistribution ;

                        $delay = $producer->order_delay ;
                        $deadline = $producer->order_deadline ;

                        if($producer->$fieldDayDistributionDelay) {
                                $delay = $producer->$fieldDayDistributionDelay ;
                        }

                        if($producer->$fieldDayDistributionDeadline) {
                                $deadline = $producer->$fieldDayDistributionDeadline ;
                        }

                        $countDaysTodayDistribution = number_format((strtotime($dateDistribution) - strtotime($dateToday)) / (24 * 60 * 60) , 0);

                        if(date('H') >= $deadline) {
                                $countDaysTodayDistribution -- ;
                        }

                        if($countDaysTodayDistribution < $delay) {
                                unset($distributionsArray[$keyDistribution]) ;
                        }
                }

                $newDistributionsArray = [] ;
                foreach($distributionsArray as $distribution) {
                        $newDistributionsArray[] = $distribution ;
                }

                return $newDistributionsArray ;
        }

        /**
         * Lie un produit aux jours de distribution futurs.
         *
         * @param Product $product
         */
        public static function linkProductIncomingDistributions($product)
        {
                $distributionsArray = self::getIncomingDistributions();
                foreach ($distributionsArray as $distribution) {
                        $distribution->linkProduct($product);
                }
        }

        /**
         * Lie un produit à la distribution.
         *
         * @param Product $product
         */
        public function linkProduct($product)
        {
                $productDistribution = ProductDistribution::searchOne([
                        'id_distribution' => $this->id,
                        'id_product' => $product->id
                ]);

                if (!$productDistribution) {
                        $productDistribution = new ProductDistribution();
                        $productDistribution->id_distribution = $this->id;
                        $productDistribution->id_product = $product->id;
                }

                $dayDistribution = date('N', strtotime($this->date));
                $daysArray = [
                        1 => 'monday',
                        2 => 'tuesday',
                        3 => 'wednesday',
                        4 => 'thursday',
                        5 => 'friday',
                        6 => 'saturday',
                        7 => 'sunday',
                ];

                $productDistribution->active = 0;
                $day = $daysArray[$dayDistribution];
                if ($product->active && $product->$day) {
                        $productDistribution->active = 1;
                }

                $productDistribution->quantity_max = $product->quantity_max;
                $fieldQuantityMax = 'quantity_max_'.$day ;
                if(isset($product->$fieldQuantityMax) && $product->$fieldQuantityMax > 0) {
                        $productDistribution->quantity_max = $product->$fieldQuantityMax ;
                }

                $productDistribution->save();

                return $productDistribution;
        }

        /**
         * Lie le produit "Don" à la distribution
         */
        public function linkProductGift()
        {
                $productGift = Product::getProductGift();

                if ($productGift) {
                        $productDistribution = ProductDistribution::searchOne([
                                'id_distribution' => $this->id,
                                'id_product' => $productGift->id
                        ]);

                        if (!$productDistribution) {
                                $productDistribution = new ProductDistribution();
                                $productDistribution->id_distribution = $this->id;
                                $productDistribution->id_product = $productGift->id;
                                $productDistribution->active = 1;
                                $productDistribution->save();
                        }
                }
        }

        /**
         * Lie un point de vente aux jours de distribution futurs.
         *
         * @param PointSale $pointSale
         */
        public static function linkPointSaleIncomingDistributions($pointSale)
        {
                $distributionsArray = self::getIncomingDistributions();
                foreach ($distributionsArray as $distribution) {
                        $distribution->linkPointSale($pointSale);
                }
        }

        /**
         *
         * @param type $pointSale
         */
        public function linkPointSale($pointSale)
        {
                $pointSaleDistribution = PointSaleDistribution::searchOne([
                        'id_distribution' => $this->id,
                        'id_point_sale' => $pointSale->id
                ]);

                if (!$pointSaleDistribution) {
                        $pointSaleDistribution = new PointSaleDistribution();
                        $pointSaleDistribution->id_distribution = $this->id;
                        $pointSaleDistribution->id_point_sale = $pointSale->id;
                }

                $dayDistribution = date('N', strtotime($this->date));
                $daysArray = [
                        1 => 'monday',
                        2 => 'tuesday',
                        3 => 'wednesday',
                        4 => 'thursday',
                        5 => 'friday',
                        6 => 'saturday',
                        7 => 'sunday',
                ];

                $pointSaleDistribution->delivery = 0;
                $deliveryDay = 'delivery_' . $daysArray[$dayDistribution];
                if ($pointSale->$deliveryDay) {
                        $pointSaleDistribution->delivery = 1;
                }

                $pointSaleDistribution->save();
        }

        /**
         * Active ou désactive la distribution.
         */
        public function active($active = true)
        {
                PointSaleDistribution::setAll($this->id, true);
                $this->active = (int)$active;
                $this->save();

                if ($active) {
                        // ajout des abonnements
                        Subscription::addAll($this->date);
                }
        }

}