<?php
/**
 * 考勤签到表Service
 *
 * @author: houyingcai
 * @email:     594609175@qq.com
 * @date :  2017-08-29 16:35:26
 *
 */

namespace Common\Service;

use Common\Common\ExportDownload;
use Common\Model\EducationModel;
use Common\Model\PlanModel;
use Common\Model\RightUsersModel;
use Common\Model\SignModel;
use Com\PythonExcel;

class SignService extends AbstractService
{
    // 未默认状态
    const SIGN_DEFAULT = 3;
    // 已签到
    const SIGN_DO = 1;
    // 缺勤
    const SIGN_NOT_DO = 2;
    // 审核通过
    const  CHECK_PASS = 1;
    /** @var PlanModel */
    protected $plan_d;
    /** @var EducationModel */
    protected $education_d;
    /** @var RightUsersModel */
    protected $right_user_d;

    public function __construct()
    {
        $this->_d = new SignModel();
        $this->plan_d = new PlanModel();
        $this->education_d = new EducationModel();
        $this->right_user_d = new RightUsersModel();
        parent::__construct();
    }

    /**
     * 考勤列表接口
     *
     * @author 蔡建华
     * @param array $params 搜索参数
     * @param array $page_option 分页参数
     *
     * @return array
     */
    public function sign_search_list($params = [], $page_option = null)
    {
        // 默认值
        $page = !empty($params['page']) ? intval($params['page']) : self::PAGE_DEFAULT;
        $limit = !empty($params['limit']) ? intval($params['limit']) : self::PAGE_LIMIT_DEFAULT;
        if (empty($params['plan_id'])) {

            E('_EMPTY_PLAN_ID');
        }

        $plan = $this->plan_d->get($params['plan_id']);
        $education = $this->education_d->get($plan['ed_id']);
        // 判断计划信息是否存在
        if (empty($plan)) {

            E('_EMPTY_PLAN_LIST');
        }

        $uids = [];
        // 部门,角色,岗位,用户名查询
        if (!empty($params['dpIDs']) || !empty($params['jobID']) || !empty($params['roleID']) || !empty($params['memUsername'])) {
            // 根据搜索条件获取用户ID集合(此处为各条件获取的用户uid的交集)
            $uids = $this->list_uids_by_dp_job_role($params['dpIDs'], $params['roleID'], $params['jobID'],
                $params['memUsername']);
            if (empty($uids)) {
                return [
                    'total' => 0,
                    'limit' => intval($limit),
                    'page' => intval($page),
                    'list' => [],
                ];
            }
        }

        $sign_list = [];
        // 根据签到状态搜索签到人员
        $sign_status = intval($params['sign_status']);
        // 搜索已签到和缺勤
        if (self::SIGN_DO == $sign_status) {
            // 已签到
            // 按照签到时间进行倒序排列
            $order_option = ['sign_on_time' => 'DESC'];

            $conds = [
                'plan_id' => $params['plan_id'],
                'article_id' => $params['article_id'],
            ];
            // 按照部门,角色,岗位,用户名称查询
            if ($uids) {

                $conds['sign_uid'] = $uids;
            }

            // 列表总数
            $total = $this->_d->list_by_conds($conds);
            if ($total > 0) {

                $fields = 'sign_id,sign_uid,sign_on_time,ed_id,plan_id';
                $data = $this->_d->list_by_conds($conds, $page_option, $order_option, $fields);
                // 提取用户
                $ru_uids = array_column($data, 'sign_uid');
                // 签到列表
                $sign_list = array_combine_by_key($data, 'sign_uid');
            }
        } elseif (self::SIGN_NOT_DO == $sign_status) {
            // 缺勤
            // 按照签到时间进行倒序排列
            $order_option = ['ru_id' => 'asc'];
            // 按照部门,角色,岗位,用户名称查询
            if ($uids) {
                $conds['ru_uid'] = $uids;
            }
            // 报名成功
            $conds['ru_sign_status'] = RightUsersService::SIGN_SUCCESS;
            $conds['ed_id'] = $plan['ed_id'];
            // 开启审核
            if (EducationService::EDUCATION_CHECK == $education['ed_is_check']) {
                $conds['ru_check_status'] = self::CHECK_PASS;
            }

            // 查询班级表
            $fields = 'ru_uid';
            $user_list = $this->right_user_d->list_by_conds($conds, null, $order_option, $fields);
            $user_list = array_combine_by_key($user_list, 'ru_uid');

            $ru_uids = array_column($user_list, 'ru_uid');
            $fields = 'sign_id,sign_uid,sign_on_time,ed_id,plan_id';
            $where = [
                'plan_id' => $params['plan_id'],
            ];
            // 查询签到表
            $sign_list = $this->_d->list_by_conds($where, null, null, $fields);
            $sign_list_uids = array_column($sign_list, 'sign_uid');
            // 没有签到的用户uid集合
            $diff_uids = array_diff($ru_uids, $sign_list_uids);

            $total = count($diff_uids);
            // 初始化未签到的用户列表
            $sign_list = [];
            if ($total) {
                // 获取未签到用户的班级表信息
                foreach ($diff_uids as $no_sing_uid) {
                    $sign_list[] = $user_list[$no_sing_uid];
                }

                if ($page_option != null) {
                    // 数组分页
                    $sign_list = array_slice($sign_list, $page_option[0], $limit);
                }

                // 分页后的用户UID
                $ru_uids = array_column($sign_list, 'ru_uid');
            }

        } else {
            // 全部
            // 按照签到时间进行倒序排列
            $order_option = ['ru_id' => 'asc'];
            // 按照部门,角色,岗位,用户名称查询
            if ($uids) {
                $conds['ru_uid'] = $uids;
            }
            // 报名成功
            $conds['ru_sign_status'] = RightUsersService::SIGN_SUCCESS;
            $conds['ed_id'] = $plan['ed_id'];
            // 开启审核
            if (EducationService::EDUCATION_CHECK == $education['ed_is_check']) {
                $conds['ru_check_status'] = self::CHECK_PASS;
            }
            $total = $this->right_user_d->count_by_conds($conds);

            if ($total > 0) {
                // 查询班级表
                $fields = 'ru_uid';
                $user_list = $this->right_user_d->list_by_conds($conds, $page_option, $order_option, $fields);
                $ru_uids = array_column($user_list, 'ru_uid');
                $fields = 'sign_id,sign_uid,sign_on_time,ed_id,plan_id';
                $where = [
                    'plan_id' => $params['plan_id'],
                ];
                // 查询签到表
                $sign_list = $this->_d->list_by_conds($where, null, null, $fields);
                // 转换键值
                $sign_list = array_combine_by_key($sign_list, 'sign_uid');
            }
        }

        $list = $this->format_sign_list($ru_uids, $sign_list, $page, $limit);
        // 组装返回数
        return [
            'total' => intval($total),
            'limit' => intval($limit),
            'page' => intval($page),
            'list' => $list,
        ];
    }

    /**
     * 签到列表数据格式化
     *
     * @author 蔡建华
     *
     * @param $uids array 用户UID
     * @param $sign_list array 签到数据
     * @param $page int 页码
     * @param $limit int 每页条数
     *
     * @return array
     */
    protected function format_sign_list($uids, $sign_list, $page, $limit)
    {
        if (empty($uids)) {
            return [];
        }
        $result = [];
        $user_list = $this->get_all_user_by_cache($uids);
        // 开始条数
        $start = ($page - 1) * $limit;

        foreach ($uids as $key => $val) {
            $value = [];
            // 排序序号
            $value['order_num'] = $start + $key + 1;
            $_user = $user_list[$val];
            $value['memUsername'] = $_user['memUsername'];
            // 部门去重
            $dpName = array_column($_user['dpName'], 'dpName');
            array_unique($dpName);
            $value['dpName'] = implode(',', $dpName);
            $value['jobName'] = $_user['memJob'];
            $value['roleName'] = $_user['memRole'];
            $value['sign_id'] = intval($sign_list[$val]['sign_id']);

            // 已经签到
            if ($sign_list[$val]['sign_on_time']) {
                $value['sign_on_time'] = $sign_list[$val]['sign_on_time'];
                $value['sign_status'] = self::SIGN_DO;
            } else {
                // 缺勤
                $value['sign_status'] = self::SIGN_NOT_DO;
                $value['sign_on_time'] = '';
            }

            $result[] = $value;
        }

        return $result;
    }

    /**
     * 考勤下载列表接口
     *
     * @author 蔡建华
     * @param $params array 请求参数
     * @param $user array 后台用户详情
     *
     * @return bool
     */
    public function sign_download_list($params = [], $user = [])
    {
        if (empty($params['ed_id'])) {

            return false;
        }

        // 判断计划信息是否存在
        $planlist = $this->plan_d->list_by_conds(
            [
                'ed_id' => $params['ed_id'],
                'plan_type' => self::SIGN_DO
            ],
            null,
            ['plan_order' => 'ASC', 'plan_id' => 'DESC']
        );

        // 判断签到计划是否存在
        if (empty($planlist)) {

            return false;
        }

        // 培训详情
        $education = $this->education_d->get($params['ed_id']);

        if (empty($education)) {

            return false;
        }

        // 员工班级ID正序排列
        $order_option = ['ru_id' => 'ASC'];

        // 查询已报名状态
        $conds['ru_sign_status'] = RightUsersService::SIGN_SUCCESS;

        // 开启审核
        if (EducationService::EDUCATION_CHECK == $education['ed_is_check']) {

            $conds['ru_check_status'] = self::CHECK_PASS;
        }

        // 培训ID
        $conds['ed_id'] = $params['ed_id'];

        $ru_uids = [];
        $total = $this->right_user_d->count_by_conds($conds);
        $sign_list = [];

        if ($total > 0) {

            // 查询班级表
            $fields = 'ru_uid';
            $user_list = $this->right_user_d->list_by_conds($conds, null, $order_option, $fields);
            $ru_uids = array_column($user_list, 'ru_uid');

            // 查询签到表字段
            $fields = 'sign_id,sign_uid,sign_on_time,ed_id,plan_id';

            // 签到计划条件
            $where = [
                'ed_id' => $params['ed_id'],
                'article_id' => 0 // 过滤线下课程签到
            ];

            // 查询签到表
            $sign_list = $this->_d->list_by_conds($where, null, null, $fields);

            // 转换键值
            $sign_list = array_combine_by_key($sign_list, 'sign_uid');
        }

        // 格式化数据
        $data = $this->format_down_list($ru_uids, $sign_list, $planlist);

        // 下载
        $this->_download($data, $education['ed_name'], $user);

        return true;
    }

    /**
     * 考勤下载数据格式化
     *
     * @author 蔡建华
     * @param $uids array 用户UID(所有已报名的班级人员UID)
     * @param $sign_list array 签到数据(在任一签到场次签到的人员列表)
     * @param $planlist array 签到场次(所有的签到场次列表)
     *
     * @return array
     */
    protected function format_down_list($uids, $sign_list, $planlist)
    {
        // 初始化签到信息列表
        $list = [];

        if (!empty($uids)) {
            // 查询用户缓存
            $user_list = $this->get_all_user_by_cache($uids);

            // 任一场次签到的所有人员UID列表
            $sign_uids = array_column($sign_list, 'sign_uid');

            // 所有场次均未签到的人员UID列表
            $unsign_uids = array_diff($uids, $sign_uids);

            // 获取所有场次均未签到的人员信息
            $unsign_user_list = [];
            foreach ($unsign_uids as $val) {

                $unsign_user_list[] = [
                    $user_list[$val]['memUsername'],
                    implode(',', array_unique(array_column($user_list[$val]['dpName'], 'dpName'))),
                    $user_list[$val]['memJob'],
                    $user_list[$val]['memRole'],
                    '',
                    '缺勤',
                ];
            }

            foreach ($planlist as $plan) {
                // 初始化对应场次未签到的人员信息列表
                $plan_unsign_user_list = [];

                // 将所有签到的人员分发到对应的签到场次中
                foreach ($sign_list as $v) {

                    if ($v['plan_id'] == $plan['plan_id']) {
                        // 对应场次签到的人员信息列表
                        $list[$plan['plan_id']][] = [
                            $user_list[$v['sign_uid']]['memUsername'],
                            implode(',', array_unique(array_column($user_list[$v['sign_uid']]['dpName'], 'dpName'))),
                            $user_list[$v['sign_uid']]['memJob'],
                            $user_list[$v['sign_uid']]['memRole'],
                            empty($v['sign_on_time']) ? '' : rgmdate(strval($v['sign_on_time']), "Y-m-d H:i:s"),
                            empty($v['sign_on_time']) ? '' : '已签到'

                        ];
                    } else {
                        // 对应场次未签到的人员信息列表
                        $plan_unsign_user_list[] = [
                            $user_list[$v['sign_uid']]['memUsername'],
                            implode(',', array_unique(array_column($user_list[$v['sign_uid']]['dpName'], 'dpName'))),
                            $user_list[$v['sign_uid']]['memJob'],
                            $user_list[$v['sign_uid']]['memRole'],
                            '',
                            '缺勤',
                        ];
                    }
                }
                // 对应场次所有未签到的人员信息合并
                if (empty($unsign_user_list)) {

                    $all_unsign_user_list = $plan_unsign_user_list;
                } else {

                    $all_unsign_user_list = array_merge($unsign_user_list, $plan_unsign_user_list);
                }

                // 对应场次所有已签到和未签到人员信息合并
                if (empty($list[$plan['plan_id']])) {

                    $list[$plan['plan_id']] = $all_unsign_user_list;
                } else {

                    $list[$plan['plan_id']] = array_merge($list[$plan['plan_id']], $all_unsign_user_list);
                }
            }
        }

        return [
            'list' => $list,
            'planlist' => $planlist
        ];
    }

    /**
     * 导出模板
     *
     * @author 蔡建华
     * @param array $list 列表数据
     * @param string $name 培训名称
     * @param $user array 后台用户详情
     * @return bool
     */
    private function _download($list = [], $name = '', $user = [])
    {
        // 初始化导出数据
        $row_data = [];
        $file_name = $name . '-签到-' . rgmdate((string)NOW_TIME, 'Ymd');

        $title = [
            '员工姓名',
            '组织',
            '岗位',
            '角色',
            '签到时间',
            '签到状态'
        ];

        $temp = $list['list'];
        // 按照签到场次组装
        $sheets = [];
        foreach ($list['planlist'] as $k => $v) {

            if (in_array($v['plan_name'], $sheets)) {
                // 如果sheet名字重复自定加一
                $sheets[] = $v['plan_name'] . '_' . $k;

            } else {
                // sheet名字组合
                $sheets[] = $v['plan_name'];
            }

            $value = [
                'columns' => $title,
                'rows' => isset($temp[$v['plan_id']]) ? $temp[$v['plan_id']] : []
            ];

            $row_data[] = $value;
        }

        // 生成Excel
        $realpath = ExportDownload::get_down_dir($user['eaId'] . microtime(true)) . NOW_TIME . ".xls";
        $ret = PythonExcel::instance()->writeSheet($realpath, $sheets, $row_data);

        if ($ret) {
            $conditon = [
                'title' => $file_name,
                'ea_id' => $user['eaId'],
                'username' => $user['eaRealname'],
                'type' => ExportDownload::EXCEL_TYPE,
                'url' => $realpath
            ];

            ExportDownload::insert_down_load($conditon);
        }

        return true;
    }

    /**
     * 导出线下课程签到数据
     * @author zhonglei
     * @param array $article 线下课程数据
     * @param array $data 线下课程签到数据
     * @param array $user 管理员数据
     * @return void
     */
    public function exportArticleSignData($article, $data, $user)
    {
        $titles = [
            '员工姓名',
            '组织',
            '岗位',
            '角色',
            '签到时间',
            '签到状态'
        ];

        $realpath = ExportDownload::get_down_dir($user['eaId'] . microtime(true)) . MILLI_TIME . '.xls';
        $ret = PythonExcel::instance()->write($realpath, $titles, $data);

        if ($ret) {
            $conditon = [
                'title' => "{$article['article_title']}-签到-" . rgmdate(MILLI_TIME),
                'ea_id' => $user['eaId'],
                'username' => $user['eaRealname'],
                'type' => ExportDownload::EXCEL_TYPE,
                'url' => $realpath
            ];

            ExportDownload::insert_down_load($conditon);
        }
    }
}