<?php
namespace common\models\forms;

use common\components\Model;
use common\helpers\Date;
use common\helpers\Form;
use common\libs\logging\operate\AdminOperate;
use common\models\Config;
use common\models\Period;
use yii\db\Exception;

/**
 * Login form
 */
class ConfigPeriodForm extends Model
{
    public $calcYear;
    public $closeWeekDate;
    public $closeTime;

    public function init() {
        parent::init();
        $this->adminOperateLogger = new AdminOperate([
            'fetchClass' => Config::class,
        ]);
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['calcYear', 'closeWeekDate', 'closeTime'], 'required'],
            [['calcYear'], 'integer', 'max'=>2050, 'min'=>2018],
            [['closeWeekDate'], 'match', 'pattern' => '/^[0-6]/', 'message' => '请填写有效的星期'],
            [['closeTime'], 'time', 'format'=>'HH:mm'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'calcYear' => '计算至年份',
            'closeWeekDate' => '封期日期',
            'closeTime' => '封期时间',
        ];
    }

    /**
     * 更新配置
     * @return bool|null
     * @throws Exception
     */
    public function update(){
        if(!$this->validate()){
            return null;
        }
        $configs = Config::find()->where("TYPE='period'")->orderBy('SORT ASC')->indexBy('CONFIG_NAME')->asArray()->all();
        $configNames = [];
        foreach ($configs as $value){
            $configNames[] = $value['CONFIG_NAME'];
        }
        $beforeData = Config::getConfigByType('period');
        $this->adminOperateLogger->saveBeforeContent=$beforeData;

        $transaction = \Yii::$app->db->beginTransaction();
        try{
            if(!Config::updateAll(['VALUE'=>$this->calcYear, 'UPDATED_AT'=>Date::nowTime()], "CONFIG_NAME='calcYear'")){
                throw new Exception('计算至年份更新失败');
            }
            if(!Config::updateAll(['VALUE'=>$this->closeWeekDate, 'UPDATED_AT'=>Date::nowTime()], "CONFIG_NAME='closeWeekDate'")){
                throw new Exception('封期日期更新失败');
            }
            if(!Config::updateAll(['VALUE'=>$this->closeTime, 'UPDATED_AT'=>Date::nowTime()], "CONFIG_NAME='closeTime'")){
                throw new Exception('封期时间更新失败');
            }
            // 异步处理添加任务
            $taskKey = \Yii::$app->swooleAsyncTimer->asyncHandle('config/update-period', \Yii::$app->request->post());
            if($taskKey === false){
                throw new Exception('请求异步服务器失败');
            }
            $transaction->commit();
        } catch (Exception $e){
            $transaction->rollBack();
            $this->addError('closeWeekDate', $e->getMessage());
            return null;
        }
        $afterData = Config::getConfigByType('period');
        $this->adminOperateLogger->saveAfterContent=$afterData;
        unset($beforeData,$afterData);
        $this->adminOperateLogger->clean()->save([
            'optType' => '更新期数配置',
        ]);
        return true;
    }

    /**
     * 异步更新期数表
     * @return bool
     * @throws Exception
     */
    public function updateAsync(){
        if(!$this->validate()){
            return false;
        }
        $period = Period::instance();
        // 获取当前期数
        $periodNum = $period->getNowPeriodNum();
        // 把所有没封期的期数都删掉只保留当前期
        Period::deleteAll('IS_CLOSED=0 AND PERIOD_NUM<>:PERIOD_NUM', [':PERIOD_NUM'=>$periodNum]);
        //$nowPeriodStart = $period->getNowPeriodStart();
        $periodEnd = $period->getNowPeriodEnd();
        // 开始时间归到0点
        $nowPeriodStart = $periodEnd + 1;
        // 循环到2030年的所有日期
        $nowPeriodNum = $periodNum + 1;
        $startDateTemp = $nowPeriodStart;
        $transaction = \Yii::$app->db->beginTransaction();
        try{
            for($startDate = $nowPeriodStart + 86400; $startDate < strtotime($this->calcYear.'-12-31'); $startDate += 86400 ){
                if(Date::dateWeek(\date('Y-m-d',$startDate)) == $this->closeWeekDate){
                    $periodModel = new Period();
                    $periodModel->PERIOD_NUM = $nowPeriodNum;
                    $periodModel->START_TIME = $startDateTemp;
                    $periodModel->END_TIME = Date::dayMinute($startDate, $this->closeTime) - 1;
                    $periodModel->CALC_MONTH = date('m', $periodModel->END_TIME);
                    $periodModel->CALC_YEAR = date('Y', $periodModel->END_TIME);
                    $periodModel->CREATED_AT = Date::nowTime();
                    if(!$periodModel->save()){
                        throw new Exception(Form::formatErrorsForApi($periodModel->getErrors()));
                    };
                    $startDateTemp = $periodModel->END_TIME+1;
                    // 查看上一期的月份是否比本期的月份不等，则把上一期设置为月结点
                    $lastPeriod = Period::findOne(['PERIOD_NUM'=>$nowPeriodNum-1]);
                    if($lastPeriod){
                        if($lastPeriod['CALC_MONTH'] != $periodModel->CALC_MONTH){
                            $lastPeriod->IS_MONTH = 1;
                        }
                        // 查看上一期的年份是否比本期的不等，则把上一期的设置为年节点
                        if($lastPeriod['CALC_YEAR'] != $periodModel->CALC_YEAR){
                            $lastPeriod->IS_YEAR = 1;
                        }
                        if($lastPeriod->IS_MONTH || $lastPeriod->IS_YEAR){
                            if(!$lastPeriod->save()){
                                throw new Exception(Form::formatErrorsForApi($lastPeriod->getErrors()));
                            }
                        }
                    }
                    $periodModel = null;
                    $lastPeriod = null;
                    unset($periodModel, $lastPeriod);
                    $nowPeriodNum += 1;
                    //echo date('Y-m-d', $startDate).PHP_EOL;
                }
            }
            $transaction->commit();
        } catch (Exception $e){
            $transaction->rollBack();
            $this->addError('update', $e->getMessage());
            return false;
        }
        return true;
    }
}
