<?php
/**
 * 问卷基本信息表
 * BaseinfoService.class.php
 * CreateBy:daijun
 * Date:2017-03-06
 */

namespace Common\Service;

use Common\Common\Msg;
use Common\Model\BaseinfoModel;
use Common\Model\ClassifyModel;
use VcySDK\Cron;
use VcySDK\Service;

class BaseinfoService extends AbstractService
{

    // 调研搜索状态:预发布
    const PRE_PUBLISH_STATUS = 1;
    // 调研搜索状态:草稿
    const DRAFT_STATUS = 2;

    // 调研搜索状态:已发布-进行中
    const PUBLISH_STATUS = 3;
    // 调研搜索状态:已发布-已结束
    const PUBLISH_OVER_STATUS = 4;

    // 前端调研状态标识:未开始
    const QU_NO_STRART = 1;
    // 前端调研状态标识:进行中
    const QU_STATUS_ING = 2;
    // 前端调研状态标识:已结束
    const QU_STATUS_OVER = 3;

    // 可重复填写
    const REPEAT_YES = 1;
    // 不可重复填写
    const REPEAT_NO = 2;

    // 允许外部人员参与
    const SHARE_YES = 1;
    // 不允许外部人员参与
    const SHARE_NO = 0;

    // 定时任务编辑
    const CRON_TYPE_EDIT = 1;

    // 实名填写
    const REAL_NAME = 1;
    // 匿名填写
    const ANONYMOUS = 0;

    // 常规类型
    const ROUTINE_TYPE = 1;
    // 任务类型
    const TASK_TYPE = 2;
    // 线下培训
    const OFF_LINE_TYPE = 3;
    // 其他类型
    const OTHER_TYPE = 4;

    // 手机端调研状态:进行中
    const FRONTEND_QU_STATUS_ING = 1;
    // 手机端调研状态:已结束
    const FRONTEND_QU_STATUS_END = 2;

    // 调研开启保密
    const SECRET_YES = 1;
    // 调研关闭保密
    const SECRET_NO = 0;

    // 全员可见
    const IS_ALL_YES = 1;
    // 非全员可见
    const IS_ALL_NO = 0;

    // 一分钟为60秒
    const MINUTE_TO_SECOND = 60;

    // 发布时发送推送消息
    const NOCTICE_YES = 1;
    // 发布时不发送推送消息
    const NOCTICE_NO = 0;

    // 积分策略不启用
    const INTEGRAL_ACTION_NO = 2;

    // 积分策略不启用
    const CREDIT_ACTION_NO = 2;

    // 开启调研结束前推送消息
    const IS_REMIND_YES = 1;
    // 关闭点烟结束钱推送消息
    const IS_REMIND_NO = 0;

    // 默认分页页码
    const DEFAULT_PAGE_NUM = 1;
    // 默认分页条数
    const DEFAULT_PAGE_LIMIT = 12;

    /** @var ClassifyModel */
    protected $_d_class;

    // 构造方法
    public function __construct()
    {

        $this->_d = new BaseinfoModel();
        // 可见范围信息表
        $this->_d_class = new ClassifyModel();

        parent::__construct();
    }

    /**
     * 执行自定义查询SQL语句(安装应用回调时用)
     *
     * @author 侯英才
     *
     * @param string $sql 执行的SQL语句
     *
     * @return mixed
     */
    public function query($sql)
    {

        return $this->_d->query($sql);
    }

    /**
     * 调研基本信息数据组装验证
     *
     * @param array $data 调研基本信息
     *
     * @return array|bool
     */
    public function checkData($data)
    {

        // 标题非空验证
        if (empty($data['title'])) {

            E('_EMPTY_BASEINFO_TITLE');
        }

        // 分类非空验证
        if (empty($data['qc_id'])) {

            E('_EMPTY_CATE_ID');
        }

        // 分类是否存在
        $classify = $this->_d_class->get(intval($data['qc_id']));
        if (empty($classify)) {

            E('_ERR_CLASSIFY_NOT_FOUND');
        }

        // 调研状态非空验证
        if (empty($data['qu_status'])) {

            E('_EMPTY_QUSTATUS_STATUS');
        }

        // 如果不是草稿,则还需验证以下内容
        if (BaseinfoService::DRAFT_STATUS != $data['qu_status']) {
            // 验证截止时间
            if (empty($data['deadline'])) {

                E('_EMPTY_BASEINFO_DEADLINE');
            }

            // 截止时间小于等于当前时间
            if ($data['deadline'] <= MILLI_TIME) {
                // 调研截止时间不能小于当前时间
                E('_ERR_DEADLINE_LT_TIME');
            }

            // 调研结束前多少分钟进行消息提醒设置时间不为空
            if (intval($data['remind'])) {
                // 提醒时间
                $remind_time = $data['deadline'] - to_milli_time(intval($data['remind']) * self::MINUTE_TO_SECOND);
                // 已发布、进行中,并且提醒时间小于当前时间
                if (BaseinfoService::PUBLISH_STATUS == $data['qu_status'] && $remind_time < MILLI_TIME) {

                    E('_ERR_REMINDTIME_LT_PUBLISHTIME');
                } elseif (BaseinfoService::PRE_PUBLISH_STATUS == $data['qu_status'] && $remind_time < $data['release']) { // 预发布并且提醒时间小于定时发布时间

                    E('_ERR_REMINDTIME_LT_PUBLISHTIME');
                }
            }

            // 验证保密设置
            if (!isset($data['secret'])) {

                E('_EMPTY_SECRET_SET');
            }

            // 验证是否允许外部人员参与设置
            if (!isset($data['share'])) {

                E('_EMPTY_SHARE_SET');
            }

            // 验证权限设置
            if (!isset($data['is_all'])) {

                E('_EMPTY_IS_ALL');
            }

            // 验证填写类型设置
            if (!isset($data['anonymous'])) {

                E('_EMPTY_WRITE_TYPE');
            }

            // 验证策略类型设置
            if (empty($data['integral_action_type'])) {

                E('_EMPTY_INTEGRAL_ACTION');
            }

            // 验证学分策略类型设置
            if (empty($data['credit_action_type'])) {
                E('_EMPTY_INTEGRAL_ACTION');
            }

            // 如果策略类型自定义策略,则策略ID不能为空
            if (self::INTEGRAL_ACTION_TYPE_MY == $data['integral_action_type'] && empty($data['integral_strategyid'])) {

                E('_EMPTY_INTEGRAL_ACTIONID');
            }

            // 是否发布时推送提醒消息
            if (!isset($data['is_notice'])) {

                E('_EMPTY_NOTICE_SET');
            }

            // 是否开启在调研结束前推送提醒消息设置不能为空
            if (!isset($data['is_remind'])) {

                E('_EMPTY_REMIND_SET');
            }

            // 在开启在调研结束前推送提醒消息时,提前时间不能小于1分钟
            if (self::IS_REMIND_YES == $data['is_remind'] && $data['remind'] <= 0) {

                E('_ERR_REMIND_TIME');
            }
        }

        // 当允许外部人员参与的时候,保密设置关闭
        if (self::SHARE_YES == $data['share']) {

            $data['secret'] = self::SECRET_NO;
        }

        $remind = 0;
        if (self::IS_REMIND_YES == $data['is_remind']) {

            $remind = rintval($data['remind']);
        }

        $base_data = [
            'title' => $data['title'], // 调研标题
            'introduce' => $data['introduce'], // 调研描述
            'qc_id' => rintval($data['qc_id']), // 调研分类
            'qu_type' => rintval($data['qu_type']), // 调研类型
            'deadline' => $data['deadline'] ? $data['deadline'] : 0, // 截止时间
            'secret' => $data['secret'] ? self::SECRET_YES : self::SECRET_NO, // 内容保密(0:关闭;1:开启)
            'share' => $data['share'] ? self::SHARE_YES : self::SHARE_NO, // 是否可允许外部人员参与(0:不允许;1:允许)
            'is_all' => $data['is_all'] ? self::IS_ALL_YES : self::IS_ALL_NO, // 是否全部人员可见(0:否,1:是)
            'anonymous' => $data['anonymous'] ? self::REAL_NAME : self::ANONYMOUS, // 匿名(0:匿名;1:实名)
            'remind' => $remind, // 调研结束前多少分钟进行消息提醒,单位:分钟
            'release' => $data['release'] ? $data['release'] : 0, // 定时发布时间
            'release_status' => rintval($data['qu_status']), // 调研状态(1:预发布-定时发布,2:草稿,3:发布)
            'integral_action_type' => rintval($data['integral_action_type']), // 积分策略(1:启用默认,2:不启用,3:启用自定义策略)
            'credit_action_type' => rintval($data['credit_action_type']), // 学分策略(1:启用默认,2:不启用,3:启用自定义策略)
            'integral_strategyid' => $data['integral_strategyid'] ? $data['integral_strategyid'] : '', // 积分策略id
            'is_notice' => $data['is_notice'] ? self::NOCTICE_YES : self::NOCTICE_NO // 调研发布时是否进行提醒(0:否,1:是)
        ];

        // 发布
        if (self::PUBLISH_STATUS == $base_data['release_status']) {

            $base_data['release_time'] = MILLI_TIME; // 发布时间为当前时间
            $base_data['updated'] = MILLI_TIME; // 最后修改时间为当前时间
        }

        return $base_data;
    }

    /**
     * 调研基本信息数据组装验证
     *
     * @param array $data 调研基本信息
     *
     * @return array|bool
     */
    public function check_BaseInfoData($data)
    {
        // 标题非空验证
        if (empty($data['title'])) {

            E('_EMPTY_BASEINFO_TITLE');
        }

        // 分类非空验证
        if (empty($data['qc_id'])) {

            E('_EMPTY_CATE_ID');
        }

        // 分类是否存在
        $classify = $this->_d_class->get(intval($data['qc_id']));
        if (empty($classify)) {

            E('_ERR_CLASSIFY_NOT_FOUND');
        }

        // 调研状态非空验证
        if (empty($data['qu_status'])) {

            E('_EMPTY_QUSTATUS_STATUS');
        }

        // 如果不是草稿,则还需验证以下内容
        if (BaseinfoService::DRAFT_STATUS != $data['qu_status']) {
            // 验证保密设置
            if (!isset($data['secret'])) {

                E('_EMPTY_SECRET_SET');
            }

            // 验证填写类型设置
            if (!isset($data['anonymous'])) {

                E('_EMPTY_WRITE_TYPE');
            }
        }

        $base_data = [
            'title' => $data['title'], // 调研标题
            'introduce' => $data['introduce'], // 调研描述
            'qc_id' => rintval($data['qc_id']), // 调研分类
            'qu_type' => rintval($data['qu_type']), // 调研类型
            'deadline' => 0, // 截止时间
            'secret' => $data['secret'] ? self::SECRET_YES : self::SECRET_NO, // 内容保密(0:关闭;1:开启)
            'share' => $data['share'] ? self::SHARE_YES : self::SHARE_NO, // 是否可允许外部人员参与(0:不允许;1:允许)
            'is_all' => self::IS_ALL_YES, // 全部人员可见
            'anonymous' => $data['anonymous'] ? self::REAL_NAME : self::ANONYMOUS, // 匿名(0:匿名;1:实名)
            'remind' => 0, // 调研结束前多少分钟进行消息提醒,单位:分钟
            'release' => 0, // 定时发布时间
            'release_status' => rintval($data['qu_status']), // 调研状态(1:预发布-定时发布,2:草稿,3:发布)
            'integral_action_type' => self::INTEGRAL_ACTION_NO, // 积分策略不启用
            'credit_action_type' => self::CREDIT_ACTION_NO, // 学分策略不启用
            'integral_strategyid' => '', // 积分策略id
            'is_notice' => $data['is_notice'] ? self::NOCTICE_YES : self::NOCTICE_NO // 调研发布时是否进行提醒(0:否,1:是)
        ];

        // 学习地图 积分、学分可以开启
        if ($base_data['qu_type'] == BaseinfoService::OTHER_TYPE) {
            $base_data['integral_action_type'] = $data['integral_action_type'];
            $base_data['credit_action_type'] = $data['credit_action_type'];
        }

        return $base_data;
    }

    /**
     * 获取调研列表
     *
     * @param array $data 搜索条件
     *
     * @return array
     */
    public function list_by_params($data)
    {

        // 搜索标题
        $title = trim($data['title']);

        // 调研分类
        $qc_id = rintval($data['qc_id']);

        // 截止时间(左边界)
        $deadline_time_begin = $data['deadline_time_start'];
        // 截止时间(右边界)
        $deadline_time_end = $data['deadline_time_end'];

        // 调研状态(1:预发布,2:草稿,3:进行中,4:已结束)
        $qu_status = rintval($data['qu_status']);

        // 最后更新时间(左边界)
        $updated_time_begin = $data['updated_time_start'];
        // 最后更新时间(右边界)
        $updated_time_end = $data['updated_time_end'];

        // 页码
        $pageNum = is_numeric($data['page']) ? $data['page'] : self::DEFAULT_PAGE_NUM;
        // 每页条数
        $pageSize = is_numeric($data['limit']) ? $data['limit'] : self::DEFAULT_PAGE_LIMIT;
        // 设置分页
        list($start, $limit, $pageNum) = page_limit($pageNum, $pageSize);

        // 搜素条件数组
        $condition = [];

        // 非草稿、非常规调研
        if (!empty($data['release_status']) && $data['release_status'] != self::DRAFT_STATUS
            && $data['qu_type'] != self::ROUTINE_TYPE
        ) {

            return [0, $limit, $pageNum, []];
        }

        // 标题不为空
        if (isset($title)) {
            // 查询%需要转义
            $title = str_replace('%', '\%', $title);
            $condition['title LIKE ?'] = '%' . $title . '%';
        }

        // 如果调研ID为空则不搜索
        if (!empty($qc_id)) {

            $condition['qc_id'] = $qc_id;
        }

        // 如果查询调研类型为空不搜索
        if (!empty($data['qu_type'])) {

            $condition['qu_type'] = $data['qu_type'];
        }

        // 调研状态不为空(1.预发布;2.草稿;3.进行中,4.已结束)
        if (!empty($qu_status)) {
            // 预发布、草稿
            if (self::PRE_PUBLISH_STATUS == $qu_status || self::DRAFT_STATUS == $qu_status) {

                $condition['release_status'] = $qu_status;
            } else {
                // 发布
                $condition['release_status'] = self::PUBLISH_STATUS;

                // 已发布-进行中
                if (self::PUBLISH_STATUS == $qu_status) {
                    // 截止时间大于当前时间
                    $condition['deadline > ? '] = MILLI_TIME;
                } elseif (self::PUBLISH_OVER_STATUS == $qu_status) { // 已发布-已结束
                    // 截止时间小于当前时间
                    $condition['deadline < ? '] = MILLI_TIME;
                    $condition['deadline != ? '] = 0;
                }
            }
        }

        // 截止时间区间不为空
        if (!empty($deadline_time_begin) && !empty($deadline_time_end)) {

            $condition['deadline >= ? '] = $deadline_time_begin;
            $condition['deadline <= ? '] = $deadline_time_end;
        }

        // 最后更新时间区间不为空
        if (!empty($updated_time_begin) && !empty($updated_time_end)) {

            $condition['updated >= ? '] = $updated_time_begin;
            $condition['updated <= ? '] = $updated_time_end;
        }

        // 获取总数
        $total = $this->_d->count_by_conds($condition);

        $list = [];
        if ($total) {
            // 分页参数
            $page_option = [$start, $limit];
            // 排序
            $order_by['qu_id'] = 'DESC';
            // 获取列表
            $list = $this->_d->list_by_conds($condition, $page_option, $order_by);
        }

        // 返回数据
        return [$total, $limit, $pageNum, $list];
    }

    /**
     * 获取有权限的调研总数
     *
     * @param int $q_type 调研状态 1进行中,2已结束
     * @param array $ids 有权限的调研ID集合
     *
     * @return mixed
     */
    public function count_by_where($q_type, $ids)
    {

        return $this->_d->count_by_where($q_type, $ids);
    }

    /**
     * 执行sql 语句
     *
     * @param $sql
     *
     * @return mixed
     */
    public function execute($sql)
    {

        return $this->_d->execute($sql);
    }

    /**
     * 获取有权限的调研列表
     *
     * @param int $q_type 调研状态 1进行中,2已结束
     * @param array $ids 有权限的调研ID集合
     * @param array $page_option 分页数组
     * @param array $order_by 排序条件
     *
     * @return mixed
     */
    public function list_by_where($q_type, $ids, $page_option, $order_by)
    {

        return $this->_d->list_by_where($q_type, $ids, $page_option, $order_by);
    }

    /**
     * 格式化返回数据
     *
     * @param array $data 调研基本信息
     *
     * @return mixed
     */
    public function _format_data(&$data)
    {

        $data['qu_id'] = intval($data['qu_id']);
        $data['qc_id'] = intval($data['qc_id']);
        $data['secret'] = intval($data['secret']);
        $data['share'] = intval($data['share']);
        $data['is_all'] = intval($data['is_all']);
        $data['anonymous'] = intval($data['anonymous']);
        $data['remind'] = intval($data['remind']);
        $data['involved_num'] = intval($data['involved_num']);
        $data['involved_total'] = intval($data['involved_total']);
        $data['release_status'] = intval($data['release_status']);
        $data['is_notice'] = intval($data['is_notice']);

        unset($data['deleted'], $data['updated'], $data['status'], $data['domain']);

        return $data;
    }

    /**
     * 新增/编辑调研定时任务添加
     *
     * @param $param array
     *          qu_id => 调研id
     *          type=> 模式 0:添加 1:修改
     *
     * @return bool
     */
    public function cron_add($param)
    {

        // 实例化定时任务类
        $cron_serv = new Cron(Service::instance());

        // 获取调研基本信息
        $data = $this->get($param['qu_id']);

        // 如果是修改就删除以前的定时任务
        if (self::CRON_TYPE_EDIT == $param['type']) {
            // 存在定时发布
            if (!empty($data['release_crid'])) {

                $cron_serv->delete($data['release_crid']);
            }
            // 存在定时提醒
            if (!empty($data['remind_crid'])) {

                $cron_serv->delete($data['remind_crid']);
            }
        }

        // 需要定时通知的调研id
        $res_params = [
            'qu_id' => $param['qu_id'],
        ];
        // json参数
        $json_params = json_encode($res_params);

        // 初始化定时任务入库id
        $cron_remind = '';
        $cron_publish = '';

        // 如果调研状态为发布
        if ($data['release_status'] == self::PUBLISH_STATUS) {

            // 如果调研结束前多少分钟进行消息提醒设置不为空
            if (!empty($data['remind'])) {

                // 获取截止提醒时间
                $remind_time = $data['deadline'] - $data['remind'] * 60 * 1000;

                // 调研结束提醒定时
                $conds_remind = [
                    'crRemark' => 'questionnaire_deadline',
                    'crType' => 2,
                    'crParams' => $json_params,
                    'crMethod' => 'POST',
                    'crReqUrl' => oaUrl('Frontend/Callback/Remind/Index'), // 回调地址
                    'crTimes' => 1,
                    'crCron' => rgmdate((String)$remind_time, 's i G j n ? Y'),
                    'crMonitorExecution' => 0,
                    'crDescription' => '调研定时提醒'
                ];

                // 创建定时任务
                $res_remind = $cron_serv->add($conds_remind); // crId
                $cron_remind = $res_remind['crId'];
            }
        } else {

            if (self::PRE_PUBLISH_STATUS == $data['release_status']) {
                // 如果调研状态为预发布(定时发布)
                if (!empty($data['release'])) {

                    if (!empty($data['remind'])) {
                        // 获取截止提醒时间
                        $remind_time = $data['deadline'] - to_milli_time($data['remind'] * 60);
                        // 问卷结束提醒定时
                        $conds_remind = [
                            'crRemark' => 'questionnaire_remind',
                            'crType' => 2,
                            'crParams' => $json_params,
                            'crMethod' => 'POST',
                            'crReqUrl' => oaUrl('Frontend/Callback/Remind/Index'), // 回调地址
                            'crTimes' => 1,
                            'crCron' => rgmdate((String)$remind_time, 's i G j n ? Y'),
                            'crMonitorExecution' => 0,
                            'crDescription' => '调研定时提醒'
                        ];

                        // 创建定时任务
                        $res_remind = $cron_serv->add($conds_remind); // crId
                        $cron_remind = $res_remind['crId'];
                    }

                    // 获取定时发布时间
                    $publish_time = $data['release'];

                    // 调研定时发布
                    $conds_publish = [
                        'crRemark' => 'questionnaire_publish',
                        'crType' => 2,
                        'crParams' => $json_params,
                        'crMethod' => 'POST',
                        'crReqUrl' => oaUrl('Frontend/Callback/Release/Index'), // 回调地址
                        'crTimes' => 1,
                        'crCron' => rgmdate((String)$publish_time, 's i G j n ? Y'),
                        'crMonitorExecution' => 0,
                        'crDescription' => '调研定时发布',
                    ];

                    // 创建定时任务
                    $res_publish = $cron_serv->add($conds_publish); // crId
                    $cron_publish = $res_publish['crId'];
                }
            }
        }

        $update_data = [
            'remind_crid' => $cron_remind,
            'release_crid' => $cron_publish
        ];

        $this->update($param['qu_id'], $update_data);

        return true;
    }

    /**
     * 发布调研推送提醒
     *
     * @param array $data
     *
     * @return bool
     */
    public function sendmsg_release($data = [])
    {

        $application_name = cfg('APPLICATION_NAME');

        $right_s = new RightService();
        // 获取应参与人员列表
        $user_ids = $right_s->list_user($data['qu_id'], $data['is_all']);

        // 消息接收人id(参与人员id)
        $toUser = implode('|', $user_ids);
        // 组装消息推送参数
        $articles = [
            [
                'title' => '【培训调研】' . $data['title'],
                'description' => '您有一个' . $application_name . '需要填写,请于'
                    . rgmdate(strval($data['deadline']), 'Y-m-d H:i') . '前填写完毕',
                'url' => oaUrl('Frontend/Index/QuestionnaireView/Index', ['qu_id' => $data['qu_id']]),
                'picUrl' => ''
            ]
        ];

        // 实例化消息类
        $msg = new Msg();
        // 推送消息给参与人员
        $msg->sendNews($toUser, '', '', $articles, $safe = 0);

        return true;
    }

    /**
     * 查询分类id及对应的调研总数
     *
     * @return mixed
     */
    public function classify_baseinfo_count()
    {

        return $this->_d->classify_baseinfo_count();
    }
}