<?php
namespace process;

use FilesystemIterator;
use Workerman\Timer;
use support\Db;
use support\Log;
use support\ApiTask;
use support\LibDb;

class TaskCreateReport
{
    private $task;
    private $pdo;
    public function onWorkerStart()
    {
        set_time_limit(3600 * 100);
        ini_set('memory_limit', '2048M');
        
        $this->task = new ApiTask('TaskCreateReport');
        // 每隔60秒检查一次
        // 执行一次大概15秒
        Timer::add(15, function(){
    		$data = $this->task->get();
    		if($data->enable 
    		   && time()>strtotime($data->begin_start_time) //开始时间
    		   && (empty($data->access_time) || time()-strtotime($data->access_time) > $data->interval)
    		){
                $nowTime = getNowTime();
                if($data->interval >= 86400){ //达到或超过1天时
                    $t = explode(' ',$data->begin_start_time); 
                    $jgTime = $t[1];
                    $t = explode(' ',getNowTime()); 
                    $date = $t[0];
                    $nowTime  = $date .' '. $jgTime;
                }
    			$this->task->begin($nowTime);
    			$this->execute($data->access_time,$nowTime);
                $this->task->complete(getNowTime());
    		}
        });
    }

    public function execute($beginTime,$endTime)
    {
         $doingMaxTime = 15 * 60; //15分钟 
         $doingCount = Db::table('smt_task')
            ->where('smttask_state','doing')
            ->where('smttask_dodate','>', date('Y-m-d H:i:s',time()-$doingMaxTime) )
            ->count();
         if(!empty($doingCount)) {
             //print_r('doingCount:'.$doingCount."\r\n");
             return; //还有未完成的任务
         }
         
         $rows = Db::table('smt_task')
        ->join('smt_rules', 'smttask_sr_id', '=', 'sr_id')
        ->select(
                    'smttask_id','smttask_err_count','smttask_isnow','smttask_rundate',
                    'smttask_dodate','smttask_state','smttask_rate',
                    'sr_id','sr_title','sr_rule1','sr_cols','sr_factorys','sr_sql','smt_task.opuser'
        )
        ->where('smttask_err_count','<',3)
        ->whereNotIn('smttask_state',['done','error'])
        ->orderBy('smttask_isnow','desc')
        ->orderBy('smttask_rundate','asc')
        ->get();
        if(empty($rows)) {
            return;
        }
        $this->pdo = new LibDb();
        foreach($rows as $row){
            if(date('Y-m-d') >= $row->smttask_rundate){
                if($row->smttask_state=='doing'){
                    $this->setErrorCount($row);
                }
                $isDoit = true;
                $dodateTimestamp  = $row->smttask_dodate ?  strtotime($row->smttask_dodate) : strtotime($row->smttask_rundate);
                switch($row->smttask_rate){
                    case 'week':
                        $isDoit =  date('Y-m-d',strtotime('+1 week', $dodateTimestamp)) == date('Y-m-d');
                        break;
                    case 'month':
                        $isDoit =  date('Y-m-d',strtotime('+1 month', $dodateTimestamp)) == date('Y-m-d');
                        break;
                    case 'year':
                        $isDoit =  date('Y-m-d',strtotime('+1 year', $dodateTimestamp)) == date('Y-m-d');
                        break;
                }
                if($isDoit){
                    //print_r("isDoit\r\n");
                    $this->setDoDate($row, date('Y-m-d H:i:s'));
                    $this->doit($row);
                    break; //每次执行一个任务
                }
            }
        }
        $this->pdo->Close();
        //print_r("End.\r\n");
    }
        
    public function doit($row)
    {
        $this->setState($row,'doing');
        $sqlArr = json_decode($row->sr_sql,true);
        if($sqlArr){
            $clientCount = count($sqlArr);
            $this->setRunQty($row,0,$clientCount);
            $i=1;
            $fields = [
                'NULL smt_report_id',
                $row->smttask_id .' smt_report_ver',
                't.smt_report_cid',
                't.smt_report_pid',
                $row->sr_id .' smt_report_sr_id',
                't.smt_p_outnum smt_report_outnum',
                '"'.$row->opuser.'" smt_report_user',
                't.smt_report_rule',
                '0 smt_report_copy_id',
                '"'.date('Y-m-d H:i:s').'" smt_report_time',
                '0 smt_report_area',
                '0 smt_report_export',
                'NULL smt_report_export_time',
                '0 smt_report_export_lock',
                'mms_link_id smt_report_ktype',
                'markline_ms_id smt_report_markline_ms_id',
                '0 smt_report_newsale',
                '0 smt_report_money',
                '"" smt_report_saleno',
                '0 smt_report_records',
                't.smt_report_from_pid',
                't.smt_report_scba2_pid1',
            ];
            foreach($sqlArr as $cid=>$arr){
                foreach($arr as $k=>$strSql){
                    $arr[$k] = "SELECT * FROM (".$strSql.") t".$k;
                }
                $unionSql = implode(' UNION ', $arr);
                $selectSql = "SELECT ". implode(',', $fields) ." FROM (".$unionSql.") t GROUP BY smt_report_ver,smt_report_cid,smt_report_pid";
                $insertSQL = "INSERT IGNORE INTO smt_report ".$selectSql;
				Log::channel('task_create_report')->info($insertSQL);
                try{
                    //$this->pdo->Begin();
                    //写清单头
                    //Db::insert($insertSQL);
					$this->pdo->query("INSERT IGNORE INTO smt_report_head ".$selectSql." LIMIT 1");
                    //写清单明细
                    //Db::insert($insertSQL);
					$this->pdo->query($insertSQL);
                    //$this->pdo->End();
                    $where = [
                        ['smt_report_ver',$row->smttask_id],
                        ['smt_report_cid',$cid],
                    ];
                    $recordCount = Db::table('smt_report')->where($where)->count();
                    $this->pdo->query("UPDATE smt_report_head SET smt_report_records=".$recordCount
                                    ." WHERE smt_report_ver=".$row->smttask_id." AND smt_report_cid='".$cid."'");
                    $this->setErrorInfo($row,'记录数: '.$recordCount);
                    if($recordCount ==0) Log::channel('task_create_report')->info('--0记录:'.$insertSQL."---");
                    //如果超出规定数量
                    if($recordCount>1000){
                        //锁记录  清单头
                        Db::table('smt_report_head')
                            ->where($where)
                            ->update([
                                    'smt_report_export_lock'=>1
                            ]);
                        //锁记录  清单明细
                        Db::table('smt_report')
                            ->where($where)
                            ->update([
                                    'smt_report_export_lock'=>1
                            ]);
                        //BPM 记录
                        $smt_bpm_check_data = [
                            'sbc_ver'=>$row->smttask_id,
                            'sbc_cid'=>$cid,
                            'sbc_sr_id'=>$row->sr_id,
                            'sbc_count'=>$recordCount,
                        ];
                        Db::table('smt_bpm_check')
                            ->updateOrInsert(
                              [
                                'sbc_ver'=>$row->smttask_id,
                                'sbc_cid'=>$cid,
                                'sbc_sr_id'=>$row->sr_id,
                              ],
                              $smt_bpm_check_data);
                    }
                } catch(Exception $e) {
                    Log::channel('task_create_report')->info($e->getMessage());
                    Log::channel('task_create_report')->info($insertSQL);
                    $this->setErrorCount($row);
                }
                $this->setRunQty($row,$i,$clientCount);
                $i++;
            }
            $this->setState($row,'done');
        }else{
            $this->setErrorCount($row);
        }
    }
        
    public function setState($row,$state)
    {
        Db::table('smt_task')
        ->where('smttask_id','=',$row->smttask_id)
        ->update(['smttask_state'=>$state]);
    }

    public function setDoDate($row,$date)
    {
        Db::table('smt_task')
        ->where('smttask_id','=',$row->smttask_id)
        ->update(['smttask_dodate'=>$date]);
    }
        
    public function setRunQty($row,$qty,$count)
    {
        Db::table('smt_task')
        ->where('smttask_id','=',$row->smttask_id)
        ->update(['smttask_runqty'=>$qty.' / '.$count]);
    }
        
    public function setErrorCount($row)
    {
        $upData = [
            'smttask_err_count'=>$row->smttask_err_count+1
        ];
        Db::table('smt_task')
        ->where('smttask_id','=',$row->smttask_id)
        ->update($upData);
    }
        
    public function setErrorInfo($row,$info)
    {
        $upData = [
            'smttask_send_err_info'=>$info
        ];
        Db::table('smt_task')
        ->where('smttask_id','=',$row->smttask_id)
        ->update($upData);
    }
}