<?php

namespace app\common\Model;

use Exception;
use function GuzzleHttp\Promise\task;
use service\DateService;
use service\RandomService;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\facade\Hook;

/**
 * 任务
 * Class Organization
 * @package app\common\Model
 */
class Task extends CommonModel
{
    protected $append = ['priText', 'statusText', 'liked', 'stared', 'tags', 'childCount', 'hasUnDone', 'parentDone', 'hasComment', 'hasSource', 'canRead'];

    public function read($code)
    {
        if (!$code) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $code])->field('id', true)->find()->toArray();
        if (!$task) {
            throw new Exception('该任务已失效', 404);
        }
        $project = Project::where(['code' => $task['project_code']])->field('name,open_begin_time')->find();
        $stage = TaskStages::where(['code' => $task['stage_code']])->field('name')->find();
        $task['executor'] = null;
        if ($task['assign_to']) {
            $task['executor'] = Member::where(['code' => $task['assign_to']])->field('name,code,avatar')->find();
        }
        $exchange_list=explode(',',$task['exchange_list']);
        $copied_list=explode(',',$task['copied_list']);
        $task['exchange_info']=null;
        $task['copied_info']=null;
        foreach($exchange_list as $k=>$v){
            $find=Member::where(['code'=>$v])->field('name,code,avatar')->find();
            if($find){
                $task['exchange_info'][]=$find;
            }
        }
        foreach($copied_list as $k=>$v){
            $find=Member::where(['code'=>$v])->field('name,code,avatar')->find();
            if($find){
                $task['copied_info'][]=$find;
            }
        }
        if($task['department_liaison']){
            $task['liasion_info']=MemberAccount::where(['code'=>$task['department_liaison']])->field('name,member_code as code,avatar')->find();
        }else{
            $task['liasion_info']=[];
        }
        if($task['department']){
            $task['department_info']=Department::where(['code'=>$task['department']])->field('name')->find();
        }else{
            $task['department_info']=[];
        }
        if ($task['pcode']) {
            $task['parentTask'] = self::where(['code' => $task['pcode']])->field('id', true)->find();
            $parents = [];
            if (isset($task['path'])) {
                $paths = explode(',', $task['path']);
                if ($paths) {
                    foreach ($paths as $parentCode) {
                        $item = self::where(['code' => $parentCode])->field('name')->find();
                        $parents[] = ['code' => $parentCode, 'name' => $item['name']];
                    }
                }
            }
            $task['parentTasks'] = array_reverse($parents);
        }
        $task['openBeginTime'] = $project['open_begin_time'];
        $task['projectName'] = $project['name'];
        $task['stageName'] = $stage['name'];
        //TODO 查看权限
        return $task;
    }

    /**
     * @param $projectCode
     * @param $deleted
     * @throws DbException
     */
    public function listForProject($projectCode, $deleted)
    {
        $this->_list($where);
    }

    public function dateTotalForProject($projectCode, $beginTime = '', $endTime = '')
    {
        !$beginTime && $beginTime = date("Y-m-d", strtotime("-20 day"));
        !$endTime && $endTime = nowTime();
        $dateList = DateService::getDateFromRange($beginTime, $endTime);
        $list = [];
        if ($dateList) {
            foreach ($dateList as $date) {
                $currentDate = "{$date} 00:00:00";
                $currentDateEnd = "{$date} 23:59:59";
                $total = Task::where("project_code  = '{$projectCode}' and (create_time between '{$currentDate}' and '{$currentDateEnd}')")->count('id');
                $list[] = ['date' => $date, 'total' => $total];
            }
        }
        return $list;
    }

    public function edit($code, $data)
    {

        if (!$code) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $code, 'deleted' => 0])->field('id', true)->find();
        if (!$task) {
            throw new Exception('该任务在回收站中无法编辑', 1);
        }
        if (isset($data['description']) && $data['description'] == '<p><br></p>') {
            $data['description'] = "";
        }
        $result = self::update($data, ['code' => $code]);
        $member = getCurrentMember();
        $type = '';
        if (isset($data['name'])) {
            $type = 'name';
        }
        if (isset($data['description'])) {
            $type = 'content';
            if (!$data['description']) {
                $type = 'clearContent';
            }
        }
        if (isset($data['pri'])) {
            $type = 'pri';
        }
        if (isset($data['status'])) {
            $type = 'status';
        }
        if (isset($data['begin_time'])) {
            $type = 'setBeginTime';
            if (!$data['begin_time']) {
                $type = 'clearBeginTime';
            }
        }
        if (isset($data['end_time'])) {
            $type = 'setEndTime';
            if (!$data['end_time']) {
                $type = 'clearEndTime';
            }
        }
        if (isset($data['work_time'])) {
            $type = 'setWorkTime';
        }
        $type && self::taskHook($member['code'], $code, $type);
        //TODO 任务动态
        return $result;
    }

    public function taskSources($code)
    {
        if (!$code) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $code])->field('id', true)->find();
        if (!$task) {
            throw new Exception('该任务不存在', 2);
        }
        $sources = SourceLink::where(['link_code' => $code, 'link_type' => 'task'])->field('id', true)->order('id desc')->select()->toArray();
        if ($sources) {
            foreach ($sources as &$source) {
                $source = SourceLink::getSourceDetail($source['code']);
            }
        }
        return $sources;
    }

    /**
     * @param $code
     * @param bool $like
     * @return bool
     * @throws \think\Exception
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function like($code, $like = true)
    {
        if (!$code) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $code, 'deleted' => 0])->field('id', true)->find();
        if (!$task) {
            throw new Exception('该任务在回收站中不能点赞', 1);
        }
        if ($like) {
            $result = self::where(['code' => $code])->setInc('like');
        } else {
            $result = self::where(['code' => $code])->setDec('like');
        }
        $member = getCurrentMember();
        TaskLike::likeTask($code, $member['code'], $like);
        return $result;
    }

    /**
     * @param $code
     * @param bool $star
     * @return bool
     * @throws \think\Exception
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function star($code, $star = true)
    {
        if (!$code) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $code, 'deleted' => 0])->field('id', true)->find();
        if (!$task) {
            throw new Exception('该任务在回收站中不能收藏', 1);
        }
        if ($star) {
            $result = self::where(['code' => $code])->setInc('star');
        } else {
            $result = self::where(['code' => $code])->setDec('star');
        }
        $member = getCurrentMember();
        Collection::starTask($code, $member['code'], $star);
        return $result;
    }

    /**
     * 创建任务
     * @param $stageCode
     * @param $projectCode
     * @param $name
     * @param $memberCode
     * @param string $assignTo
     * @param string $parentCode
     * @param string $pri
     * @param string $description
     * @param array $tagCodes
     * @return Task
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function createTask($stageCode, $projectCode, $name, $memberCode, $assignTo = '', $parentCode = '', $pri = '', $description = '', $tagCodes = [], $beginTime = '', $endTime = '',$data=[])
    {
        if (!$name) {
            return error(1, '请填写任务标题');
        }
        $stage = TaskStages::where(['code' => $stageCode])->field('id')->find();
        if (!$stage) {
            return error(2, '该任务列表无效');
        }
        $project = Project::where(['code' => $projectCode, 'deleted' => 0])->field('id,open_task_private')->find();
        if (!$project) {
            return error(3, '该项目已失效');
        }
        if ($parentCode) {
            $parentTask = self::where(['code' => $parentCode])->find();
            if (!$parentTask) {
                return error(8, '父任务无效');
            }
            if ($parentTask['deleted']) {
                return error(6, '父任务在回收站中无法编辑');
            }
            if ($parentTask['done']) {
                return error(7, '父任务已完成,无法添加新的子任务');
            }
        }
        if ($assignTo) {
            $assignMember = Member::where(['code' => $assignTo])->field('id')->find();
            if (!$assignMember) {
                return error(4, '任务执行人有误');
            }
        }

        Db::startTrans();
        try {
            $taskTitles = explode("\n", $name);
            foreach ($taskTitles as $taskTitle) {
                if (!trim($taskTitle)) {
                    continue;
                }
                $maxNum = self::where(['project_code' => $projectCode])->max('id_num');
                if (!$maxNum) {
                    $maxNum = 0;
                }
                $maxSort = self::where('project_code', $projectCode)->where('stage_code', $stageCode)->max('sort');
                $maxSort = $maxSort ?? 0;
                $path = '';
                if ($parentCode) {
                    $parentTask['path'] && $parentTask['path'] = ",{$parentTask['path']}";
                    $path = "{$parentTask['code']}{$parentTask['path']}";
                }
                $code= TaskStages::where('project_code',$projectCode)->where('name','进行中')->where('deleted',0)->value('code');

                $datas = [
                    'create_time' => nowTime(),
                    'code' => createUniqueCode('task'),
                    'create_by' => $memberCode,
                    'assign_to' => $assignTo,
                    'id_num' => $maxNum + 1,
                    'sort' => $maxSort + 65536,
                    'project_code' => $projectCode,
                    'pcode' => $parentCode,
                    'path' => $path,
                    'stage_code' => $code,
                    'pri' => $pri,
                    'description' => $description,
                    'begin_time' => $beginTime,
                    'end_time' => date('Y-m-d H:i:s',bcdiv($endTime,1000)),
                    'private' => $project['open_task_private'] ? 1 : 0,
                    'name' => trim($taskTitle),
                    'exchange_list' => $data['exchangeList'],
                    'copied_list' => $data['copied_list'],
                    'department' => $data['department_code'],
                    'department_liaison' => $data['liasion_code'],
                    'status' => 2,
                ];
                $result = self::create($datas);
//                self::update(['sort' => $result['id']], ['id' => $result['id']]);
                self::taskHook($memberCode, $datas['code'], 'create');
                if ($parentCode) {
                    self::taskHook($memberCode, $parentCode, 'createChild', '', '', 0, '', '', ['taskName' => trim($taskTitle)]);
                }
                $isExecutor = 0;
                $logType = 'inviteMember';
                if ($assignTo) {
                    if ($memberCode == $assignTo) {
                        $isExecutor = 1;
                        $logType = 'claim';
                    }
//                    Task::taskHook($memberCode, $data['code'], $logType, $assignTo);
                    TaskMember::inviteMember($assignTo, $datas['code'], 1, $isExecutor);
                }
                if (!$assignTo || !$isExecutor) {
                    TaskMember::inviteMember($memberCode, $datas['code'], 0, 1);
                }
                if ($tagCodes) {
                    foreach ($tagCodes as $tagCode) {
                        TaskTag::setTag($tagCode, $datas['code']);
                    }
                }
                if(isset($data['file_list']) && $data['file_list']){
                   $file_list= explode(',',$data['file_list']);
                  foreach ($file_list as $v){
                    \app\common\Model\SourceLink::createSource('file', $v, 'task', $datas['code']);
                    }
                }
            }

            //todo 添加任务动态

            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return error(9, $e->getMessage());
        }
        return $this->read($result['code']);
    }

    public function taskDone($taskCode, $done)
    {
        if (!$taskCode) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $taskCode])->find();
        if (!$task) {
            throw new Exception('任务已失效', 2);
        }
        if ($task['deleted']) {
            throw new Exception('任务在回收站中无法进行编辑', 3);
        }
        if ($task['pcode'] && $task['parentDone']) {
            throw new Exception('父任务已完成,无法重做子任务', 4);
        }
        if ($task['hasUnDone']) {
            throw new Exception('子任务尚未全部完成,无法完成父任务', 55);
        }

        Db::startTrans();
        try {
            $result = self::update(['done' => $done], ['code' => $taskCode]);
            //todo 添加任务动态,编辑权限检测
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            throw new Exception($e->getMessage());
        }
        $member = getCurrentMember();
        $done ? $type = 'done' : $type = 'redo';
        self::taskHook($member['code'], $taskCode, $type);
        if ($task['pcode']) {
            $done ? $type = 'doneChild' : $type = 'redoChild';
            self::taskHook($member['code'], $task['pcode'], $type);
        }
        return $result;
    }

    /**
     * 指派任务
     * @param $taskCode
     * @param $executorCode
     * @return TaskMember|bool
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function assignTask($taskCode, $executorCode)
    {
        if (!$taskCode) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $taskCode])->find();
        if (!$task) {
            throw new Exception('任务已失效', 2);
        }
        if ($task['deleted']) {
            throw new Exception('任务在回收站中无法进行指派', 3);
        }
        Db::startTrans();
        try {
            $result = TaskMember::inviteMember($executorCode, $taskCode, 1);
            if($task['exchange_list']){
                $exchange_list=explode(',',$task['exchange_list']);
                foreach ($exchange_list as $k=>$exchange){
                    if($executorCode==$exchange){
                        unset($exchange_list[$k]);
                    }
                }
                if($exchange_list){
                    $task->exchange_list=implode(',',$exchange_list);
                    $task->save();
                }else{
                    $task->exchange_list='';
                    $task->save();
                }
            }
            //todo 添加任务动态,编辑权限检测
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            throw new Exception($e->getMessage());
        }
        return $result;
    }

    public function batchAssignTask($taskCodes, $executorCode)
    {
        if ($taskCodes) {
            try {
                foreach ($taskCodes as $taskCode) {
                    $this->assignTask($taskCode, $executorCode);
                }
            } catch (Exception $e) {
                return error(201, $e->getMessage());
            }
        }
        return true;
    }

    /**
     * @param $taskCode
     * @param $comment
     * @param $mentions
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function createComment($taskCode, $comment, $mentions = [],$type=0)
    {
        if (!$taskCode) {
            throw new Exception('请选择任务', 1);
        }
        $task = self::where(['code' => $taskCode])->withAttr('exchange_list', function($value) {
            if($value){
                return explode(',',$value);
            }else{
                return [];
            }
        })->withAttr('transferred', function($value) {
            if($value){
                return explode(',',$value);
            }else{
                return [];
            }
        })
        ->find();
        if (!$task) {
            throw new Exception('任务已失效', 2);
        }
        $task=$task->toArray();
//        $data = [
//            'member_code' => getCurrentMember()['code'],
//            'source_code' => $taskCode,
//            'action_type' => 'task',
//            'code' => createUniqueCode('projectLog'),
//            'create_time' => nowTime(),
//            'is_comment' => 1,
//            'content' => $comment,
//            'type' => 'comment'
//        ];
        $comments='comment';
        if($type==1){
            $data['status']=2;//进行中
            if($task['exchange_list']){
                $transferred=$task['transferred'];
                array_push($transferred,$task['exchange_list'][0]);
                $data['transferred']=implode(',',$transferred);
                $executorCode=$task['exchange_list'][0];
                unset($task['exchange_list'][0]);
                if($task['exchange_list']){
                    $data['exchange_list']=implode(',',$task['exchange_list']);
                }else{
                    $data['exchange_list']='';
                }
                TaskMember::inviteMember($executorCode, $taskCode, 1);
                $code= TaskStages::where('project_code',$task['project_code'])->where('name','进行中')->where('deleted',0)->value('code');
                if(!$code){
                    throw new Exception('任务列表CODE不存在', 1);
                }
                $data['stage_code']=$code;
                self::where('id',$task['id'])->update($data);
            }else{
                $code= TaskStages::where('project_code',$task['project_code'])->where('name','已完成')->where('deleted',0)->value('code');
                if(!$code){
                    throw new Exception('任务列表CODE不存在', 1);
                }
                $data['status']=1;
                $data['done']=1;
                $data['execute_status']='done';
                $data['stage_code']=$code;
                self::name('task')->where('id',$task['id'])->update($data);
            }
            $comments='pass';
        }elseif($type==2){
            $comments='reject';
            $data['status']=2;
            $code= TaskStages::where('project_code',$task['project_code'])->where('name','进行中')->where('deleted',0)->value('code');
            if(!$code){
                throw new Exception('任务列表CODE不存在', 1);
            }
            $data['stage_code']=$code;
            self::name('task')->where('id',$task['id'])->update($data);
        }elseif($type==3){
            $comments='add';
            $code= TaskStages::where('project_code',$task['project_code'])->where('name','待验收')->where('deleted',0)->value('code');
            if(!$code){
                throw new Exception('任务列表CODE不存在', 1);
            }
            $data['stage_code']=$code;
            $data['status']=4;
            self::name('task')->where('id',$task['id'])->update($data);
        }
        self::taskHook(getCurrentMember()['code'], $taskCode, $comments, '', 1, '', $comment, '', $mentions);

        return true;
//        return ProjectLog::create($data);
    }

    /**
     * 任务排序,事件:把 $preCode 移动到 $nextCode 前面
     * @param $preCode string 前一个移动的列表
     * @param $nextCode string 后一个移动的列表
     * @param $toStageCode string 要移动到到的分组
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function sort($preCode, $nextCode, $toStageCode)
    {
        $preTask = self::where(['code' => $preCode])->field('sort,stage_code,done')->find();
        if ($preCode == $nextCode) {
            return false;
        }
        if ($preTask) {
            $done = $preTask['done'];
            if ($nextCode) {
                $nextTask = self::where(['code' => $nextCode])->field('sort')->find();
                $nextPreTask = self::where('sort', '<', $nextTask['sort'])->where('code', '<>', $nextCode)->where('stage_code', '=', $toStageCode)->where('done', $done)->order('sort desc')->find();
                $nextPreTaskSort = $nextPreTask ? $nextPreTask['sort'] : 0;
                $newSort = (int)($nextTask['sort'] + $nextPreTaskSort) / 2;
            } else {
                $maxSort = self::where('stage_code', '=', $toStageCode)->where('done', $done)->max('sort');
                $newSort = $maxSort + 65536;
            }
            if ($newSort and $newSort > 50) {
                $preTask->stage_code = $toStageCode;
                $preTask->sort = $newSort;
                $preTask->save();
            } else {
//                小于安全值
                $this->resetSort($preTask['stage_code'], $done);
                $this->sort($preCode, $nextCode, $toStageCode);
            }
            return true;
        }
        return false;
    }


    public function resetSort($stageCode, $done)
    {
        $taskList = self::where('stage_code', $stageCode)->order('sort asc, id asc')->where('done', $done)->select();
        if ($taskList) {
            $sort = 65536;
            foreach ($taskList as $task) {
                $task->sort = $sort;
                $task->save();
                $sort += 65536;
            }
        }
    }

    /**
     * 任务排序
     * @param $stageCode string 移到的任务列表code
     * @param $codes array 经过排序的任务code列表
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    /* public function sort($stageCode, $codes)
     {
         if (!$codes) {
             return false;
         }
         if ($codes) {
             $stage = TaskStages::where(['code' => $stageCode])->find();
             $sort = 0;
             foreach ($codes as $key => $code) {
                 $task = self::where(['code' => $code])->find();
                 self::update(['sort' => $sort, 'stage_code' => $stageCode], ['code' => $code]);
                 $sort += 65536;
                 if ($task['stage_code'] != $stageCode) {
                     self::taskHook(getCurrentMember()['code'], $code, 'move', '', '', '', '', '', ['stageName' => $stage['name']]);
                 }
             }
             return true;
         }
         return false;
     }*/

    /**
     * 成员任务
     * @param string $memberCode
     * @param int $done
     * @param int $taskType 搜索类型 1-我执行的 2-我参与的 3-我创建的
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getMemberTasks($memberCode = '', $done = 0, $taskType = 1, $page = 1, $pageSize = 10)
    {
        if (!$memberCode) {
            $memberCode = getCurrentMember()['code'];
        }
        if ($page < 1) {
            $page = 1;
        }
        $offset = ($page - 1) * $pageSize;
        $limit = $pageSize;
        $prefix = config('database.prefix');
        $doneSql = '';
        if ($done != -1) {
            $doneSql = " and t.done = {$done}";
        }
        //我执行的
        if ($taskType == 1) {
            $sql = "select *,t.id as id,t.name as name,t.code as code,t.create_time as create_time,t.end_time,t.begin_time from {$prefix}task as t join {$prefix}project as p on t.project_code = p.code where  t.deleted = 0 {$doneSql} and t.assign_to = '{$memberCode}' and p.deleted = 0 order by t.id desc";
        }
        //我参与的
        if ($taskType == 2) {
            $sql = "select *,t.id as id,t.name as name,t.code as code,t.create_time as create_time,t.end_time,t.begin_time from {$prefix}task as t join {$prefix}project as p on t.project_code = p.code left join {$prefix}task_member as tm on tm.task_code = t.code where  t.deleted = 0 {$doneSql} and tm.member_code = '{$memberCode}' and p.deleted = 0 order by t.id desc";
        }
        //我创建的
        if ($taskType == 3) {
            $sql = "select *,t.id as id,t.name as name,t.code as code,t.create_time as create_time,t.end_time,t.begin_time from {$prefix}task as t join {$prefix}project as p on t.project_code = p.code where  t.deleted = 0 {$doneSql} and t.create_by = '{$memberCode}' and p.deleted = 0 order by t.id desc";
        }
        $total = Db::query($sql);
        $total = count($total);
        $sql .= " limit {$offset},{$limit}";
        $list = Db::query($sql);
        return ['list' => $list, 'total' => $total];
    }


    /**
     * 导入成员
     * @param \think\File $file
     * @return bool
     * @throws Exception
     */
    public function uploadFile(\think\File $file, $projectCode, $memberCode)
    {
        try {
            $data = importExcel($file->getInfo()['tmp_name']);
        } catch (Exception $e) {
            return error('201', $e->getMessage());
        }
        $count = 0;
        if ($data) {
            foreach ($data as $key => $item) {
                if ($key > 2) {
                    $name = trim($item['A']);
                    $pTaskName = trim($item['B']);
                    $taskStageName = trim($item['C']);
                    $executorName = trim($item['D']);
                    $beginTime = trim($item['E']);
                    $endTime = trim($item['F']);
                    $description = trim($item['G']);
                    $priName = trim($item['H']);
                    $tagNameList = trim($item['I']);

                    if (!$name || !$taskStageName) {
                        continue;
                    }
                    $taskStage = TaskStages::where(['name' => $taskStageName, 'project_code' => $projectCode])->field('code')->find();
                    if (!$taskStage) {
                        continue;
                    }
                    $taskStageCode = $taskStage['code'];

                    switch ($priName) {
                        case '紧急':
                            $pri = 1;
                            break;
                        case '非常紧急':
                            $pri = 2;
                            break;
                        default:
                            $pri = 0;
                    }

                    $tagCodes = [];
                    if ($tagNameList) {
                        $tagNameList = explode(';', $tagNameList);
                        foreach ($tagNameList as $tagName) {
                            $tag = TaskTag::where(['name' => $tagName, 'project_code' => $projectCode])->field('code')->find();
                            if ($tag) {
                                $tagCodes[] = $tag['code'];
                            }
                        }
                    }

                    if ($pTaskName) {
                        if (!isset($parentCode) || !$parentCode) {
                            $pTask = self::where(['name' => $pTaskName, 'project_code' => $projectCode])->field('code')->order('id desc')->find();
                            if ($pTask) {
                                $parentCode = $pTask['code'];
                            } else {
                                $parentCode = '';
                            }
                        }
                    } else {
                        $parentCode = '';
                    }

                    $executorCode = '';
                    if ($executorName) {
                        $prefix = config('database.prefix');
                        $sql = "select m.code as code from {$prefix}project_member as pm join {$prefix}member as m on pm.member_code = m.code where m.name = '{$executorName}'";
                        $executor = Db::query($sql);
                        if ($executor) {
                            $executorCode = $executor[0]['code'];
                        }
                    }

                    $beginTime = DateService::checkDateIsValid($beginTime) ? $beginTime : '';
                    $endTime = DateService::checkDateIsValid($endTime) ? $endTime : '';
                    $task = $this->createTask($taskStageCode, $projectCode, $name, $memberCode, $executorCode, $parentCode, $pri, $description, $tagCodes, $beginTime, $endTime);
                    if ($task) {
                        $count++;
                    }
                }

            }
        }
        return $count;
    }

    /**
     * 批量放入回收站
     * @param $stageCode
     * @return Task
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function recycleBatch($stageCode)
    {
        $stage = TaskStages::where(['code' => $stageCode])->find();
        if (!$stage) {
            throw new Exception('任务列表不存在', 1);
        }
        $where = ['stage_code' => $stageCode, 'deleted' => 0];
        $taskCodes = self::where($where)->column('code');
        $memberCode = getCurrentMember()['code'];
        if ($taskCodes) {
            foreach ($taskCodes as $taskCode) {
                self::taskHook($memberCode, $taskCode, 'recycle');
            }
        }
        $result = self::update(['deleted' => 1, 'deleted_time' => nowTime()], $where);
        return $result;
    }

    /**
     * 放入回收站
     * @param $code
     * @return Project
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function recycle($code)
    {
        $info = self::where(['code' => $code])->find();
        if (!$info) {
            throw new Exception('任务不存在', 1);
        }
        if ($info['deleted']) {
            throw new Exception('任务已在回收站', 2);
        }
        $result = self::update(['deleted' => 1, 'deleted_time' => nowTime()], ['code' => $code]);
        self::taskHook(getCurrentMember()['code'], $code, 'recycle');
        return $result;
    }

    /**
     * 恢复任务
     * @param $code
     * @return Project
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function recovery($code)
    {
        $info = self::where(['code' => $code])->find();
        if (!$info) {
            throw new Exception('任务不存在', 1);
        }
        if (!$info['deleted']) {
            throw new Exception('任务已恢复', 2);
        }
        $result = self::update(['deleted' => 0], ['code' => $code]);
        self::taskHook(getCurrentMember()['code'], $code, 'recovery');
        return $result;
    }

    public function del($code)
    {
        //权限判断
        $info = self::where(['code' => $code])->find();
        if (!$info) {
            throw new Exception('任务不存在', 1);
        }
        Db::startTrans();
        try {
            self::where(['code' => $code])->delete();
            self::where(['pcode' => $code])->delete();
            TaskMember::where(['task_code' => $code])->delete();
            TaskLike::where(['task_code' => $code])->delete();
            ProjectLog::where(['source_code' => $code, 'action_type' => 'task'])->delete();
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            throw new Exception($e->getMessage());
        }
        return true;
    }


    public function getPriTextAttr($value, $data)
    {
        if (!isset($data['pri'])) {
            $data['pri'] = 0;
        }
        $status = [0 => '普通', 1 => '紧急', 2 => '非常紧急'];
        return $status[$data['pri']];
    }

    public function getStatusTextAttr($value, $data)
    {
        if (!isset($data['status'])) {
            $data['status'] = 0;
        }
        $status = [0 => '未开始', 1 => '已完成', 2 => '进行中', 3 => '挂起', 4 => '验收中'];
        return $status[$data['status']];
    }

    /**
     * 标签
     */
    public function getTagsAttr($value, $data)
    {
        $tags = [];
        if (isset($data['code'])) {
            $tags = TaskToTag::where(['task_code' => $data['code']])->field('id', true)->order('id asc')->select()->toArray();
        }
        return $tags;
    }

    /**
     * 子任务数
     */
    public function getChildCountAttr($value, $data)
    {
        $childTasks = [];
        if (isset($data['code'])) {
            $childTaskCount = self::where(['pcode' => $data['code'], 'deleted' => 0])->count('id');
            $childTasks[] = $childTaskCount;
            $childTaskCount = self::where(['pcode' => $data['code'], 'deleted' => 0, 'done' => 1])->count('id');
            $childTasks[] = $childTaskCount;
        }
        return $childTasks;
    }

    /**
     * 父任务是否完成
     */
    public function getParentDoneAttr($value, $data)
    {
        $done = 1;
        if (isset($data['code']) && isset($data['pcode']) && $data['pcode']) {
            $task = self::where(['code' => $data['pcode']])->field('done,deleted')->find();
            if ($task && !$task['deleted'] && !$task['done']) {
                $done = 0;
            }
        }
        return $done;
    }

    /**
     * 是否有子任务未完成
     */
    public function getHasUnDoneAttr($value, $data)
    {
        $hasUnDone = 0;
        if (isset($data['code'])) {
            $taskCount = self::where(['pcode' => $data['code'], 'done' => 0, 'deleted' => 0])->count('id');
            if ($taskCount) {
                $hasUnDone = 1;
            }
        }
        return $hasUnDone;
    }

    public function getHasCommentAttr($value, $data)
    {
        $comment = 0;
        if (isset($data['code'])) {
            $comment = ProjectLog::where(['source_code' => $data['code'], 'type' => 'task', 'is_comment' => 1])->count('id');
        }
        return $comment;
    }

    public function getHasSourceAttr($value, $data)
    {
        $sources = 0;
        if (isset($data['code'])) {
            $sources = SourceLink::where(['link_code' => $data['code'], 'link_type' => 'task'])->count('id');
        }
        return $sources;
    }

    /**
     * 是否有阅读权限
     * @param $value
     * @param $data
     * @return bool
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function getCanReadAttr($value, $data)
    {
        $canRead = 1;
        if (isset($data['private'])) {
            if ($data['private']) {
                $taskMember = TaskMember::where(['task_code' => $data['code'], 'member_code' => getCurrentMember()['code']])->field('id')->find();
                if (!$taskMember) {
                    $canRead = 0;
                }
            }
        }
        return $canRead;
    }

    public function getLikedAttr($value, $data)
    {
        $like = 0;
        if (isset($data['code'])) {
            $member = getCurrentMember();
            $taskLike = TaskLike::where(['task_code' => $data['code'], 'member_code' => $member['code']])->find();
            if ($taskLike) {
                $like = 1;
            }
        }
        return $like;
    }

    public function getStaredAttr($value, $data)
    {
        $stared = 0;
        if (isset($data['code'])) {
            $member = getCurrentMember();
            $taskStar = Collection::where(['source_code' => $data['code'], 'type' => 'task', 'member_code' => $member['code']])->find();
            if ($taskStar) {
                $stared = 1;
            }
        }
        return $stared;
    }

    /** 任务变动钩子
     * @param $memberCode
     * @param $taskCode
     * @param string $type
     * @param string $toMemberCode
     * @param int $isComment
     * @param string $remark
     * @param string $content
     * @param string $fileCode
     * @param array $data
     * @param string $tag
     */
    public static function taskHook($memberCode, $taskCode, $type = 'create', $toMemberCode = '', $isComment = 0, $remark = '', $content = '', $fileCode = '', $data = [], $tag = 'task')
    {
        $data = ['memberCode' => $memberCode, 'taskCode' => $taskCode, 'remark' => $remark, 'type' => $type, 'content' => $content, 'isComment' => $isComment, 'toMemberCode' => $toMemberCode, 'fileCode' => $fileCode, 'data' => $data, 'tag' => $tag];
        Hook::listen($tag, $data);

    }
}