<?php

namespace common\modules\triggers\models;

use common\modules\messageTemplate\models\MessageTemplate;
use common\modules\triggers\components\conditions\Conditions;
use Faker\Provider\tr_TR\DateTime;
use Yii;
use common\modules\messageTemplate\components\Templates;
use common\modules\users\models\User;
use common\components\UnisenderAPI;
use yii\helpers\Json;

/**
 * This is the model class for table "trigger_trigger".
 *
 * @property integer $id
 * @property integer $active
 * @property string $name
 * @property string $description
 * @property integer $owner_id
 * @property string $date_create
 * @property integer $timeout
 * @property integer $message_template_id
 *
 * @property TriggerCondition[] $triggerConditions
 * @property TriggerConnection[] $triggerConnections
 * @property User $owner
 */
class TriggerTrigger extends \common\components\ActiveRecordModel
{
    const PAGE_SIZE = 10;

    public $conditions = [];

    public function name()
    {
        return 'Триггеры';
    }

    public function afterFind(){
        /** @var TriggerCondition $condition */
        foreach($this->triggerConditions as $condition) {
            $this->conditions[$condition->group_number][$condition->getPrimaryKey()] = [
                'id' => $condition->condition_id
            ];
            foreach($condition->triggerParams as $param) {
                $this->conditions[$condition->group_number][$condition->getPrimaryKey()]['params'][$param->key] = $param->value;
            }
        }
    }

    public function afterSave($insert,$changedAttributes){
        parent::afterSave($insert,$changedAttributes);


        if ($this->scenario == 'update') {
            foreach($this->triggerConditions as $condition) {
                TriggerParam::deleteAll(['condition_id' => $condition->getPrimaryKey()]);
                TriggerCondition::deleteAll(['id' => $condition->getPrimaryKey()]);
            }
        }
        // Сбросили ключи
        $this->conditions = array_values($this->conditions);
        // Перебираем условия в цикле
        foreach($this->conditions as $group_index=>$condition_array) {
            foreach($condition_array as $condition) {
                $conditionModel = new TriggerCondition();
                $conditionModel->group_number = $group_index;
                $conditionModel->trigger_id = $this->id;
                $conditionModel->condition_id = $condition['id'];
                if ($conditionModel->save()) {
                    if (array_key_exists('params', $condition)) {
                        foreach($condition['params'] as $key=>$param) {
                            $paramModel = new TriggerParam();
                            $paramModel->condition_id = $conditionModel->getPrimaryKey();
                            $paramModel->key = $key;
                            $paramModel->value = $param;
                            if (!$paramModel->save())
                                echo current(current($paramModel->getErrors()));
                        }
                    }
                }
            }
        }
    }

    public function getConditionTable(){
        // Формируем html будущей таблицы, открыли тег
        $table = '<table class="table table-bordered">';
        // Формируем тело будущей таблицы
        $table .= '<tbody>';
        // Если есть ошибка
        if ($this->getErrors('conditions')) {
            $error = $this->getErrors('conditions');
            $table .= '<tr><td style="color: red;">'.$error[0].'</td></tr>';
        }
        // Тут добавляем кнопки управления
        if (count($this->conditions)>0) {
            // Условие если эта форма уже содержит параметры
            foreach($this->conditions as $condition_array) {
                $table .= Conditions::getControlButtons($condition_array);
            }
        } else
            // И если это новая форма, еще пустая
            $table .= Conditions::getControlButtons();
        $table .= '</tbody>';
        // Формируем футер
        $table .= '<tfoot>';
        $table .= '<td><button type="button" class="btn btn-primary add-and-condition">Добавить условие "И"</button></td>';
        $table .= '</tfoot>';
        // Закрываем таблицу
        $table .= '</table>';
        return $table;
    }

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

    public function behaviors()
    {
        return [];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['active', 'owner_id', 'timeout', 'message_template_id'], 'integer'],
            [['name', 'owner_id', 'timeout'], 'required'],
            [['description'], 'string'],
            [['date_create'], 'safe'],
            [['name'], 'string', 'max' => 255],
            [['conditions'], function($attribute, $params) {
                if (!is_array($this->$attribute) || count($this->$attribute)===0) {
                    $this->addError($attribute, 'Conditions is empty or has a wrong format');
                }
            },'skipOnEmpty'=>false, 'skipOnError'=>false],
            [['owner_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['owner_id' => 'id']],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'active' => 'Активно',
            'name' => 'Название триггера',
            'description' => 'Описание триггера',
            'owner_id' => 'Автор',
            'date_create' => 'Дата создания',
            'timeout' => 'Задержка перед выполнением (секунд)',
            'message_template_id' => 'Шаблон письма',
            'conditions' => 'Условия',
        ];
    }

    /**
     * @return TriggerCondition[]
     */
    public function getTriggerConditions()
    {
        return $this->hasMany(TriggerCondition::className(), ['trigger_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getTriggerConnections()
    {
        return $this->hasMany(TriggerConnection::className(), ['trigger_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getOwner()
    {
        return $this->hasOne(User::className(), ['id' => 'owner_id']);
    }

    public function scenarios(){
        return [
            'default' => ['active','name','description','owner_id','date_create','timeout','message_template_id','conditions'],
            'update' => ['active','name','description','owner_id','date_create','timeout','message_template_id','conditions'],
        ];
    }

    /**
     * Метод возвращает массив актуальных на данный момент триггеров
     * @param $id
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getActualTriggers($id=null) {
        return ($id===null)
            ? TriggerTrigger::find()->indexBy('id')->all()
            : TriggerTrigger::find()->joinWith('triggerConditions')->where(['trigger_condition.condition_id' => $id])->all();
    }

    /**
     * Тут выполняем то, что произойдет когда триггер сработает
     *
     * @param array $params
     * @return string
     */
    public function initAction($params=array()){
        $email = (!Yii::$app->user->isGuest) ? Yii::$app->user->identity->email : null;
        if ($email===null && array_key_exists('email', $params))
            $email = $params['email'];
        else
            return 'Email not found';

        /** @var \DateTime $time_now */
        $time_now=new \DateTime();
        /** @var MessageTemplate $templateModel */
        $templateModel = MessageTemplate::findOne($this->message_template_id);
        /** @var Templates $template */
        $template = new Templates($this->message_template_id);
        $sender = new UnisenderAPI();
        // Create the send list
        $newList = $sender->createList();
        $newListObject=Json::decode($newList);
        if (array_key_exists('result', $newListObject) && is_array($newListObject['result']) && array_key_exists('id', $newListObject['result'])) {
            $newListId=$newListObject['result']['id'];
            // Subscribe user to new List
            $sender->subscribe(['list_ids' => $newListId, 'fields[email]' => $email, 'double_optin' => 1]);
            // Create new message
            $newMessage=$sender->createEmailMessage(Yii::$app->name, $email, $templateModel->subject, $template->getTemplate(), $newListId);
            // Decode result
            $newMessageObject=Json::decode($newMessage);
            if (array_key_exists('result', $newMessageObject) && is_array($newMessageObject['result']) && array_key_exists('message_id', $newMessageObject['result'])) {
                // Get the message ID
                $newMessageId=$newMessageObject['result']['message_id'];
                // Create new campaign
                $newCampaign = $sender->createCampaign($newMessageId);
                // Parse the result
                $newCampaignObject = Json::decode($newCampaign);
                if (array_key_exists('result', $newCampaignObject) && is_array($newCampaignObject['result']) && array_key_exists('campaign_id', $newCampaignObject['result'])) {
                    $newCampaignId = $newCampaignObject['result']['campaign_id'];

                    $schedule = new TriggerSchedule();
                    $schedule->sended=1;
                    $schedule->checked=0;
                    $schedule->message_id=$newMessageId;
                    $schedule->message=$template->getTemplate();
                    $schedule->email=$email;
                    $schedule->time=$time_now->format('Y-m-d H:i:s');
                    $schedule->date_create=$time_now->format('Y-m-d H:i:s');
                    $schedule->list_id=$newListId;
                    $schedule->campaign_id=$newCampaignId;
                    if ($schedule->save()) {
                        return true;
                    } else {
                        return (current(current($schedule->getErrors())));
                    }
                } else {
                    $error = (array_key_exists('error', $newCampaignObject)) ? $newCampaignObject['error'].' (createCampaign)' : 'Неизвестная ошибка (CreateCampaign)';
                    return $error;
                }
            } else {
                $error = (array_key_exists('error', $newMessageObject)) ? $newMessageObject['error'].' (createMessage)' : 'Неизвестная ошибка (CreateMessage)';
                return $error;
            }
        } else {
            $error = (array_key_exists('error', $newListObject)) ? $newListObject['error'].' (createList)' : 'Неизвестная ошибка (CreateList)';
            return $error;
        }
    }
}
