<?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 Yii;
use common\components\ActiveRecordCommon;
use common\helpers\Departments;
use yii\helpers\Html;

/**
 * This is the model class for table "etablissement".
 *
 * @property integer $id
 * @property string $name
 * @property string $siret
 * @property string $logo
 * @property string $photo
 * @property string $description
 * @property string $postcode
 * @property string $city
 * @property float credit_limit_reminder
 * @property boolean online_payment
 * @property string mentions
 * @property string gcs
 * @property boolean option_allow_user_gift
 * @property string credit_functioning
 * @property boolean use_credit_checked_default
 * @property float credit_limit
 * @property string background_color_logo
 *
 */
class Producer extends ActiveRecordCommon
{
        const CREDIT_FUNCTIONING_MANDATORY = 'mandatory';
        const CREDIT_FUNCTIONING_OPTIONAL = 'optional';
        const CREDIT_FUNCTIONING_USER = 'user';

        const HINT_CREDIT_FUNCTIONING = '<ul>'
        . '<li>Optionnelle : l\'utilisateur choisit s\'il utilise son Crédit ou non. Les commandes peuvent être payées ou impayées.</li>'
        . '<li>Obligatoire : toutes les commandes de l\'utilisateur son comptabilisées au niveau du Crédit. Toutes les commandes sont payées.</li>'
        . '<li>Basée sur l\'utilisateur : Crédit obligatoire si l\'utilisateur a le crédit activé au niveau de son compte, système de Crédit non affiché sinon.</li>'
        . '</ul>';

        public static $creditFunctioningArray = [
                self::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire',
                self::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle',
                self::CREDIT_FUNCTIONING_USER => 'Basée sur l\'utilisateur',
        ];

        const BEHAVIOR_DELETE_ORDER_DELETE = 'delete';
        const BEHAVIOR_DELETE_ORDER_STATUS = 'status';

        var $secret_key_payplug;

        /**
         * @inheritdoc
         */
        public static function tableName()
        {
                return 'producer';
        }

        /**
         * @inheritdoc
         */
        public function rules()
        {
                return [
                        [['name', 'type', 'id_tax_rate_default'], 'required'],
                        [['tiller_provider_token', 'tiller_restaurant_token'], 'required', 'when' => function ($model) {
                                return $model->tiller == true;
                        }],
                        [['order_delay', 'order_deadline', 'order_delay_monday', 'order_deadline_monday', 'order_delay_tuesday', 'order_deadline_tuesday',
                                'order_delay_wednesday', 'order_deadline_wednesday', 'order_delay_thursday', 'order_deadline_thursday', 'order_delay_friday',
                                'order_deadline_friday', 'order_delay_saturday', 'order_deadline_saturday', 'order_delay_sunday', 'order_deadline_sunday',
                                'id_tax_rate_default', 'document_quotation_duration'], 'integer'],
                        [['order_deadline', 'order_deadline_monday', 'order_deadline_tuesday', 'order_deadline_wednesday',
                                'order_deadline_thursday', 'order_deadline_friday', 'order_deadline_saturday',
                                'order_deadline_sunday', ], 'in', 'range' => [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]],
                        ['order_delay', 'in', 'range' => [1, 2, 3, 4, 5, 6, 7]],
                        ['code', function ($attribute, $params) {
                                $code = $this->$attribute;
                                $producer = Producer::findOne(['code' => $code]);
                                if ($producer && $producer->id != $this->id) {
                                        $this->addError($attribute, 'Ce code est déjà utilisé par un autre producteur.');
                                }
                        }],
                        [['document_quotation_prefix', 'document_invoice_prefix', 'document_delivery_note_prefix'], function($attribute, $params) {
                                if(!ctype_upper($this->$attribute)) {
                                        $this->addError($attribute, 'Ne doit contenir que des majuscules') ;
                                }
                        }],
                        [['description', 'mentions', 'gcs', 'order_infos', 'slug', 'secret_key_payplug', 'background_color_logo', 'option_behavior_cancel_order', 'tiller_provider_token', 'tiller_restaurant_token', 'status',
                                'document_infos_bottom', 'document_infos_quotation', 'document_infos_invoice', 'document_infos_delivery_note', 'address'], 'string'],
                        [['negative_balance', 'credit', 'active', 'online_payment', 'user_manage_subscription', 'option_allow_user_gift', 'use_credit_checked_default', 'tiller'], 'boolean'],
                        [['name', 'siret', 'logo', 'photo', 'postcode', 'city', 'code', 'type', 'credit_functioning', 'option_behavior_cancel_order', 'document_quotation_prefix', 'document_quotation_first_reference', 'document_invoice_prefix', 'document_invoice_first_reference', 'document_delivery_note_prefix', 'document_delivery_note_first_reference'], 'string', 'max' => 255],
                        [['free_price', 'credit_limit_reminder', 'credit_limit'], 'double'],
                        ['free_price', 'compare', 'compareValue' => 0, 'operator' => '>=', 'type' => 'number', 'message' => 'Prix libre doit être supérieur ou égal à 0'],
                ];
        }

        /**
         * @inheritdoc
         */
        public function attributeLabels()
        {
                return [
                        'id' => 'ID',
                        'name' => 'Nom',
                        'siret' => 'Siret',
                        'logo' => 'Logo',
                        'photo' => 'Photo',
                        'description' => 'Description',
                        'postcode' => 'Code postal',
                        'city' => 'Ville',
                        'code' => 'Code',
                        'order_delay' => 'Délai de commande',
                        'order_deadline' => 'Heure limite de commande',
                        'order_delay_monday' => 'Délai de commande (lundi)',
                        'order_deadline_monday' => 'Heure limite de commande (lundi)',
                        'order_delay_tuesday' => 'Délai de commande (mardi)',
                        'order_deadline_tuesday' => 'Heure limite de commande (mardi)',
                        'order_delay_wednesday' => 'Délai de commande (mercredi)',
                        'order_deadline_wednesday' => 'Heure limite de commande (mercredi)',
                        'order_delay_thursday' => 'Délai de commande (jeudi)',
                        'order_deadline_thursday' => 'Heure limite de commande (jeudi)',
                        'order_delay_friday' => 'Délai de commande (vendredi)',
                        'order_deadline_friday' => 'Heure limite de commande (vendredi)',
                        'order_delay_saturday' => 'Délai de commande (samedi)',
                        'order_deadline_saturday' => 'Heure limite de commande (samedi)',
                        'order_delay_sunday' => 'Délai de commande (dimanche)',
                        'order_deadline_sunday' => 'Heure limite de commande (dimanche)',
                        'negative_balance' => 'Solde négatif',
                        'credit' => 'Crédit pain',
                        'active' => 'Actif',
                        'date_creation' => 'Date de création',
                        'order_infos' => 'Informations',
                        'slug' => 'Slug',
                        'type' => 'Type de producteur',
                        'credit_limit_reminder' => 'Seuil de crédit limite avant relance',
                        'online_payment' => 'Activer le paiement en ligne',
                        'secret_key_payplug' => 'Clé secrète Payplug',
                        'user_manage_subscription' => 'Autoriser les utilisateurs à gérer leurs abonnements',
                        'mentions' => 'Mentions légales',
                        'gcs' => 'Conditions générales de vente',
                        'option_allow_user_gift' => 'Autoriser les utilisateurs à effectuer un don à la plateforme lors de leur commande',
                        'credit_functioning' => 'Utilisation du Crédit par l\'utilisateur',
                        'credit_limit' => 'Crédit limite',
                        'use_credit_checked_default' => 'Cocher par défaut l\'option "Utiliser mon crédit" lors de la commande de l\'utilisateur',
                        'background_color_logo' => 'Couleur de fond du logo',
                        'option_behavior_cancel_order' => 'Comportement lors de la suppression d\'une commande',
                        'tiller' => 'Tiller',
                        'tiller_provider_token' => 'Token provider',
                        'tiller_restaurant_token' => 'Token restaurant',
                        'status' => 'Statut',
                        'id_tax_rate_default' => 'Taxe',
                        'document_quotation_prefix' => 'Préfixe des devis',
                        'document_quotation_first_reference' => 'Première référence des devis',
                        'document_quotation_duration' => 'Durée du devis',
                        'document_invoice_prefix' => 'Préfixe des factures',
                        'document_invoice_first_reference' => 'Première référence des factures',
                        'document_delivery_note_prefix' => 'Préfixe des bons de livraison',
                        'document_delivery_note_first_reference' => 'Première référence des bons de livraison',
                        'document_infos_bottom' => 'Informations affichées en bas des documents',
                        'document_infos_quotation' => 'Informations affichées en bas des devis',
                        'document_infos_invoice' => 'Informations affichées en bas des factures',
                        'document_infos_delivery_note' => 'Informations affichées en bas des bons de livraison',
                        'address' => 'Adresse'
                ];
        }

        /*
         * Relations
         */

        public function getUserProducer()
        {
                return $this->hasMany(
                        UserProducer::className(),
                        ['id_producer' => 'id']
                );
        }

        public function getUser()
        {
                return $this->hasMany(User::className(), ['id_producer' => 'id']);
        }

        public function getContact()
        {
                return $this->hasMany(User::className(), ['id_producer' => 'id'])
                        ->where(['status' => User::STATUS_PRODUCER]);
        }

        public function getTaxRate()
        {
                return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate_default']);
        }

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

        /**
         * Retourne la liste des établissements pour l'initialisation d'une liste
         * sélective.
         *
         * @return array
         */
        public static function getProducerPopulateDropdown()
        {
                $producers = Producer::find()
                        ->where([
                                'active' => true,
                        ])
                        ->orderBy('postcode, city ASC')
                        ->all();

                $departments = Departments::get();
                $dataProducers = [];
                $optionsProducers = [];
                foreach ($producers as $p) {
                        if (!key_exists('d' . substr($p->postcode, 0, 2), $dataProducers)) {
                                $dataProducers['d' . substr($p->postcode, 0, 2)] = '<strong>' . $departments[substr($p->postcode, 0, 2)] . '</strong>';
                                $optionsProducers['d' . substr($p->postcode, 0, 2)] = ['disabled' => true];
                        }

                        $dataProducers[$p->id] = '<span class="glyphicon glyphicon-lock"></span> ' . Html::encode($p->name) . ' - ' . Html::encode($p->postcode) . ' ' . Html::encode($p->city) . ' <span class="glyphicon glyphicon-lock"></span>';

                        if (strlen($p->code)) {
                                $optionsProducers[$p->id] = ['class' => 'lock'];
                        }
                }

                return ['data' => $dataProducers, 'options' => $optionsProducers];
        }

        /**
         * Retourne le CA de l'établissement pour un mois donné.
         *
         * @param string $period
         * @param boolean $format
         * @return string
         */
        public function getTurnover($period = '', $format = false)
        {
                if (!$period) {
                        $period = date('Y-m');
                }

                $connection = Yii::$app->getDb();
                $command = $connection->createCommand('
            SELECT SUM(product_order.price * product_order.quantity) AS turnover
            FROM `order`, product_order, distribution, product
            WHERE `order`.id = product_order.id_order
            AND distribution.id_producer = :id_producer
            AND `order`.id_distribution = distribution.id
            AND product_order.id_product = product.id
            AND distribution.date > :date_begin
            AND distribution.date < :date_end', [
                        ':date_begin' => date('Y-m-31', strtotime("-1 month", strtotime($period))),
                        ':date_end' => date('Y-m-01', strtotime("+1 month", strtotime($period))),
                        ':id_producer' => $this->id
                ]);

                $result = $command->queryOne();
                $turnover = $result['turnover'];

                if ($format) {
                        return number_format($turnover, 2) . ' €';
                } else {
                        return $turnover;
                }
        }

        /**
         * Retourne le montant à facturer pour une période donnée.
         *
         * @param string $periode
         * @param float $ca
         * @param boolean $format
         * @return string
         */
        public function getMAmountBilled($format = false)
        {
                if ($format) {
                        return number_format($this->free_price, 2) . ' €';
                } else {
                        return $this->free_price;
                }
        }

        /**
         * Retourne la facture d'une période donnée.
         *
         * @param string $periode
         * @return Facture
         */
        public function getInvoice($period = '')
        {
                if (!$period) {
                        $period = date('Y-m', strtotime('-1 month'));
                }

                $invoice = Invoice::searchOne(
                        ['id_producer' => $this->id, 'period' => ':period'],
                        ['params' => [':period' => $period]]
                );

                return $invoice;
        }

        /**
         * Retourne la facture du mois dernier.
         *
         * @return Facture
         */
        public function getInvoiceLastMonth()
        {
                return $this->getInvoice(date('Y-m', strtotime('-1 month')));
        }

        /**
         * Retourne une configuration d'un établissement donné.
         *
         * @param string $config
         * @param integer $id_etablissement
         * @return mixed
         */
        public static function getConfig($config = '', $idProducer = 0)
        {
                if (strlen($config)) {
                        if (!$idProducer) {
                                $idProducer = GlobalParam::getCurrentProducerId();
                        }

                        $producer = self::findOne($idProducer);
                        if ($producer) {
                                return $producer->$config;
                        }
                }

                return false;
        }

        /**
         * Retourne le montant de l'abonnement à prix libre définit par
         * le producteur.
         *
         * @param boolean $format
         * @return mixed
         */
        public function getFreePrice($format = true)
        {
                if (!is_null($this->free_price)) {
                        if ($format) {
                                return number_format($this->free_price, 2, ',', false) . ' € HT';
                        } else {
                                return $this->free_price;
                        }
                }
        }

        /**
         * Lie un utilisateur à un producteur.
         *
         * @param integer $id_user
         * @param integer $id_producer
         * @return UserProducer
         */
        public static function addUser($idUser, $idProducer, $bookmark = 1)
        {
                $userProducer = UserProducer::searchOne([
                        'user_producer.id_user' => $idUser,
                        'user_producer.id_producer' => $idProducer
                ]);

                if (!$userProducer) {
                        $newUserProducer = new UserProducer;
                        $newUserProducer->id_producer = $idProducer;
                        $newUserProducer->id_user = $idUser;
                        $newUserProducer->credit = 0;
                        $newUserProducer->active = 1;
                        $newUserProducer->bookmark = (int)$bookmark;
                        $newUserProducer->save();
                } else {
                        if (!$userProducer->active) {
                                $userProducer->active = 1;
                                $userProducer->save();
                        }
                }

                return $userProducer;
        }

        public function getSpecificDelays()
        {
                $array = [] ;
                $daysArray = [
                        'monday','tuesday','wednesday','thursday','friday','saturday','sunday'
                ] ;


                foreach($daysArray as $day) {
                        $fieldDelay = 'order_delay_'.$day ;
                        $fieldDeadline = 'order_deadline_'.$day ;

                        $delay = $this->order_delay ;
                        $deadline = $this->order_deadline ;
                        if($this->$fieldDelay) {
                                $delay = $this->$fieldDelay ;
                        }
                        if($this->$fieldDeadline) {
                                $deadline = $this->$fieldDeadline ;
                        }

                        $array[$day] = [
                                'order_delay' => $delay,
                                'order_deadline' => $deadline,
                        ] ;
                }

                return $array ;
        }

        public function hasSpecificDelays()
        {
                $daysArray = [
                        'monday','tuesday','wednesday','thursday','friday','saturday','sunday'
                ] ;

                foreach($daysArray as $day) {
                        $fieldDelay = 'order_delay_'.$day ;
                        $fieldDeadline = 'order_deadline_'.$day ;

                        if($this->$fieldDelay || $this->$fieldDeadline) {
                                return true ;
                        }
                }

                return false ;
        }

        /**
         * Retourne le chemin vers le fichier contenant la clé secrète d'API de Payplug
         *
         * @return string
         */
        public function getFilenameSecretKeyPayplug()
        {
                return '../../common/config/payplug/' . $this->id . '.key';
        }

        /**
         * Enregistre la clé secrète d'API de Payplug dans un fichier
         */
        public function saveSecretKeyPayplug()
        {
                if ($this->online_payment) {
                        $handle = fopen($this->getFilenameSecretKeyPayplug(), "w");
                        fwrite($handle, $this->secret_key_payplug);
                        fclose($handle);
                }
        }

        /**
         * Retourne la clé secrète d'API de Payplug.
         *
         * @return string
         */
        public function getSecretKeyPayplug()
        {
                if (file_exists($this->getFilenameSecretKeyPayplug())) {
                        $handle = fopen($this->getFilenameSecretKeyPayplug(), "r");
                        $filesize = filesize($this->getFilenameSecretKeyPayplug());
                        if ($handle && $filesize) {
                                $secretKey = fread($handle, $filesize);
                                fclose($handle);
                                return $secretKey;
                        }
                }

                return '';
        }

        /**
         * Retourne le compte producteur de démonstration.
         *
         * @return Producer
         */
        public static function getDemoAccount()
        {
                $producer = Producer::find()->where('name LIKE \'Démo\'')->one();
                return $producer;
        }

        /**
         * Retourne true si le compte est un compte de démo.
         *
         * @return boolean
         */
        public function isDemo()
        {
                if (strpos($this->name, 'Démo') !== false) {
                        return true;
                }

                return false;
        }

        public function getFullAddress($nl2br = false)
        {
                $address = '' ;
                $address .= $this->name."\n" ;

                if(strlen($this->address)) {
                        $address .= $this->address."\n" ;
                }

                if(strlen($this->postcode) || strlen($this->city)) {
                        $address .= $this->postcode.' '.$this->city ;
                }

                if($nl2br) {
                        $address = nl2br($address) ;
                }

                return $address ;
        }

        public function getHtmlLogo()
        {
                $html = '' ;

                if(strlen($this->logo)) {
                        $html = '<img src="'.$this->getUrlLogo().'" class="producer-logo" />' ;
                }

                return $html ;
        }

        public function getUrlLogo()
        {
                return Yii::$app->urlManagerProducer->getHostInfo().'/'.Yii::$app->urlManagerProducer->baseUrl.'/uploads/'.$this->logo ;
        }

        public function getEmailOpendistrib()
        {
                return $this->slug.'@opendistrib.net' ;
        }

}
        
