<?php

declare(strict_types=1);

namespace app\control\controller\exam;

use app\common\model\account\User as UserModel;
use app\common\model\Base;
use app\control\model\User;
use app\Request;
use app\common\model\exam\Question as QuestionModel;
use Exception;
use app\common\model\core\Excel;
use mb\helper\Collection;
use think\facade\App;
use think\facade\Db;
use think\response\Json;
use app\common\model\exam\Subject;
use app\common\model\exam\Knowledge;
use app\common\model\exam\Paper;

/**
 * Class Question
 * @package app\control\controller\exam
 */
class Question
{
    /**
     * @param Request $request
     * @return Json
     * @see QuestionTest::testHandelAdd() 添加操作题
     * @see QuestionTest::testJudgeAdd() 添加判断题
     * @see QuestionTest::testChoiceAdd() 添加单选题
     * @see QuestionTest::testChoicesAdd() 添加多选题
     * @see QuestionTest::testCompositionAdd() 添加作文题
     * @see QuestionTest::testTypingAdd() 添加打字题
     *
     * @api {post} /exam/question/add 添加试题
     * @apiGroup ExamQuestion
     * @apiName sort1
     * @apiVersion 1.0.0
     *
     * @apiDescription 添加试题 <hr><br />
     * type 类型：judge - 判断 fillIn - 填空 choice - 单选 choices - 复选
     * handel - 操作 composition - 作文 answer - 问答 typing - 打字 <br />
     * difficultyLevel 类型: easy 容易 moreEasily 较易 medium 中等 moreDifficult 较难 difficult 难
     *
     * @apiParam {string} name  题目
     * @apiParam {string} type  类型
     * @apiParam {number} score  分数
     * @apiParam {string} difficultyLevel  难度
     * @apiParam {number} knowledge  知识点ID
     * @apiParam {number} subject  科目ID
     * @apiParam {string} analysis  解析
     * @apiParam {Object} answer  答案
     * @apiParam {Object} options  选项
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     */
    public function add(Request $request)
    {
        $currentUser = User::fetchCurrent();
        $input = $request->post();
        if (empty($input['type']) || empty($input['knowledge']) ||
            empty($input['subject']) || empty($input['difficultyLevel']) || empty($input['score']) ||
            empty($input['name']) || empty(
                $input['analysis'] ||
                !in_array($input['type'], QuestionModel::TYPE)
            )) {
            return payload(error(-10, '缺少参数'));
        }
        $questionInfo = [
            'name' => $input['name'],
            'type' => $input['type'],
            'score' => $input['score'],
            'founder' => $currentUser['id'],
            'difficultyLevel' => $input['difficultyLevel'],
            'knowledge' => $input['knowledge'],
            'subject' => $input['subject'],
            'analysis' => serialize($input['analysis']),
        ];
        $res = self::handelOptions($questionInfo['type'], $input);
        if (is_error($res)) {
            return payload($res);
        }
        list($questionInfo['answer'], $questionInfo['options']) = $res;
        $result = QuestionModel::add($questionInfo);
        if (is_error($result)) {
            return payload(error(-20, '添加失败'));
        }
        return payload();
    }

    /**
     * @param $type
     * @param $input
     * @return array|\Error
     */
    public static function handelOptions($type, $input)
    {
        $answer = $input['answer'];
        $options = [];
        switch ($type) {
            case 'judge':
            case 'fillIn':
            case 'answer':
            case 'typing':
            case 'handel':
            case 'composition':
                break;
            case 'choices':
            case 'choice':
                if (empty($input['options'])) {
                    return error(-12, '缺少options参数');
                    break;
                }
                foreach ($input['options'] as $k => $v) {
                    $options[QuestionModel::CHOICES[$k + 1]] = $v['content'];
                }
                break;
            default:
                return error(-11, 'type错误');
                break;
        }
        return [serialize($answer), serialize($options)];
    }

    /**
     * @param Request $request
     * @return Json
     *
     * @api {post} /exam/question/search 试题列表
     * @apiGroup ExamQuestion
     * @apiName sort2
     * @apiVersion 1.0.0
     *
     * @apiDescription 接口描述
     *
     * @apiParam {number} current  页码
     * @apiParam {number} pageSize  页数
     * @apiParam {string} [type]  类型 参考添加题
     * @apiParam {number} [knowledge]  知识点ID
     * @apiParam {number} [subject]  科目ID
     * @apiParam {string} [difficultyLevel]  级别
     * @apiParam {string} [name]  名称
     * @apiParam {string} [sortField]  排序字段
     * @apiParam {string} [sortDirection]  排序方式
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     */
    public function search(Request $request)
    {
        $input = $request->post();
        $pageIndex = empty($input['current']) ? 1 : intval($input['current']);
        $pageSize = empty($input['pageSize']) ? 10 : intval($input['pageSize']);
        $total = 0;
        $filters = [];
        if (!empty($input['type'])) {
            $filters['type'] = $input['type'];
        }
        if (!empty($input['knowledge'])) {
            $filters['knowledge'] = $input['knowledge'];
        }
        if (!empty($input['subject'])) {
            $filters['subjects'] = $input['subject'];
        }
        if (!empty($input['difficultyLevel'])) {
            $filters['difficultyLevel'] = $input['difficultyLevel'];
        }
        if (!empty($input['name'])) {
            $filters['name'] = $input['name'];
        }
        $sortField = empty($input['sortField']) ? 'id' : $input['sortField'];
        $sortDirection = empty($input['sortDirection']) ? 'desc' : $input['sortDirection'];
        $filters['order'] = [$sortField => $sortDirection];
        $dataSet = QuestionModel::search($filters, $pageIndex, $pageSize, $total);
        foreach ($dataSet as $key => &$row) {
            if ($sortDirection == 'asc') {
                $row['number'] = (($pageIndex - 1) * $pageSize) + $key + 1;
            } else {
                $row['number'] = $total - ((($pageIndex - 1) * $pageSize) + $key);
            }
            $subjectInfo = Subject::fetch(intval($row['subject']));
            $row['subjectTitle'] = empty($subjectInfo['title']) ? '' : $subjectInfo['title'];
            $knowledgeInfo = Knowledge::fetch(intval($row['knowledge']));
            $row['knowledgeTitle'] = empty($knowledgeInfo['title']) ? '' : $knowledgeInfo['title'];
            $row['typeTitle'] = !empty(QuestionModel::TYPE[$row['type']]) ? QuestionModel::TYPE[$row['type']] : '';
            $row['difficultyLevelTitle'] = !empty(QuestionModel::DIFFICULTY_LEVEL[$row['difficultyLevel']])
                ? QuestionModel::DIFFICULTY_LEVEL[$row['difficultyLevel']] : '';
            $userInfo = UserModel::fetch($row['founder']);
            $row['founderTitle'] = isset($userInfo['uid']) ? $userInfo['uid'] : '';
        }
        return payload(['dataSet' => $dataSet, 'total' => $total]);
    }

    /**
     * @param Request $request
     * @return Json
     * @see QuestionTest::testQuestionModify() 测试修改
     *
     * @api {post} /exam/question/modify 修改试题
     * @apiGroup ExamQuestion
     * @apiName sort3
     * @apiVersion 1.0.0
     *
     * @apiDescription 添加试题 <hr><br />
     * type 类型：judge - 判断 fillIn - 填空 choice - 单选 choices - 复选
     * handel - 操作 composition - 作文 answer - 问答 typing - 打字 <br />
     * difficultyLevel 类型: easy 容易 moreEasily 较易 medium 中等 moreDifficult 较难 difficult 难
     *
     * @apiParam {string} id  题目
     * @apiParam {string} name  题目
     * @apiParam {string} type  类型
     * @apiParam {number} score  分数
     * @apiParam {string} difficultyLevel  难度
     * @apiParam {number} knowledge  知识点ID
     * @apiParam {number} subject  科目ID
     * @apiParam {string} analysis  解析
     * @apiParam {Object} answer  答案
     * @apiParam {Object} options  选项
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     */
    public function modify(Request $request)
    {
        $currentUser = User::fetchCurrent();
        $input = $request->post();
        $existsParasm = Base::existsParams(
            $input,
            ['id', 'type', 'knowledge', 'subject', 'difficultyLevel', 'score', 'name', 'answer', 'analysis']
        );
        $existsParasm['analysis'] = serialize($existsParasm['analysis']);
        if (is_error($existsParasm)) {
            return payload($existsParasm);
        }
        $questionInfo = QuestionModel::fetch(['id' => $existsParasm['id'], 'founder' => $currentUser['id']]);
        if (empty($questionInfo)) {
            return payload(error(-20, '未查到试题'));
        }
        $res = self::handelOptions($existsParasm['type'], $input);
        if (is_error($res)) {
            return payload($res);
        }
        list($existsParasm['answer'], $existsParasm['options']) = $res;
        $result = QuestionModel::update(intval($existsParasm['id']), $existsParasm);
        if (is_error($result)) {
            return payload(error(-21, '修改失败'));
        }
        return payload();
    }

    /**
     * @param Request $request
     * @return Json
     *
     * @api {post} /exam/question/delete 删除试题
     * @apiGroup ExamQuestion
     * @apiName sort4
     * @apiVersion 1.0.0
     *
     * @apiDescription 删除试题
     *
     * @apiParam {number} [id]  id
     * @apiParam {object} [ids]  id组
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     */
    public function delete(Request $request)
    {
        $currentUser = User::fetchCurrent();
        $input = $request->post();
        if (empty($input['id']) && empty($input['ids'])) {
            return payload(error(-10, '缺少参数'));
        }
        $filters = [];
        if (!empty($input['id'])) {
            $filters['id'] = $input['id'];
            $check = Paper::search(['question' => $filters['id'], 'timeEnd' => date('Y-m-d H:i:s', time())], 0, 0);
            if (!empty($check)) {
                return payload(error(-10, '该题已被使用，无法删除'));
            }
        } else {
            $filters['ids'] = $input['ids'];
            foreach ($filters['ids'] as $item) {
                $res = Paper::search(['question' => $item, 'timeEnd' => date('Y-m-d H:i:s', time())], 0, 0);
                if (!empty($res)) {
                    return payload(error(-10, '该题已被使用，无法删除'));
                }
            }
        }
        $filters['founder'] = $currentUser['id'];
        $result = QuestionModel::remove($filters);
        if ($result) {
            return payload();
        }
        return payload(error(-20, '删除失败'));
    }

    /**
     * @param Request $request
     * @return Json
     */
    public function import(Request $request)
    {
        $input = $request->post();
        if (empty($input['src'])) {
            return payload(error(-10, '参数不完整'));
        }
        $result = QuestionModel::questionImport(App::getRootPath() . 'public/' . $input['src']);
        if (!empty($result)) {
            return payload(['dataSet' => ['error' => $result]]);
        }
        return payload();
    }

    /**
     * @return Json
     */
    public function export(Request $request)
    {
        $input = $request->param();
        try {
            $subjects = Db::table('exam_subjects')->select()->toArray();
            $subjects = Collection::key($subjects, 'id');
            $knowledges = Db::table('exam_knowledge')->select()->toArray();
            $knowledges = Collection::key($knowledges, 'id');
        } catch (Exception $e) {
            return payload(error(-20, '导出失败'));
        }
        $filters = [];
        if (!empty($input['type'])) {
            $filters['type'] = $input['type'];
        }
        if (!empty($input['knowledge'])) {
            $filters['knowledge'] = $input['knowledge'];
        }
        if (!empty($input['subject'])) {
            $filters['subjects'] = $input['subject'];
        }
        if (!empty($input['difficultyLevel'])) {
            $filters['difficultyLevel'] = $input['difficultyLevel'];
        }
        if (!empty($input['name'])) {
            $filters['name'] = $input['name'];
        }
        $headers = ['', '科目名称', '知识点', '题型名称', '试题难度', '试题分数', '试题内容', '试题选项', '标准答案', '试题解析'];
        $questions = QuestionModel::search($filters, 0);
        $excelSet = [];
        foreach ($questions as $k => $v) {
            $answer = $v['answer'];
            if ($v['type'] == 'choices') {
                $answer = implode('', $answer);
            } elseif ($v['type'] == 'judge') {
                $answer = empty($answer) ? '错误' : '正确';
            } elseif ($v['type'] == 'handel') {
                $answer = empty($answer['url']) ? '' : $answer['url'];
            } elseif (in_array($v['type'], ['typing'])) {
                $answer = implode(',', $answer);
            }
            $excelSet[] = [
                '' => '',
                'subject' => !empty($subjects[$v['subject']]) ? $subjects[$v['subject']]['title'] : '',
                'knowledge' => !empty($knowledges[$v['knowledge']]) ? $knowledges[$v['knowledge']]['title'] : '',
                'type' => !empty(QuestionModel::TYPE[$v['type']]) ? QuestionModel::TYPE[$v['type']] : '',
                'difficulty_level' => !empty(QuestionModel::DIFFICULTY_LEVEL[$v['difficultyLevel']]) ? QuestionModel::DIFFICULTY_LEVEL[$v['difficultyLevel']] : '',
//                'score' => $v['score'],
                'name' => $v['name'],
                'options' => !empty($v['options']) ? implode('|', $v['options']) : '',
                'answer' => $answer,
                'analysis' => $v['analysis']
            ];
        }
        Excel::write('题库列表', $headers, $excelSet);
        exit;
    }

    /**
     * @param Request $request
     * @return Json
     * @api {post} /exam/question/questionStatistics 试题统计
     * @apiGroup ExamQuestion
     * @apiName sort5
     * @apiVersion 1.0.0
     *
     * @apiDescription 试题统计
     *
     * @apiParam {number} subject  科目ID
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     */
    public function questionStatistics(Request $request)
    {
        $input = $request->post();
        $params = Base::existsParams($input, ['subject']);
        if (is_error($params)) {
            return payload($params);
        }
        $dataSet = QuestionModel::statistics($params['subject']);
        $dataSet['knowledgeCount'] = array_map(
            function ($row) {
                $knowledgeInfo = Knowledge::fetch(intval($row['type']));
                if (!empty($knowledgeInfo)) {
                    $row['type'] = $knowledgeInfo['title'];
                }
                return $row;
            },
            $dataSet['knowledgeCount']
        );
        $dataSet['difficultyCount'] = array_map(
            function ($row) {
                $row['type'] = QuestionModel::DIFFICULTY_LEVEL[$row['type']];
                return $row;
            },
            $dataSet['difficultyCount']
        );
        if (is_error($dataSet)) {
            return payload($dataSet);
        }
        return payload(['dataSet' => $dataSet]);
    }

    /**
     * @param Request $request
     * @return Json
     *
     * @api {post} /exam/question/subjectStatistics 科目统计
     * @apiGroup ExamQuestion
     * @apiName sort6
     * @apiVersion 1.0.0
     *
     * @apiDescription 科目统计
     *
     * @apiParam {number} current  页码
     * @apiParam {number} pageSize  页数
     * @apiParam {string} title  科目名称
     *
     * @apiSuccess {Number} code    状态码，0：请求成功
     * @apiSuccess {String} message   提示信息
     * @apiSuccess {Object} dataSet    返回数据
     *
     * @apiSuccessExample {json} Success-Response:
     * {"errCode":0,"errMsg":"","dataSet":[],"total":0}
     *
     * @apiErrorExample {json} Error-Response:
     * {"errCode":5001,"errMsg":"接口异常"}
     *
     */
    public function subjectStatistics(Request $request)
    {
        $input = $request->post();
        $pageIndex = empty($input['current']) ? 1 : intval($input['current']);
        $pageSize = empty($input['pageSize']) ? 10 : intval($input['pageSize']);
        $total = 0;
        $filters = [];
        if (!empty($input['title'])) {
            $filters['title'] = $input['title'];
        }
        $dataSet = Subject::search($filters, $pageIndex, $pageSize, $total);
        $returnSet = array_map(
            function ($row) {
                $row['questionCount'] = QuestionModel::questionCount($row['id']);
                return $row;
            },
            $dataSet
        );
        return payload(['dataSet' => $returnSet, 'total' => $total]);
    }
}