<?php
/**
 * 培训计划表Service
 * Created by PhpStorm.
 */
namespace Common\Service;

use Common\Common\Constant;
use Common\Common\Teacher;
use Common\Common\AttachOperation;
use Common\Model\PlanModel;

class PlanService extends AbstractService
{

    //  计划名称最大长度
    const PLAN_NAME_MAX_LENGTH = 62;

    // 培训计划启用状态:失效
    const PLAN_STATUS_CLOSE = 0;
    // 培训计划启用状态:启用
    const PLAN_STATUS_OPEN = 1;

    // 培训计划操作状态:锁定
    const PLAN_OPERATE_LOCK = 0;
    // 培训计划操作状态:开启
    const PLAN_OPERATE_OPEN = 1;
    // 培训计划操作状态:已完成(已签到,素材、照片墙已查看,完成考试,完成问卷)
    const PLAN_OPERATE_DONE = 2;

    // 培训计划类型:签到
    const PLAN_TYPE_SIGN = 1;
    // 培训计划类型:素材
    const PLAN_TYPE_SOURCE = 2;
    // 培训计划类型:问卷
    const PLAN_TYPE_QUESTION = 3;
    // 培训计划类型:考试
    const PLAN_TYPE_EXAM = 4;
    // 培训计划类型:照片墙
    const PLAN_TYPE_PHOTO = 5;
    // 培训计划类型:线下课程
    const PLAN_TYPE_UNDER_LINE_COURSE = 6;

    // 允许员工上传照片
    const ALLOW_UPLOAD = 1;
    // 不允许员工上传照片
    const NOT_ALLOW_UPLOAD = 0;
    // 每个类型计划个数最大值
    const PLAN_MAX_COUNT = 10;
    /** @var PlanModel */
    protected $_d;
    /** @var PlanPicService */
    protected $plan_pic_service;
    /** @var CourseArticleService */
    protected $course_article_service;

    // 计划类型对应的类型名称
    protected $plan_type_names = [
        self::PLAN_TYPE_SIGN => '签到',
        self::PLAN_TYPE_SOURCE => '素材',
        self::PLAN_TYPE_QUESTION => '问卷',
        self::PLAN_TYPE_EXAM => '考试',
        self::PLAN_TYPE_PHOTO => '照片墙',
        self::PLAN_TYPE_UNDER_LINE_COURSE => '线下课程',
    ];

    public function __construct()
    {
        parent::__construct();

        // 实例化培训计划model
        $this->_d = new PlanModel();
        $this->plan_pic_service = new PlanPicService();
        $this->course_article_service = new CourseArticleService();
    }

    /**
     * 验证培训计划列表数据
     *
     * @author houyingcai
     * @param array $list 培训计划列表
     * @int int $ed_status 培训状态(1=草稿;2=发布;3=已终止)
     * @int int $old_ed_status 原培训状态(1=草稿;2=已发布;3=已终止)
     *
     * @return bool
     */
    public function validate_plan_data($list = [], $ed_status = Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED, $old_ed_status = Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED)
    {
        $plan_max_error = [];

        foreach ($list as $key => $val) {
            if (isset($plan_max_error[$val['plan_type']])) {
                // 如果没有定义 默认值已
                $plan_max_error[$val['plan_type']] = 1;
            } else {
                // 如果存在定义 加一下
                $plan_max_error[$val['plan_type']] = $plan_max_error[$val['plan_type']] + 1;
            }
            // 判断每个计划不能超过10个
            foreach ($plan_max_error as $k => $value) {
                if ($value > self::PLAN_MAX_COUNT) {
                    E('【' . $this->plan_type_names[$k] . '不能超过10个');
                }
            }

            // 计划名称不能有空
            if (empty($val['plan_name'])) {

                E('_EMPTY_PLAN_NAME');
            }

            // 计划对应ID不能为空(除签到、线下课程之外)
            if ($val['plan_type'] != self::PLAN_TYPE_SIGN && $val['plan_type'] != self::PLAN_TYPE_UNDER_LINE_COURSE && !intval($val['plan_obj_id'])) {

                E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':计划对应ID不能为空', 2169100);
            }

            // 计划类型参数无效(类型必须在 1-6 之间)
            if (intval($val['plan_type']) < self::PLAN_TYPE_SIGN || intval($val['plan_type']) > self::PLAN_TYPE_UNDER_LINE_COURSE) {

                E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':类型参数无效', 2169101);
            }

            // 计划启用状态参数无效
            if ($val['plan_use_status'] != self::PLAN_OPERATE_LOCK && $val['plan_use_status'] != self::PLAN_OPERATE_OPEN) {

                E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':启用状态参数无效', 2169103);
            }

            // 计划启用状态时启用时间大于0
            if ($val['plan_use_status'] == self::PLAN_STATUS_OPEN && !$val['plan_use_time']) {

                E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':启用时间不能为空', 2169104);
            }

            // 培训计划类型为:签到类型
            if (self::PLAN_TYPE_SIGN == $val['plan_type']) {
                // 组装签到时间段数组,用于验证时间段是否有重叠
                $sign_list[$key]['plan_sign_begin'] = $val['plan_sign_begin'];
                $sign_list[$key]['plan_sign_end'] = $val['plan_sign_end'];

                // 签到是否是新增
                if (!$val['plan_id']) {

                    // 签到开始时间不能为空
                    if (empty($val['plan_sign_begin'])) {

                        E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':签到开始时间不能为空', 2169105);
                    }
                    // 签到结束时间不能为空
                    if (empty($val['plan_sign_end'])) {

                        E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':签到结束时间不能为空', 2169106);
                    }

                    // 签到结束时间不能小于开始时间
                    if ($val['plan_sign_end'] < $val['plan_sign_begin']) {

                        E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':签到结束时间不能小于当前时间', 2169108);
                    }
                }

                // 验证签到时间段是否有重叠
                if (!empty($sign_list) && count($sign_list) > 1) {

                    foreach ($sign_list as $k => $v) {
                        // 签到时间段有重叠
                        if (!empty($val['plan_sign_begin']) && (($val['plan_sign_begin'] >= $v['plan_sign_begin'] && $val['plan_sign_begin'] <= $v['plan_sign_end']) || ($val['plan_sign_end'] >= $v['plan_sign_begin'] && $val['plan_sign_end'] <= $v['plan_sign_end'])) && $k != $key
                        ) {

                            E('_ERR_PLAN_SIGN_TIME_REPEAT');
                        }
                    }
                }
            }

            // 培训计划类型为:照片墙类型
            if (self::PLAN_TYPE_PHOTO == $val['plan_type'] && !in_array(intval($val['plan_allow_upload']), [self::NOT_ALLOW_UPLOAD, self::ALLOW_UPLOAD], true)) {

                E('【' . $this->plan_type_names[$val['plan_type']] . '】:' . $val['plan_name'] . ':是否允许员工上传参数无效', 2169111);
            }

            // 培训计划类型为:线下课程
            if (self::PLAN_TYPE_UNDER_LINE_COURSE == $val['plan_type']) {
                $this->course_article_service->check_data($val['course'], $ed_status, $old_ed_status);
            }
        }

        return true;
    }

    /**
     * 批量删除培训安排
     * @author liyifei
     * @param array $plan_ids 待删除的培训安排id
     * @int int $ed_status 培训状态(1=草稿;2=发布;3=已终止)
     * @return bool
     */
    public function delete_plan($plan_ids, $ed_status = Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED)
    {
        // 删除线下课程类型的培训计划时,需通知讲师中心、删除课程的计划任务
        $conds = [
            'plan_id' => $plan_ids,
            'plan_type' => Constant::PLAN_TYPE_UNDER_LINE_COURSE,
        ];
        $article_plan_list = $this->list_by_conds($conds, [], [], 'plan_obj_id');

        if (!empty($article_plan_list)) {

            $articleServ = new CourseArticleService();
            $signServ = new SignService();
            $cronServ = new CronService();
            $teacherServ = &Teacher::instance();

            $article_ids = array_column($article_plan_list, 'plan_obj_id');
            $article_list = $articleServ->list_by_pks($article_ids);

            // 删除线下课程数据
            $articleServ->delete($article_ids);

            // 删除线下课程签到数据
            $signServ->delete_by_conds(['article_id' => $article_ids]);

            foreach ($article_list as $article) {

                if ($ed_status == Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED) {
                    // 将讲师ID设置为0
                    $article['teacher_id'] = 0;
                    $teacherServ->saveOfflineCourse($article);

                    // 删除课程的计划任务
                    $cronServ->delCron('', $article['article_id']);
                }
            }
        }

        // 删除照片墙类型的培训计划时,需删除UC附件服务器文件
        $conds['plan_type'] = Constant::PLAN_TYPE_PHOTO;
        $del_photos = $this->list_by_conds($conds, [], [], 'plan_id');

        if (!empty($del_photos)) {
            $attachServ = new AttachOperation();

            $del_photo_plan_ids = array_column($del_photos, 'plan_id');

            $attachServ->delete_attach(APP_DIR, 'plan', $del_photo_plan_ids);
        }

        $this->delete($plan_ids);
    }

    /**
     * 保存培训安排
     *
     * @author houyingcai
     * @param int $ed_id 培训ID
     * @param int $stage_id 培训阶段ID
     * @param array $data 培训安排数据
     * @int int $ed_status 培训状态(1=草稿;2=发布;3=已终止)
     *
     * @return bool
     */
    public function save_plan($ed_id = 0, $stage_id = 0, $data = [], $ed_status = Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED)
    {
        $courseServ = new CourseArticleService();

        // 组装数据
        $insert_data = [];
        foreach ($data as $k => &$v) {
            unset($v['plan_id']);
            $v['ed_id'] = $ed_id;
            $v['stage_id'] = $stage_id;
            $v['plan_obj_id'] = $v['plan_obj_id'] ? (int)$v['plan_obj_id'] : 0;
            $v['plan_order'] = $k + 1;
            $v['plan_name'] = raddslashes($v['plan_name']);
            $v['plan_sign_begin'] = !empty($v['plan_sign_begin']) ? $v['plan_sign_begin'] : '';
            $v['plan_sign_end'] = !empty($v['plan_sign_end']) ? $v['plan_sign_end'] : '';
            $v['plan_sign_comments'] = !empty($v['plan_sign_comments']) ? raddslashes($v['plan_sign_comments']) : '';

            // 对数组进行排序,防止insert_all时出错
            ksort($v);

            switch ($v['plan_type']) {
                // 照片墙(数据已提前写入plan表,此处仅需修改即可)
                case self::PLAN_TYPE_PHOTO:
                    $plan_id = $v['plan_obj_id'];
                    $v['plan_obj_id'] = 0;

                    $row = $this->update($plan_id, $v);

                    if (!$row) {

                        E('【照片墙】:' . $v['plan_name'] . ' 添加失败', '2169112');
                    }
                    // 更新照片表的培训ID
                    $this->plan_pic_service->update_by_conds(['plan_id' => $plan_id], ['ed_id' => $ed_id]);
                    break;

                // 线下课程
                case self::PLAN_TYPE_UNDER_LINE_COURSE:
                    // 保存线下课程
                    $v['plan_obj_id'] = $courseServ->save_course($v['course'], $ed_status, $v['plan_use_status']);

                    // 保存培训安排
                    unset($v['course']);
                    $insert_data[] = $v;
                    break;

                default:
                    $insert_data[] = $v;
                    break;
            }
        }

        // 批量插入新增数据
        if (!empty($insert_data)) {
            $row_plans = $this->insert_all($insert_data);
            if (!$row_plans) {
                E('培训计划添加失败', '2169114');
            }
        }

        // 为所有线下课程绑定ed_id和plan_id
        $plan_list = $this->list_by_conds(['ed_id' => $ed_id, 'plan_type' => Constant::PLAN_TYPE_UNDER_LINE_COURSE]);
        if (!empty($plan_list)) {
            foreach ($plan_list as $plan) {
                $update_data = [
                    'ed_id' => $plan['ed_id'],
                    'plan_id' => $plan['plan_id'],
                ];
                $this->course_article_service->update($plan['plan_obj_id'], $update_data);
            }
        }

        return true;
    }

    /**
     * 编辑计划数据
     *
     * @author houyingcai
     * @param int $ed_id 培训ID
     * @param int $stage_id 培训阶段ID
     * @param array $plans 计划数据数组
     * @param array $plan_del_ids 需删除的培训安排id
     * @int int $ed_status 培训状态(1=草稿;2=发布;3=已终止)
     *
     * @return bool
     */
    public function edit_plan($ed_id = 0, $stage_id = 0, $plans = [], $plan_del_ids = [], $ed_status = Constant::EDUCATION_PUBLISH_STATUS_PUBLISHED)
    {
        $courseServ = new CourseArticleService();

        $insert_data = [];
        $plan_order = 0;
        foreach ($plans as &$v) {
            // 要删除的培训安排,不再更新
            if (in_array($v['plan_id'], $plan_del_ids)) {
                continue;
            }

            $plan_order++;

            // 更新需要更新的数据
            if (isset($v['plan_id']) && $v['plan_id'] > 0) {
                $update['ed_id'] = $ed_id;
                $update['stage_id'] = $stage_id;
                $update['plan_order'] = $plan_order;
                $update['plan_name'] = raddslashes($v['plan_name']);
                $update['plan_use_status'] = intval($v['plan_use_status']);
                $update['plan_use_time'] = $v['plan_use_time'];

                switch ($v['plan_type']) {
                    // 签到
                    case self::PLAN_TYPE_SIGN:
                        $update['plan_sign_begin'] = $v['plan_sign_begin'];
                        $update['plan_sign_end'] = $v['plan_sign_end'];
                        $update['plan_sign_comments'] = $v['plan_sign_comments'];
                        break;

                    // 照片墙
                    case self::PLAN_TYPE_PHOTO:
                        $update['plan_allow_upload'] = intval($v['plan_allow_upload']);
                        // 更新照片表的培训ID
                        $this->plan_pic_service->update_by_conds(['plan_id' => $v['plan_id']], ['ed_id' => $ed_id]);
                        break;

                    // 线下课程
                    case self::PLAN_TYPE_UNDER_LINE_COURSE:
                        if (isset($v['course']) && !empty($v['course'])) {
                            // 修改线下课程详情
                            $courseServ->save_course($v['course'], $ed_status, $v['plan_use_status']);
                        }
                        break;
                }

                $row = $this->_d->update($v['plan_id'], $update);
                if (!$row) {
                    E($v['plan_name'] . ' 更新失败', '2169112');
                }

            } else {
                $v['ed_id'] = $ed_id;
                $v['stage_id'] = $stage_id;
                $v['plan_order'] = $plan_order;
                $v['plan_name'] = raddslashes($v['plan_name']);
                $v['plan_obj_id'] = $v['plan_obj_id'] ? intval($v['plan_obj_id']) : 0;
                $v['plan_sign_begin'] = !empty($v['plan_sign_begin']) ? $v['plan_sign_begin'] : '';
                $v['plan_sign_end'] = !empty($v['plan_sign_end']) ? $v['plan_sign_end'] : '';
                $v['plan_sign_comments'] = !empty($v['plan_sign_comments']) ? raddslashes($v['plan_sign_comments']) : '';

                // 新增线下课程类型
                if ($v['plan_type'] == Constant::PLAN_TYPE_UNDER_LINE_COURSE) {
                    // 保存线下课程
                    $v['plan_obj_id'] = $courseServ->save_course($v['course'], $ed_status, $v['plan_use_status']);
                    unset($v['course']);
                }

                // 保存培训安排
                ksort($v);
                $insert_data[] = $v;
            }
        }

        // 批量插入新增数据
        if (!empty($insert_data)) {

            $row_plans = $this->insert_all($insert_data);

            if (!$row_plans) {

                E('培训计划添加失败', '2169114');
            }
        }

        // 为所有线下课程绑定ed_id和plan_id
        $plan_list = $this->list_by_conds(['ed_id' => $ed_id, 'plan_type' => Constant::PLAN_TYPE_UNDER_LINE_COURSE]);
        if (!empty($plan_list)) {
            foreach ($plan_list as $plan) {
                $update_data = [
                    'ed_id' => $plan['ed_id'],
                    'plan_id' => $plan['plan_id'],
                ];
                $this->course_article_service->update($plan['plan_obj_id'], $update_data);
            }
        }

        return true;
    }

    /**
     * 添加照片墙
     *
     * @author 蔡建华
     * @param $params array 表单数据
     *
     * @return mixed
     */
    public function add_pic_plan($params = [])
    {
        if (empty($params['plan_name'])) {
            // 照片墙名称不能把为空
            E('_EMPTY_PLAN_PIC_NAME');
        }

        if (strlen($params['plan_name']) > self::PLAN_NAME_MAX_LENGTH) {
            // 照片墙名称长度超过最大值
            E('_EMPTY_PLAN_PIC_NAME_MORE');
        }

        try {
            // 开始事务
            $this->start_trans();

            $data = [
                'plan_name' => $params['plan_name'],
                'plan_type' => self::PLAN_TYPE_PHOTO,
                'plan_allow_upload' => intval($params['plan_allow_upload']),
                'plan_use_status' => self::PLAN_STATUS_OPEN
            ];
            // 添加照片墙数据
            $plan_id = $this->_d->insert($data);

            $pics = [];
            if ($plan_id) {
                // 照片墙添加成功 后台添加照片
                $upload = $params['upload'];

                foreach ($upload as $val) {
                    if (!empty($val['pic_at_id'])) {
                        $value = $val;
                        $value['plan_id'] = $plan_id;
                        $value['pic_uid'] = '';
                        $value['pic_type'] = PlanPicService::PIC_UPLOAD_TYPE_ADMIN;
                        $pics[] = $value;
                    }
                }
            }

            if (!empty($pics)) {
                // 照片数据入库
                $this->plan_pic_service->insert_all($pics);
            }

            // 提交事务
            $this->commit();
        } catch (\Exception $e) {
            \Think\Log::record($e);
            $this->_set_error($e->getMessage(), $e->getCode());
            // 事务回滚
            $this->rollback();
            return false;
        }

        // 附件操作
        if (!empty($upload)) {

            $attach_serv = new AttachOperation();
            $attach_ids = array_column($upload, 'pic_at_id');
            $attach_serv->insert_attach(
                APP_DIR,
                'plan',
                $plan_id,
                ['attach_ids' => $attach_ids]
            );
        }

        return $plan_id;
    }

    /**
     * 编辑照片墙
     *
     * @author 蔡建华
     * @param $params array 表单数据
     *
     * @return bool
     */
    public function edit_pic_plan($params = [])
    {
        if (empty($params['plan_id'])) {

            E('_EMPTY_PLAN_PIC_ID');
        }

        if (empty($params['plan_name'])) {

            E('_EMPTY_PLAN_PIC_NAME');
        }

        if (strlen($params['plan_name']) > self::PLAN_NAME_MAX_LENGTH) {
            // 照片墙名称长度超过最大值
            E('_EMPTY_PLAN_PIC_NAME_MORE');
        }

        $data = [
            'plan_name' => $params['plan_name'],
            'plan_allow_upload' => intval($params['plan_allow_upload']),
            'plan_use_status' => self::PLAN_STATUS_OPEN
        ];

        $conds = [
            'plan_id' => $params['plan_id'],
            'plan_type' => self::PLAN_TYPE_PHOTO
        ];

        $this->_d->update_by_conds($conds, $data);

        return true;
    }

    /**
     * 获取被使用的应用id集合
     *
     * @param int $plan_type 应用类型
     *
     * @return array 被使用的id集合
     */
    public function get_obj_ids($plan_type = 0)
    {

        return $this->_d->get_obj_ids($plan_type);
    }
}