<?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\logic\User\User\Model;

use common\logic\Order\Order\Model\Order;
use common\logic\User\UserProducer\Model\UserProducer;
use common\logic\User\UserUserGroup\Model\UserUserGroup;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\web\IdentityInterface;
use common\components\ActiveRecordCommon;

/**
 * User model
 */
class User extends ActiveRecordCommon implements IdentityInterface
{
    const EVENT_CREATE = 'user.event.create';

    const TYPE_INDIVIDUAL = 'individual';
    const TYPE_LEGAL_PERSON = 'legal-person';
    const TYPE_GUEST = 'guest';

    public static array $types = [
        self::TYPE_GUEST,
        self::TYPE_INDIVIDUAL,
        self::TYPE_LEGAL_PERSON
    ];

    const STATUS_DELETED = 0;
    const STATUS_ACTIVE = 10;
    const STATUS_PRODUCER = 11;
    const STATUS_ADMIN = 13;

    const ID_USER_SYSTEM = 2;

    var $password_old;
    var $password_new;
    var $password_new_confirm;
    var $points_sale = [];
    var $user_groups = [];
    var $one_name;
    var $product_price_percent;
    var $newsletter;
    var $send_mail_welcome;

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

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            TimestampBehavior::class,
        ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday',
                'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday',
                'mail_distribution_sunday', 'is_main_contact', 'newsletter', 'exclude_export_shopping_cart_labels',
                'send_mail_welcome'], 'boolean'],
            [['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code'], 'string'],
            ['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false],
            ['email', 'email', 'message' => 'Cette adresse email n\'est pas valide'],
            ['email', 'verifyEmail'],
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
            ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED, self::STATUS_ADMIN, self::STATUS_PRODUCER]],
            ['password_old', 'verifyPasswordOld'],
            ['password_new', 'verifyPasswordNew'],
            ['password_new_confirm', 'verifyPasswordNewConfirm'],
            [['date_last_connection', 'password_old', 'password_new', 'password_new_confirm', 'password_hash', 'points_sale', 'product_price_percent', 'user_groups'], 'safe'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Prénom',
            'lastname' => 'Nom',
            'phone' => 'Téléphone',
            'address' => 'Adresse',
            'username' => 'Identifiant',
            'password' => 'Mot de passe',
            'rememberMe' => 'Se souvenir de moi',
            'no_mail' => 'Ne pas recevoir d\'email de la part du Chat des Noisettes',
            'mail_distribution_monday' => 'Lundi',
            'mail_distribution_tuesday' => 'Mardi',
            'mail_distribution_wednesday' => 'Mercredi',
            'mail_distribution_thursday' => 'Jeudi',
            'mail_distribution_friday' => 'Vendredi',
            'mail_distribution_saturday' => 'Samedi',
            'mail_distribution_sunday' => 'Dimanche',
            'password_old' => 'Ancien mot de passe',
            'password_new' => 'Nouveau mot de passe',
            'password_new_confirm' => 'Confirmation du nouveau mot de passe',
            'points_sale' => 'Points de vente',
            'type' => 'Type',
            'name_legal_person' => 'Libellé',
            'is_main_contact' => 'Contact principal',
            'product_price_percent' => 'Prix produits : pourcentage',
            'user_groups' => "Groupes d'utilisateurs",
            'evoliz_code' => 'Code client Evoliz',
            'newsletter' => "Inscrit au bulletin d'information",
            'exclude_export_shopping_cart_labels' => "Exclure de l'export d'étiquettes",
            'send_mail_welcome' => "Envoyer un email de bienvenue"
        ];
    }

    /**
     * Vérifie le mot de passe envoyé par l'utilisateur.
     *
     * @param string $attribute
     * @param array $params
     */
    public function verifyPasswordOld($attribute, $params)
    {
        if (strlen($this->password_old)) {
            if (!$this->validatePassword($this->password_old)) {
                $this->addError($attribute, 'Mot de passe invalide.');
            }
        }

        if (!strlen($this->password_old) && (strlen($this->password_new) || strlen($this->password_new_confirm))) {
            $this->addError($attribute, 'Ce champs ne peut être vide');
        }

        if (!strlen($this->password_new) && (strlen($this->password_old) || strlen($this->password_new_confirm))) {
            $this->addError('password_new', 'Ce champs ne peut être vide');
        }

        if (!strlen($this->password_new_confirm) && (strlen($this->password_old) || strlen($this->password_new))) {
            $this->addError('password_new_confirm', 'Ce champs ne peut être vide');
        }
    }

    /**
     * Vérifie le mot de passe de l'utilisateur.
     *
     * @param string $attribute
     * @param array $params
     */
    public function verifyPasswordNew($attribute, $params)
    {
        if (strlen($this->password_new) < 6) {
            $this->addError($attribute, 'Votre mot de passe doit comporter au moins 6 caractères.');
        }
    }

    /**
     * Vérifie la confirmation de mot de passe de l'utilisateur.
     *
     * @param string $attribute
     * @param array $params
     */
    public function verifyPasswordNewConfirm($attribute, $params)
    {
        if ($this->password_new != $this->password_new_confirm) {
            $this->addError($attribute, 'Les deux mots de passe doivent être identiques');
        }
    }

    /**
     * Vérifie l'email de l'utilisateur.
     *
     * @param string $attribute
     * @param array $params
     */
    public function verifyEmail($attribute, $params)
    {
        if ($this->id) {
            $user = User::find()->where("email LIKE :email AND type != :guest AND id != :id")->params(array(':email' => '%' . $this->email . '%', ':id' => $this->id, ':guest' => 'guest'))->one();
        } else {
            $user = User::find()->where("email LIKE :email AND type != :guest")->params(array(':email' => '%' . $this->email . '%', ':guest' => 'guest'))->one();
        }

        if ($user) {
            $this->addError($attribute, 'Cette adresse email est déjà utilisée par un autre utilisateur ');
        }
    }

    /**
     * Vérifie que l'utilisateur a au moins un nom de défini
     *
     * @param $attribute
     * @param $params
     */
    public function verifyOneName($attribute, $params)
    {
        if (strlen($this->lastname) == 0 && strlen($this->name_legal_person) == 0) {
            $this->addError('lastname', 'Vous devez saisir au moins un nom.');
            $this->addError('name_legal_person', 'Vous devez saisir au moins un nom.');
        }
    }

    /*
     * Relations
     */

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

    public function getUserUserGroup()
    {
        return $this->hasMany(UserUserGroup::class, ['id_user' => 'id']);
    }

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function getLastname(): ?string
    {
        return $this->lastname;
    }

    public function getStatus(): string
    {
        return $this->status;
    }

    /**
     * @inheritdoc
     */
    public static function findIdentity($id)
    {
        return static::findOne(['id' => $id]);
    }

    /**
     * @inheritdoc
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }


    /**
     * @inheritdoc
     */
    public function getId()
    {
        return $this->getPrimaryKey();
    }

    /**
     * @inheritdoc
     */
    public function getAuthKey()
    {
        return $this->auth_key;
    }

    /**
     * @inheritdoc
     */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    /**
     * Validates password
     */
    public function validatePassword(string $password): bool
    {
        return \Yii::$app->security->validatePassword($password, $this->password_hash);
    }
}
