<?php
namespace app\common\model;
use think\Exception;
use think\Db;
class DailyTask extends Base {

    public function updates(){
        $post = request()->post();

        $result = validate('DailyTask')->check($post,[]);
        if(true !== $result){
            $this->error = validate('DailyTask')->getError();
            return false;
        }
        if(!$post['addrs']){
            $this->error='任务地点不能为空';
            return false;
        }
        if(!$post['user_ids']){
            $this->error='检查人员不能为空';
            return false;
        }
//        if(strtotime($post['start_time']) < time()){
//            $this->error = '开始时间不能小于当前时间';
//            return false;
//        }
        if($post['start_time'] >= $post['end_time']){
            $this->error = '结束时间请大于开始时间';
            return false;
        }
        //添加操作
        if($post['id']  == 0){
            $post['addrs']=explode(',',$post['addrs']);
            $post['user_ids']=explode(',',$post['user_ids']);
            $curtime = date('Y-m-d H:i:s');

            $data = array(
                'org_id' => cur_org_id(),
                'title' => $post['title'],
                'status' => 0,
                'create_time' => $curtime,
                'uuid' => new_guid(),        //TODO::是否检测已重复
            );
            if(date('Y-m-d',strtotime($post['start_time'])) != date('Y-m-d',strtotime($post['end_time']))){ //跨天,执行连续天数为0
                $post['days'] = 0;
            }
            $timearr = $this->get_time_arr($post['start_time'],$post['end_time'],$post['hours'],$post['days']);

            Db::startTrans();
            try{
                foreach ($timearr as $k=>$v){
                    $data['start_time'] = $v['start_time'];
                    $data['end_time'] = $v['end_time'];
                    $data['create_yyyymm'] = date('Ym',strtotime($data['start_time']));
                    $data['create_yyyy'] = date('Y',strtotime($data['start_time']));
                    $data['create_yyyymmdd'] = date('Ymd',strtotime($data['start_time']));
                    //添加任务
                    $taskid = Db::name('daily_task')->insertGetId($data);
                    if(!$taskid){
                        exception('创建任务失败');
                    }

                    //添加检查地点
                    $addr = array();
                    $post['addrs'] = array_unique($post['addrs']);
                    foreach ($post['addrs'] as $k=>$v){
                        $addr[] = array(
                            'task_id' => $taskid,
                            'daily_id' => $v
                        );
                    }
                    $taskAddr=Db::name('daily_task_addr')->insertAll($addr);
                    if(!$taskAddr){
                        exception('任务地点保存失败');
                    }

                    //添加检查人员
                    $user = array();
                    $post['user_ids'] = array_unique($post['user_ids']);
                    foreach ($post['user_ids'] as $k=>$v){
                        $user[] = array(
                            'task_id' => $taskid,
                            'user_id' => $v
                        );
                    }
                    $taskUser=Db::name('daily_task_user')->insertAll($user);
                    if(!$taskUser){
                        exception('任务地点保存失败');
                    }
                }

                Db::commit();
                return true;
            }catch (\Exception $e){
                // 回滚事务
                $this->error = $e->getMessage();
                Db::rollback();
                return false;
            }
        }
        //编辑操作
        if($post['id'] > 0){
            $curtime = date('Y-m-d H:i:s');
            $data = array(
                'title' => $post['title'],
                'update_time' => $curtime,
                'start_time' => $post['start_time'],
                'end_time' => $post['end_time'],
                'create_yyyymm' => date('Ym',strtotime($post['start_time'])),
                'create_yyyy' => date('Y',strtotime($post['end_time'])),
                'create_yyyymmdd' => date('Ymd',strtotime($post['start_time'])),
            );

            $taskInfo=$this->getTaskOne($post['id']);
            $addrIds=explode(',',$post['addrs']);
            $userIds=explode(',',$post['user_ids']);

            $addrnew = array_diff($addrIds,$taskInfo['old_addrs']);
            $addrdef = array_diff($taskInfo['old_addrs'],$addrIds);

            $usernew = array_diff($userIds,$taskInfo['old_user_ids']);
            $userdef = array_diff($taskInfo['old_user_ids'],$userIds);
            Db::startTrans();
            try {
                //编辑任务
                $res = Db::name('daily_task')->where('id',$post['id'])->update($data);
                if(!$res){
                    exception('编辑任务失败');
                }
                //编辑检查地点
                if($addrdef){
                    $delAddr=Db::name('daily_task_addr')->where('task_id',$post['id'])->whereIn('daily_id',$addrdef)->delete();
                    if(!$delAddr){
                        exception('地点编辑失败');
                    }
                }

                if($addrnew){
                    $baddr = array();
                    foreach ($addrnew as $k=>$v){
                        $baddr[] = array(
                            'task_id' => $post['id'],
                            'daily_id' => $v
                        );
                    }
                    $addTaskAddr=Db::name('daily_task_addr')->insertAll($baddr);
                    if(!$addTaskAddr){
                        exception('地点编辑失败');
                    }
                }
                //添加检查人员
                if($userdef){
                    $delTaskUser=Db::name('daily_task_user')->where('task_id',$post['id'])->whereIn('user_id',$userdef)->delete();
                    if(!$delTaskUser){
                        \exception('检查人员编辑失败');
                    }
                }
                if($usernew){
                    $buser = array();
                    foreach ($usernew as $k=>$v){
                        $buser[] = array(
                            'task_id' => $post['id'],
                            'user_id' => $v
                        );
                    }
                    $addTaskUser=Db::name('daily_task_user')->insertAll($buser);
                    if(!$addTaskUser){
                        \exception('检查人员编辑失败');
                    }

                }
                Db::commit();
                return true;
            }catch (\Exception $e){
                $this->error = $e->getMessage();
                Db::rollback();
                return false;
            }

        }

    }

    /**
     * 格式化时间,获取时间数组
     * @param $starttime 开始时间
     * @param $endtime 结束时间
     * @param $hours 重复小时
     * @param $days 执行天数
     * @return array
     */
    private function get_time_arr($starttime,$endtime,$hours,$days){
        $onehour = 60*60;
        $oneday = 24*60*60;
        $start = strtotime($starttime);
        $end = strtotime($endtime);
        $ctime = $end - $start;
        $timearr = array();

        $timearr[] = array(
            'start_time' => $starttime,
            'end_time' => $endtime,
        );
        if($hours > 0){
            if($ctime > $hours*$onehour){
                $timearr = array(); //置空
                $i = $hours;
                while(true){
                    $nend = $start + $i*$onehour;
                    $nstart = $start + ($i-$hours)*$onehour;
                    $timearr[] = array(
                        'start_time' => date('Y-m-d H:i',$nstart),
                        'end_time' => date('Y-m-d H:i',$nend),
                    );
                    if($nend >= $end){
                        break;
                    }
                    $i += $hours;
                }
            }
        }

        if($days > 0){
            $timearray = $timearr;
            for ($i=1; $i<=$days;$i++){
                foreach ($timearray as $k=>$v){
                    $timearr[] = array(
                        'start_time' => date('Y-m-d H:i',strtotime($v['start_time']) + $i*$oneday),
                        'end_time' => date('Y-m-d H:i',strtotime($v['end_time']) + $i*$oneday),
                    );
                }
            }
        }
        return $timearr;
    }

    //获取巡查计划任务
    public function getTaskOne($taskId){
        $ret=Db::name('daily_task')->where('id',$taskId)->find();
        //获取计划任务检查组id
        $old_addrs=Db::name('daily_task_addr')
            ->where('task_id',$ret['id'])->select();
        foreach ($old_addrs as $k=>$v){
            $ids[$k]=$v['daily_id'];
        }
        $ret['old_addrs']=$ids;
        //获取计划任务检查人员
        $old_user_ids=Db::name('daily_task_user')->where('task_id',$ret['id'])->select();
        foreach ($old_user_ids as $k=>$v){
            $ids[$k]=$v['user_id'];
        }
        $ret['old_user_ids']=$ids;
        return $ret;
    }

    public function get_list_by_time($orgId,$start,$end){

        $map[] = ['org_id','=',$orgId];
        $map[] = ['del','=',0];
        $map[] = ['start_time','<',$end];
        $map[] = ['end_time','>=',$start];

        $list = $this->field('id,title,start_time,end_time,status')
            ->where($map)
            ->select();
        $list = $list?$list->toArray():[];
        foreach ($list as $k=>$v){
            $userList = Db::name('daily_task_user')
                ->alias('a')
                ->field('u.id,u.real_name')
                ->join('user u','u.id = a.user_id')
                ->where('a.task_id',$v['id'])
                ->column('real_name');
            $list[$k]['users'] = $userList?implode(',',$userList):'';
        }
        return $list?$list:array();
    }
    //分组获取任务计划最近12个月份
    public function get_task_month($org_id){
        $list = $this
            ->field('create_yyyymm')
            ->group('create_yyyymm')
            ->where('org_id',$org_id)
            ->where('del',0)
            ->order('create_yyyymm','desc')
            ->limit(12)
            ->select();
        $list = $list?$list->toArray():array();
        foreach ($list as $k=>$v){
            $list[$k]['create_yyyymm'] = date('Y-m',strtotime($v['create_yyyymm'].'01'));
        }
        return $list;
    }

    //复制任务
    public function plan_data($post,$org){ //TODO::已复制过的月份是否可以继续复制
        $from = strtotime($post['from'].'-01');
        $to = strtotime($post['to'].'-01');
        $max = strtotime(date('Y-m-d', strtotime($post['to'].'-01 +1 month')));
        $cha = $to - $from;

        $map[] = ['del','=',0];
        $map[] = ['org_id','=',$org];
        $map[] = ['create_yyyymm','=',date('Ym',strtotime($post['from'].'-01'))];
        $list = $this->where($map)->select();
        if(!$list){
            $this->error = '要复制的月份下没有任务';
            return false;
        }
        $list = $list->toArray();
        $this->startTrans();
        try{
            $uuid = '';
            while (true) {
                $uuid = new_guid();
                $ret = $this
                    ->where('uuid',$uuid)
                    ->find();
                if(!$ret){
                    break;
                }
            }
            foreach ($list as $k=>$v){
                $start_time = strtotime($v['start_time'])+$cha;
                if($start_time >= $max){
                    continue;
                }
                $v['start_time'] = date('Y-m-d H:i:s',$start_time);
                $v['end_time'] = date('Y-m-d H:i:s',strtotime($v['end_time'])+$cha);
                $v['uuid'] = $uuid;
                $ret = $this->copy_one($v);
                if(!$ret){
                    \exception('复制失败');
                }
            }
            Db::commit();
            return true;
        }catch (Exception $e){
            $this->error = $e->getMessage();
            Db::rollback();
            return false;
        }
    }

    //复制单个任务
    private function copy_one($data){
        $id = $data['id'];
        unset($data['id']);
        $data['status'] = 0;
        $data['create_time'] = date('Y-m-d H:i:s');
        $data['create_yyyymm'] = date('Ym',strtotime($data['start_time']));
        $data['create_yyyy'] = date('Y',strtotime($data['start_time']));
        $data['create_yyyymmdd'] = date('Ymd',strtotime($data['start_time']));
        $addrs = $this->get_task_addr($id);
        $userids = $this->get_task_user($id);

        //添加任务
        $taskid = $this->insertGetId($data);
        if(!$taskid){
            return false;
        }

        //添加检查地点
        $addr = array();
        foreach ($addrs as $k=>$v){
            $addr[] = array(
                'task_id' => $taskid,
                'daily_id' => $v
            );
        }
        $res = Db::name('daily_task_addr')->insertAll($addr);
        if(!$res){
            return false;
        }

        //添加检查人员
        $user = array();
        foreach ($userids as $k=>$v){
            $user[] = array(
                'task_id' => $taskid,
                'user_id' => $v
            );
        }
        $res = Db::name('daily_task_user')->insertAll($user);
        if(!$res){
            return false;
        }
        return true;
    }

    //获取任务检查地点
    public function get_task_addr($taskid){
        $addrlist = Db::name('daily_task_addr')
            ->where('task_id',$taskid)
            ->column('daily_id');
        return $addrlist;
    }

    //获取任务检查人员
    public function get_task_user($taskid){
        $userlist = Db::name('daily_task_user')
            ->where('task_id',$taskid)
            ->column('user_id');
        return $userlist;
    }

    //定时处理超时任务
    public function timer_action(){
        $curTime = date('Y-m-d');
        $map[] = ['del','=',0];
        $map[] = ['status','in',[0,1]];
        $map[] = ['end_time','<',$curTime];
        $this->where($map)
            ->update(['status'=>3]);
        if(!empty($ids)){
            Db::name('task')
                ->where('type',3)
                ->where('bus_id','in',$ids)
                ->delete();
        }
    }

    public function addDailyTask(){
        $curTime = date('Y-m-d H:i:s',time()+12*60*60);
        $map[] = ['a.del','=',0];
        $map[] = ['a.status','=',0];
        $map[] = ['a.start_time','<',$curTime];

        $ids = $this
            ->alias('a')
            ->join('daily_task_user b','b.task_id=a.id')
            ->where($map)
            ->field('a.*,b.user_id')
            ->select();
        if(!empty($ids)){
            $ids = $ids->toArray();
            $a = [];
            foreach ($ids as $k=>$v){
                $check = Db::name('task')
                    ->where('type',3)
                    ->where('org_id',$v['org_id'])
                    ->where('bus_id',$v['id'])
                    ->where('user_id',$v['user_id'])
                    ->find();
                if(empty($check)){
                    $a[]= [
                        'org_id'=>$v['org_id'],
                        'type'=>3,
                        'start_time'=>$v['start_time'],
                        'create_time'=>getTime(),
                        'bus_id'=>$v['id'],
                        'user_id'=>$v['user_id']
                    ];
                }
            }
            if(!empty($a)){
                Db::name('task')
                    ->insertAll($a);
            }
        }
    }

    public function del($id,$userId){
        try{
            $ret = Db::name('daily_task')->where('id',$id)->update([
                'del' => 1,
                'del_user_id' => $userId,
                'del_time' => getTime()
            ]);
            if(!$ret){
                \exception('删除失败');
            }
            Db::name('task')
                ->where('bus_id', $id)
                ->where('type', (new Task())::TASK_TYPE_DAILY)
                ->delete();
        }catch (\Exception $e){
            trace($e->getMessage());
            return false;
        }
        return true;
    }

    public function batchDel($orgId,$userId){
        $data = request()->post();
        $minmonth = date('Y-m');
        if($minmonth >= $data['from']){
            $this->error = '当月任务不能删除';
            return false;
        }

        $where = array(
            'org_id' => $orgId,
            'del' => 0,
            'create_yyyymm' => date('Ym',strtotime($data['from'].'-01'))
        );
        $type = (new Task())::TASK_TYPE_DAILY;
        // 检查是否存在任务栏数据中
        $dailyIds = Db::name('daily_task')
            ->alias('dt')
            ->join('task t','t.bus_id = dt.id')
            ->where('t.type',$type)
            ->where('dt.org_id',$orgId)
            ->where('dt.del',0)
            ->where('dt.create_yyyymm',date('Ym',strtotime($data['from'].'-01')))
            ->column('dt.id');
        Db::startTrans();
        try{
            $default['del'] = 1;
            $default['del_user_id'] = $userId;
            $default['del_time'] = date('Y-m-d H:i:s');
            $result = Db::name('daily_task')
                ->where($where)
                ->update($default);
            if(!$result){
                \exception('操作失败');
            }

            if($dailyIds){
                $ret = Db::name('task')
                    ->where('bus_id', 'in',implode(',',$dailyIds))
                    ->where('type', (new Task())::TASK_TYPE_DAILY)
                    ->delete();
                if(!$ret){
                    \exception('操作失败');
                }
            }


            Db::commit();

            return true;
        }catch (\Exception $e){
            Db::rollback();
            return false;
        }

    }
}