<?php

/**
 * Copyright Guillaume Bourgeois (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 frontend\forms;

use domain\Config\TaxRate\TaxRate;
use domain\Producer\Producer\Producer;
use domain\Producer\Producer\ProducerModule;
use domain\User\User\User;
use domain\User\User\UserModule;
use domain\User\UserGroup\UserGroupModule;
use yii\base\Model;

/**
 * Signup form
 */
class SignupForm extends Model
{
    public $signup_producer_only = false;
    public $username;
    public $email;
    public $password;
    public $name;
    public $lastname;
    public $phone;
    public $is_producer;
    public $siret;
    public $name_producer;
    public $postcode;
    public $city;
    public $id_producer;
    public $option_user_producer;
    public $cgv;
    public $code;
    public $type;
//  public $free_price ;
    public $id_tax_rate_default;
    public $verifyCode;
    public $is_test;
    public $newsletter = false;
    public $newsletter_souke = false;
    public $sponsored_by = false;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['email', 'filter', 'filter' => 'trim'],
            ['email', 'required', 'message' => 'Champs obligatoire', 'when' => function($model) {
                return !$model->signup_producer_only;
            }],
            ['email', 'email'],
            ['email', function ($attribute, $params) {
                $email = $this->$attribute;

                $userExist = User::searchOne([
                    'type' => 'individual',
                    'email' => $email
                ]);

                if ($userExist) {
                    $this->addError($attribute, 'Cet email est déjà utilisé.');
                }
            }],
            [['name', 'lastname', 'phone'], 'required', 'message' => 'Champs obligatoire', 'when' => function($model) {
                return !$model->signup_producer_only;
            }],
            [['name', 'lastname', 'phone', 'option_user_producer'], 'string', 'min' => 2, 'max' => 255],
            ['password', 'required', 'message' => 'Champs obligatoire', 'when' => function($model) {
                return !$model->signup_producer_only;
            }],
            ['password', 'string', 'min' => 6, 'tooShort' => 'Votre mot de passe doit contenir au moins 6 caractères'],
            [['is_producer', 'newsletter', 'newsletter_souke'], 'boolean'],
            ['cgv', 'boolean'],
            ['cgv', function ($attribute, $params) {
                $cgv = $this->$attribute;

                if ($this->option_user_producer == 'producer' && !$cgv) {
                    $this->addError($attribute, 'Vous devez accepter les conditions générales de vente pour vous inscrire.');
                }
            }],
            ['postcode', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $model->option_user_producer == 'producer';
            }],
            ['id_tax_rate_default', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $model->option_user_producer == 'producer';
            }],
            ['city', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $model->option_user_producer == 'producer';
            }],
            [['name_producer', 'type', 'siret', 'is_test'], 'string'],
            ['name_producer', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $model->option_user_producer == 'producer';
            }],
            ['type', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $model->option_user_producer == 'producer';
            }],
            ['siret', function ($attribute, $params) {
                $siret = $this->$attribute;
                $siret = str_replace(' ', '', $siret);

                if (strlen($siret) != 14) {
                    $this->addError($attribute, 'Le numéro SIRET doit contenir 14 caractères');
                    return;
                }

                if (!is_numeric($siret)) {
                    $this->addError($attribute, 'Le numéro SIRET ne doit contenir que des chiffres');
                    return;
                }

                // on prend chaque chiffre un par un
                // si son index (position dans la chaîne en commence à 0 au premier caractère) est pair
                // on double sa valeur et si cette dernière est supérieure à 9, on lui retranche 9
                // on ajoute cette valeur à la somme totale

                $sum = 0;
                for ($index = 0; $index < 14; $index++) {
                    $number = (int)$siret[$index];
                    if (($index % 2) == 0) {
                        if (($number *= 2) > 9)
                            $number -= 9;
                    }
                    $sum += $number;
                }

                // le numéro est valide si la somme des chiffres est multiple de 10
                if (($sum % 10) != 0)
                    $this->addError($attribute, 'Numéro SIRET invalide');
            }],
            ['id_producer', 'integer'],
            ['id_producer', function ($attribute, $params) {
                if ($this->id_producer) {
                    $producer = Producer::findOne($this->id_producer);
                    if (!$producer) {
                        $this->addError($attribute, 'Ce producteur n\'existe pas.');
                    }
                }
            }],
            ['id_producer', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                return $this->option_user_producer == 'user';
            }],
            ['sponsored_by', 'safe'],
            ['code', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
                $producer = Producer::findOne($this->id_producer);
                if ($producer) {
                    return strlen($producer->code);
                } else {
                    return false;
                }
            }],
            ['code', function ($attribute, $params) {
                $code = $this->$attribute;
                $producer = Producer::findOne($this->id_producer);

                if ($producer && strtolower(trim($code)) != strtolower(trim($producer->code))) {
                    $this->addError($attribute, 'Code incorrect');
                }
            }],
            //['free_price', 'number'],
            ['id_tax_rate_default', 'exist',
                'targetClass' => TaxRate::className(),
                'targetAttribute' => ['id_tax_rate_default' => 'id']],
            ['verifyCode', 'captcha', 'message' => 'Veuillez recopier le code de vérification', 'when' => function($model) {
                return $model->is_test != 'isTest';
            }],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'username' => 'Identifiant',
            'password' => 'Mot de passe',
            'rememberMe' => 'Se souvenir de moi',
            'name' => 'Prénom',
            'lastname' => 'Nom',
            'phone' => 'Téléphone',
            'is_producer' => "Je suis professionnel et souhaite mettre en place un système de réservation dans mon établissement",
            'name_producer' => 'Nom de votre structure',
            'siret' => 'Numéro SIRET',
            'postcode' => 'Code postal',
            'city' => 'Commune',
            'id_producer' => 'Producteur',
            'type' => 'Type de producteur',
            'id_tax_rate_default' => 'TVA par défaut',
            'verifyCode' => 'Code de vérification',
            'newsletter' => "S'abonner à l'infolettre de ce producteur",
            'newsletter_souke' => "S'abonner à l'infolettre de Souke",
        ];
    }

    /**
     * Signs user up.
     *
     * @return User|null the saved model or null if saving fails
     */
    public function signup($user = null)
    {
        $userGroupModule = UserGroupModule::getInstance();
        $userModule = UserModule::getInstance();
        $producerModule = \Yii::$app->logic->getProducerModule();

        if ($this->validate()) {

            $sendEmailSignup = false;
            if(!$user) {
                $sendEmailSignup = true;
                $user = $userModule->instanciateUser(User::TYPE_INDIVIDUAL);
                $this->populateUser($user);
            }

            if ($this->isProducer()) {
                $producer = $this->processFormProducer($user);
                $idProducer = $producer->id;
            } else {
                $idProducer = $this->id_producer;
            }

            $producer = $producerModule->findOneProducerById($idProducer);

            if ($user->save() && $producer) {
                \Yii::$app->logic->setProducerContext($producer);

                if(!$this->isProducer()) {
                    if($producer->id_user_group_default) {
                        $userGroupDefault = $userGroupModule->getRepository()->findOneUserGroupById($producer->id_user_group_default);
                        $userModule->getBuilder()->addUserGroup($user, $userGroupDefault);
                    }
                }
                $producerModule->addUser($user, $producer, true, $this->newsletter);
                if($sendEmailSignup) {
                    $userModule->sendEmailSignup($user, $producer);
                }

                return $user;
            }
        }

        return null;
    }

    public function isCustomer()
    {
        return $this->option_user_producer == 'user';
    }

    public function isProducer()
    {
        return $this->option_user_producer == 'producer';
    }

    public function processFormProducer($user)
    {
        $userModule = UserModule::getInstance();
        $producerModule = ProducerModule::getInstance();

        // Création du producteur
        $producer = $producerModule->instanciateProducer();
        $this->populateProducer($producer);
        $producerModule->initProducer($producer);
        $producer->save();

        // Parrainage
        if($this->sponsored_by) {
            $sponsorshipProducerSponsor = $producerModule->getRepository()->findOneProducerById($this->sponsored_by);
            if($sponsorshipProducerSponsor) {
                $producer->sponsored_by = $this->sponsored_by;
                $producer->save();
            }
        }

        /*
         * Envoi d'un email à l'administrateur pour le prévenir
         * qu'un nouveau producteur s'est inscrit
         */
        $producerModule->sendEmailNewProducer($producer);

        // Initialisation de l'utilisateur (statut et liaison au producteur)
        $userModule->initProducer($user, $producer);

        return $producer;
    }

    public function populateUser($user)
    {
        $userModule = UserModule::getInstance();
        $userModule->initPassword($user, $this->password);

        $user->username = $this->email;
        $user->email = $this->email;
        $user->name = $this->name;
        $user->lastname = $this->lastname;
        $user->phone = $this->phone;
        $user->newsletter_souke = $this->newsletter_souke;
    }

    public function populateProducer($producer)
    {
        $producer->name = $this->name_producer;
        $producer->type = $this->type;
        $producer->siret = $this->siret;
        $producer->postcode = $this->postcode;
        $producer->city = $this->city;
        $producer->id_tax_rate_default = $this->id_tax_rate_default;
    }
}