<?php
/**
 * 【调研中心-后台】20_已填写人员数据导出
 * WriteListController.class.php
 * CreateBy:dj
 * Date:2017-03-08
 */

namespace Frontend\Controller\Export;

use Common\Service\AnswerService;
use Common\Service\BaseinfoService;
use Common\Service\QuestionService;
use Common\Service\RecordService;
use Org\Util\Emoji;

class WriteListController extends \Common\Controller\Frontend\AbstractController
{

    // 免登录
    protected $_require_login = false;
    // 导出excel文件名
    const QUESTIONNAIRE_XLS_FILE_NAME = '调研已填写人员数据';

    /** @var BaseinfoService */
    protected $_base_info_s;
    /** @var QuestionService */
    protected $_question_s;
    /** @var RecordService */
    protected $_record_s;
    /** @var AnswerService */
    protected $_answer_s;

    // 前置操作
    public function before_action($action = '')
    {

        if (parent::before_action($action) === false) {

            return false;
        }

        // 调研基本信息表
        $this->_base_info_s = new BaseinfoService();
        // 调研问题信息表
        $this->_question_s = new QuestionService();
        // 调研回答详情信息表
        $this->_record_s = new RecordService();
        // 调研回答用户记录表
        $this->_answer_s = new AnswerService();

        return true;
    }

    public function Index()
    {

        // 调研id
        $qu_id = trim(I('get.qu_id'));
        // 调研基本信息
        $base_info = $this->_base_info_s->get($qu_id);

        // 查询调研题目信息列表
        $question_list = $this->_question_s->list_by_conds(['qu_id' => $qu_id], null, ['q_order' => 'ASC']);
        // 数据格式化
        $list = $this->format_data($base_info, $question_list, $qu_id);

        $this->export($base_info, $question_list, $list);

        return true;
    }

    /**
     * 获取数据列表并格式化
     *
     * @param $base_info 调研基本信息
     * @param $question_list 问题列表
     * @param $qu_id 调研id
     *
     * @return array
     */
    private function format_data($base_info, $question_list, $qu_id)
    {

        $list = [];

        // 调研填写记录信息
        $answer_list = $this->_answer_s->list_by_conds(['qu_id' => $qu_id]);
        // 填写用户id集合
        $uids = array_unique(array_filter(array_column($answer_list, 'uid')));
        sort($uids);

        // 调研填写详情记录信息列表
        $record_list = $this->_record_s->list_by_conds(['qu_id' => $qu_id]);
        $emoji = Emoji::instance();

        // 查询用户列表,将用户列表转换成以用户uid为主键的二维数组
        $user_list = $this->_base_info_s->getUser($uids);

        // 序号
        $i = 1;

        foreach ($answer_list as $k => $v) {
            // 内部用户
            if (!empty($v['uid'])) {
                // 内部用户
                $u_type = '内部用户';

                // 实名
                if (BaseinfoService::REAL_NAME == $base_info['anonymous']) {
                    // 用户信息
                    $user_data = $user_list[$v['uid']];

                    // 组织名称
                    $dp_name = '';
                    // 组织名称赋值
                    if (!empty($user_data['dpName'])) {

                        $dp_name_array = array_column($user_data['dpName'], 'dpName');
                        $dp_name = implode(',', $dp_name_array);
                    }

                    $name = $user_data['memUsername'];
                    $dpName = !empty($dp_name) ? $dp_name : '';
                    $jobName = !empty($user_data['memJob']) ? $user_data['memJob'] : '';
                    $roleName = !empty($user_data['memRole']) ? $user_data['memRole'] : '';
                    $mobile = !empty($user_data['memMobile']) ? $user_data['memMobile'] : '';
                } elseif (BaseinfoService::ANONYMOUS == $base_info['anonymous']) { // 匿名

                    $name = '匿名用户' . $i;
                    $dpName = '';
                    $jobName = '';
                    $roleName = '';
                    $mobile = '';
                }
            } elseif (!empty($v['openid'])) { // 外部用户

                $name = $v['username']; // 微信昵称
                $dpName = '';
                $jobName = '';
                $roleName = '';
                $mobile = '';
                $u_type = '外部用户';  // 外部用户
            }

            $list[$k] = [
                $i, // 序号
                $name, // 用户姓名
                $dpName, // 组织名称
                $jobName, // 岗位名称
                $roleName, // 角色名称
                $mobile, // 用户手机
                $u_type, // 用户类型:内部用户/外部用户
                rgmdate($v['created'], 'Y-m-d H:i')  // 填写时间
            ];

            // 填写详情记录
            $answer_data = [];
            // 填写详情记录赋值
            foreach ($record_list as $_v) {

                if ($_v['a_id'] == $v['a_id']) {

                    $answer_data[] = $_v;
                }
            }

            // 将此数组转换成以问题ID为主键的新数组
            $answer_data = array_combine_by_key($answer_data, 'q_id');

            // 遍历问题信息
            foreach ($question_list as $_val) {
                // 问题的填写记录
                $answer = $answer_data[$_val['qid']];
                // 单选、复选、下拉选择、性别选择
                if (in_array($_val['q_type'], QuestionService::OPTION_TYPE)) {
                    // 问题内容
                    $option_arr = unserialize($_val['q_field']);
                    // 回答内容
                    $answer_arr = unserialize($answer['answer']);

                    $answer_option = array_column($answer_arr, 'option');
                    $answer_img = array_unique(array_filter(array_column($answer_arr, 'option_img')));

                    // 循环选项,看选项是否选中
                    for ($n = 0; $n < count($option_arr); $n++) {

                        if (empty($answer['answer'])) {

                            $list[$k][] = '';  // 未选中
                            continue;
                        }

                        // 如果选项中不包含图片,则只用 选项值就可以判断
                        if (empty($option_arr[$n]['option_img'])) {

                            if (in_array($option_arr[$n]['option'], $answer_option)) { // 选中

                                $list[$k][] = '√';
                            } else { // 未选中

                                $list[$k][] = '';
                            }
                        } else {
                            if (in_array($option_arr[$n]['option'], $answer_option)
                                && in_array($option_arr[$n]['option_img'], $answer_img)
                            ) {  // 选中

                                $list[$k][] = '√';
                            } else { // 未选中

                                $list[$k][] = '';
                            }
                        }
                    }

                    // 是否包含其他选项(0:不包含,1:包含)
                    if ($_val['q_other']) {
                        // 包含其他选项
                        $list[$k][] = $answer['other'];
                    }
                } else {
                    // 上传图片和上传文件类型
                    if (in_array($_val['q_type'], QuestionService::FILE_TYPE)) {
                        // 回答内容
                        $answer_arr = unserialize($answer['answer']);
                        $answer_img = array_column($answer_arr, 'option_img');

                        $imgs = '';
                        // 循环选项,看选项是否选中
                        foreach ($answer_img as $v) {

                            if (!empty($v)) {

                                $imgs .= '\r\n' . imgUrl($v);
                            }
                        }

                        // 图片集合
                        $list[$k][] = $imgs;
                    } else {
                        // 地址
                        if ($_val['q_type'] == 22) {

                            $list[$k][] = $answer['answer'] . ' ' . $answer['other'];
                        } else {

                            $list[$k][] = $emoji->filter_emoji($answer['answer']);
                        }
                    }
                }
            }

            $i++;
        }

        return $list;
    }

    /**
     * 导出模板信息
     *
     * @param array $base_info 问卷基本信息
     * @param array $question_list 问题列表
     * @param array $list 列表数据
     */
    private function export($base_info, $question_list, $list)
    {

        // 文件名
        $fileName = self::QUESTIONNAIRE_XLS_FILE_NAME . date('_YmdHis');

        $objExcelPhp = \Com\Excel::instance();

        // 先确定是否有单选,复选,下拉选择题目
        $is_option = 0; // 默认无
        $num = 0; // 表格列数
        foreach ($question_list as $v) {
            if (in_array($v['q_type'], QuestionService::OPTION_TYPE)) {
                // 如果问题是单选,复选,下拉类型
                $is_option = 1;
                $option_arr = unserialize($v['q_field']);
                if ($v['q_other']) {
                    // 包含其他选项
                    $num = $num + count($option_arr) + 1; // 一个选项占一列
                } else {
                    // 不包含其他选项
                    $num = $num + count($option_arr); // 一个选项占一列
                }
            } else {
                // 问题类型为除单选,复选,下拉的其他类型
                $num++; // 其他类型默认都只占一列
            }
        }

        // 获取该导出数据所占列的最后一列标识
        $start = 'A';
        for ($i = 1; $i < $num + 8; $i++) {

            $start++;
        }

        // 组装表头第一行:标题
        $objExcelPhp->getActiveSheet()->setCellValue('A1', '调研标题:' . $base_info['title']);
        $objExcelPhp->getActiveSheet()->mergeCells('A1:' . $start . '1');

        // 表头字体加粗
        if ($is_option) {
            // 如果包含选项类型
            $objExcelPhp->getActiveSheet()->getStyle('A1:' . $start . '3')->getFont()->setBold(true);
            //$objExcelPhp->getActiveSheet()->getColumnDimension('A1:' . $start . '3')->setAutoSize(true);
            $objExcelPhp->getActiveSheet()->getStyle('A1:' . $start . '3')->getAlignment()->setHorizontal('center')->setVertical('center');

        } else {
            // 如果不包含选项类型
            $objExcelPhp->getActiveSheet()->getStyle('A1:' . $start . '2')->getFont()->setBold(true);
            $objExcelPhp->getActiveSheet()->getStyle('A1:' . $start . '2')->getAlignment()->setHorizontal('center')->setVertical('center');
        }

        // 组装表头问题选项行
        $start_column = 'A';
        $start_arr = ['序号', '姓名', '组织', '岗位', '角色', '手机号', '用户类型', '填写时间'];

        foreach ($start_arr as $v) {

            if ($is_option) {
                // 给单元格赋值
                $objExcelPhp->getActiveSheet()->setCellValue($start_column . '2', $v);
                // 合并行
                $objExcelPhp->getActiveSheet()->mergeCells($start_column . '2:' . $start_column . '3');
            } else {
                // 给单元格赋值
                $objExcelPhp->getActiveSheet()->setCellValue($start_column . '2', $v);
            }

            $start_column++;
        }

        foreach ($question_list as $v) {

            if (in_array($v['q_type'], QuestionService::OPTION_TYPE)) {
                // 如果问题是单选,复选,下拉类型
                $option_arr = unserialize($v['q_field']);
                // 组装其他选项
                if ($v['q_other']) {
                    // 包含其他选项
                    array_push($option_arr, ['option' => '其他']);
                }

                $kai = $start_column; // 开始合并的列标识
                for ($i = 1; $i <= count($option_arr); $i++) {

                    if ($i == count($option_arr)) {

                        $objExcelPhp->getActiveSheet()->mergeCells($kai . '2:' . $start_column . '2');
                    }

                    $objExcelPhp->getActiveSheet()->setCellValue($start_column . '3', $option_arr[$i - 1]['option']);
                    $start_column++;
                }

                $objExcelPhp->getActiveSheet()->setCellValue($kai . '2', $v['q_title']);
            } else {
                // 问题类型为除单选,复选,下拉的其他类型
                if ($is_option) {
                    // 给单元格赋值
                    $objExcelPhp->getActiveSheet()->setCellValue($start_column . '2', $v['q_title']);
                    // 合并行
                    $objExcelPhp->getActiveSheet()->mergeCells($start_column . '2:' . $start_column . '3');
                } else {
                    // 给单元格赋值
                    $objExcelPhp->getActiveSheet()->setCellValue($start_column . '2', $v['q_title']);
                }

                $start_column++;
            }
        }

        // 循环表格体赋值(因为封装方法是从第二行开始赋值的,此处将赋值方法单独提出来处理)
        if ($is_option) {
            $n = 4; // 如果包含选项类型,从第四行开始赋值
        } else {
            $n = 3; // 如果不包含选项类型,从第三行开始赋值
        }

        foreach ($list as $_row) {

            $start = 'A';
            for ($i = 0; $i < count($_row); $i++) {

                $_column = $start++;
                $objExcelPhp->getActiveSheet()->setCellValueExplicit($_column . $n, $_row[$i],
                    $this->__set_data_type($_row[$i]));
                $objExcelPhp->getActiveSheet()
                    ->getStyle($_column . $n)
                    ->getAlignment()
                    ->setWrapText(true)
                    ->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
            }

            $n++;
        }

        $objExcelPhp->make_excel_download($fileName, null, null, []);
    }

    private function __set_data_type($str)
    {

        if (is_numeric($str)) {

            if (false !== strpos($str, '.')) {

                return 'b';
            } elseif (!isset($str{3})) {

                return 'n';
            } else {

                return 'str';
            }
        } else {

            return 'str';
        }
    }
}