<?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;

class Document extends ActiveRecordCommon
{
        const STATUS_DRAFT = 'draft';
        const STATUS_VALID = 'valid';

        /**
         * @inheritdoc
         */
        public function rules()
        {
                return [
                        [['name', 'id_user'], 'required'],
                        [['date'], 'safe'],
                        [['comment', 'address'], 'string'],
                        [['id_user', 'id_producer'], 'integer'],
                        [['name', 'reference', 'status'], 'string', 'max' => 255],
                        [['deliveryNotes'], 'safe']
                ];
        }

        /**
         * @inheritdoc
         */
        public function attributeLabels()
        {
                return [
                        'id' => 'ID',
                        'name' => 'Nom',
                        'reference' => 'Référence',
                        'date' => 'Date',
                        'comment' => 'Commentaire',
                        'id_user' => 'Utilisateur',
                        'address' => 'Adresse',
                        'id_producer' => 'Producteur',
                        'status' => 'Statut',
                ];
        }

        /*
         * Relations
         */

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

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

        public function relationOrders($fieldIdDocument)
        {
                $defaultOptionsSearch = Order::defaultOptionsSearch();

                return $this->hasMany(Order::className(), [$fieldIdDocument => 'id'])
                        ->with($defaultOptionsSearch['with'])
                        ->joinWith($defaultOptionsSearch['join_with']);
        }


        /*
         * Méthodes
         */

        public function getAmount($type = Order::AMOUNT_TOTAL, $format = false)
        {
                return $this->_getAmountGeneric($type, false, $format);
        }

        public function getAmountWithTax($type = Order::AMOUNT_TOTAL, $format = false)
        {
                return $this->_getAmountGeneric($type, true, $format);
        }

        protected function _getAmountGeneric($type = Order::AMOUNT_TOTAL, $withTax = true, $format = false)
        {
                $amount = 0;
                $ordersArray = $this->orders;

                foreach ($ordersArray as $order) {
                        $order->init();
                        if ($withTax) {
                                $amount += $order->getAmountWithTax($type);
                        } else {
                                $amount += $order->getAmount($type);
                        }
                }

                if ($format) {
                        return Price::format($amount);
                } else {
                        return $amount;
                }
        }

        public function getPointSale()
        {
                if (isset($this->orders) && isset($this->orders[0])) {
                        return $this->orders[0]->pointSale;
                } else {
                        return '';
                }
        }

        public function getDistribution()
        {
                if (isset($this->orders) && isset($this->orders[0])) {
                        return $this->orders[0]->distribution;
                } else {
                        return '';
                }
        }

        public function getClass()
        {
                return str_replace('common\models\\', '', get_class($this));
        }

        public function getType()
        {
                $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 isValidClass($typeDocument)
        {
                return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']);
        }

        public function generateReference()
        {
                $class = $this->getClass();
                $classLower = strtolower($class);
                if ($classLower == 'deliverynote') {
                        $classLower = 'delivery_note';
                }

                $prefix = Producer::getConfig('document_' . $classLower . '_prefix');
                $oneDocumentExist = $class::searchOne(['status' => Document::STATUS_VALID] , ['orderby' => 'reference DESC']);

                if ($oneDocumentExist) {
                        $reference = $oneDocumentExist->reference;
                        $pattern = '#([A-Z]+)?([0-9]+)#';
                        preg_match($pattern, $reference, $matches, PREG_OFFSET_CAPTURE);
                        $sizeNumReference = strlen($matches[2][0]);
                        $numReference = ((int)$matches[2][0]) + 1;
                        $numReference = str_pad($numReference, $sizeNumReference, '0', STR_PAD_LEFT);

                        return $prefix . $numReference;
                } else {
                        $firstReference = Producer::getConfig('document_' . $classLower . '_first_reference');

                        if (strlen($firstReference) > 0) {
                                return $firstReference;
                        } else {
                                return $prefix . '00001';
                        }
                }
        }

        public function generatePdf($destination)
        {
                $producer = GlobalParam::getCurrentProducer();
                $content = Yii::$app->controller->renderPartial('/document/download', [
                        'producer' => $producer,
                        'document' => $this
                ]);

                $contentFooter = '<div id="footer">';
                $contentFooter .= '<div class="infos-bottom">' . Html::encode($producer->document_infos_bottom) . '</div>';
                if ($this->isStatusValid() || $this->isStatusDraft()) {
                        $contentFooter .= '<div class="reference-document">';
                        if ($this->isStatusValid()) {
                                $contentFooter .= $this->getType() . ' N°' . $this->reference;
                        }
                        if ($this->isStatusDraft()) {
                                $contentFooter .= $this->getType() . ' non validé';
                                if($this->getType() == 'Facture') {
                                        $contentFooter .= 'e' ;
                                }
                        }
                        $contentFooter .= '</div>';
                }
                $contentFooter .= '</div>';

                $pdf = new Pdf([
                        'mode' => Pdf::MODE_UTF8,
                        'format' => Pdf::FORMAT_A4,
                        'orientation' => Pdf::ORIENT_PORTRAIT,
                        'destination' => $destination,
                        'content' => $content,
                        'filename' => $this->getFilename(),
                        'cssFile' => Yii::getAlias('@webroot/css/document/download.css'),
                        'methods' => [
                                'SetHTMLFooter' => $contentFooter
                        ]
                ]);

                return $pdf->render();
        }

        public function send()
        {
                if(isset($this->user) && strlen($this->user->email) > 0) {
                        $producer = GlobalParam::getCurrentProducer();

                        $subjectEmail = $this->getType() ;
                        if($this->isStatusValid()) {
                                $subjectEmail .= ' N°'.$this->reference ;
                        }

                        $email = Yii::$app->mailer->compose(
                                [
                                        'html' => 'sendDocument-html',
                                        'text' => 'sendDocument-text'
                                ], [
                                'document' => $this,
                        ])
                                ->setTo($this->user->email)
                                ->setFrom([$producer->getEmailOpendistrib() => $producer->name])
                                ->setSubject('['.$producer->name.'] '.$subjectEmail) ;

                        $this->generatePdf(Pdf::DEST_FILE) ;
                        $email->attach($this->getFilename());

                        return $email->send() ;
                }

                return false ;
        }

        public function changeStatus($status)
        {
                if ($status == Document::STATUS_VALID) {
                        $this->status = $status;
                        $this->reference = $this->generateReference();
                }
        }

        public function getStatusWording()
        {
                return ($this->status == self::STATUS_DRAFT) ? 'Brouillon' : 'Validé';
        }

        public function getStatusCssClass()
        {
                return ($this->status == self::STATUS_DRAFT) ? 'default' : 'success';
        }

        public function getHtmlLabel()
        {
                $label = $this->getStatusWording();
                $classLabel = $this->getStatusCssClass();
                return '<span class="label label-' . $classLabel . '">' . $label . '</span>';
        }

        public function isStatus($status)
        {
                return $this->status == $status;
        }

        public function isStatusDraft()
        {
                return $this->isStatus(self::STATUS_DRAFT);
        }

        public function isStatusValid()
        {
                return $this->isStatus(self::STATUS_VALID);
        }

        public function getProductsOrders()
        {
                $productsOrdersArray = [];
                if ($this->orders && count($this->orders)) {
                        foreach ($this->orders as $order) {
                                foreach ($order->productOrder as $productOrder) {
                                        if (!isset($productsOrdersArray[$productOrder->id_product])) {
                                                $productsOrdersArray[$productOrder->id_product] = [$productOrder];
                                        } else {
                                                $productOrderMatch = false;
                                                foreach ($productsOrdersArray[$productOrder->id_product] as &$theProductOrder) {
                                                        if ($theProductOrder->unit == $productOrder->unit && $theProductOrder->price == $productOrder->price) {
                                                                $theProductOrder->quantity += $productOrder->quantity;
                                                                $productOrderMatch = true;
                                                        }
                                                }
                                                if (!$productOrderMatch) {
                                                        $productsOrdersArray[$productOrder->id_product][] = $productOrder;
                                                }
                                        }
                                }
                        }
                }

                return $productsOrdersArray;
        }

        public function getFilename()
        {
                return Yii::getAlias('@app/web/pdf/'.$this->getType().'-' . $this->reference. '.pdf') ;
        }

}
