<?php

declare(strict_types=1);

namespace app\dock\controller;

use app\common\model\exam\Paper;
use app\BaseController;
use app\common\model\exam\paper\Record;
use app\common\model\exam\Question;
use app\Request;
use mb\helper\Collection;
use think\response\Json;
use app\dock\model\User;
use app\common\model\account\User as UserModel;

/**
 * Class Exam
 * @package app\dock\controller
 */
class Exam extends BaseController
{
    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;
        $filter = [];
        $filter['type'] = empty($input['type']) ? '' : $input['type'];
        $papers = Paper::userWatch();
        if (empty($papers)) {
            return payload(['dataSet' => [], 'total' => 0]);
        }
        $filter['ids'] = implode(',', $papers);
        $filter['timeStart'] = date('Y-m-d H:i:s', time());
        $filter['timeEnd'] = date('Y-m-d H:i:s', time());
        $dataSet = Paper::search($filter, $pageIndex, $pageSize, $total);
        $dataSet = array_map(
            function ($val) {
                $val['questionType'] = unserialize($val['questionType']);
                $totalNum = 0;
                foreach ($val['questionType'] as $item) {
                    $totalNum += $item['questionNum'];
                }
                unset($val['questionType']);
                $val['totalQuestionNum'] = $totalNum;
                return $val;
            },
            $dataSet
        );
        return payload(['dataSet' => $dataSet, 'total' => $total]);
    }

    /**
     * @param Request $request
     * @return Json
     */
    public function fetch(Request $request)
    {
        $input = $request->post();
        if (empty($input['paperId'])) {
            return payload(error(-10, '试卷信息有误'));
        }
        $filter = [];
        $filter['id'] = $input['paperId'];
        $filter['timeStart'] = date('Y-m-d H:i:s', time());
        $filter['timeEnd'] = date('Y-m-d H:i:s', time());
        $data = Paper::search($filter, 0);
        if (empty($data)) {
            return payload(error(-11, '不在考试时间内，无法查看试卷信息'));
        }
        $data = array_map(
            function ($val) {
                $val['questionType'] = unserialize($val['questionType']);
                $totalNum = 0;
                foreach ($val['questionType'] as $item) {
                    $totalNum += $item['questionNum'];
                }
                unset($val['questionType']);
                $val['totalQuestionNum'] = $totalNum;
                return $val;
            },
            $data
        );
        unset($data[0]['questionType']);
        return payload(['data' => $data[0]]);
    }

    /**
     * @param Request $request
     * @return Json
     * @throws \think\Exception
     */
    public function create(Request $request)
    {
        $user = User::fetchCurrent();
        $input = $request->post();
        if (empty($input['id'])) {
            return payload(error(-1, '参数不完整'));
        }
        $papers = Paper::userWatch();
        if (!in_array($input['id'], $papers)) {
            return payload(error(-10, '您并不在当次考试人员名单中'));
        }
        $record = Record::fetchRec(['paper' => intval($input['id']), 'user' => $user['id']]);
        $paper = Paper::fetch(intval($input['id']));
        if ((!empty($record) && ($record['status'] == 'end')) && ($paper['multiple'] != 1)) {
            return payload(error(-1, '该试卷不允许多次考试'));
        }
        if (!empty($record) && ($record['status'] == 'start')) {
            $recData['time_beat'] = time();
            Record::update(['id' => $record['id']], $recData);
            return payload([]);
        }
        $data = [
            'paper_id' => intval($input['id']),
            'user_id' => $user['id'],
            'status' => 'start',
            'total_points' => $paper['total_points'],
            'score' => 0,
            'mark_id' => 0,
            'exam_time' => 0,
            'mark_status' => 'await',
            'result' => '',
            'time_beat' => time(),
            'time_end' => 0
        ];
        if ($paper['way'] == 'question') {
            $question = Paper::make(unserialize($paper['strategies']));
            if (is_error($question)) {
                return payload(error(-1, '题库发生变更，请联系管理员修改试卷内容'));
            }
            $data['question'] = serialize($question);
        } else {
            $question = unserialize($paper['question']);
            $check = Paper::checkQuestionExist($question);
            if (is_error($check)) {
                return payload(error(-1, '题库发生变更，请联系管理员修改试卷内容'));
            }
            $data['question'] = '';
        }
        $res = Record::add($data);
        if ($res) {
            return payload([]);
        }
        return payload(error(-3, '系统故障，请重试'));
    }

    /**
     * @param Request $request
     * @return Json
     * @throws \think\Exception
     */
    public function detail(Request $request)
    {
        $user = User::fetchCurrent();
//        $user['id'] = 70;
        $input = $request->post();
        if (empty($input['id'])) {
            return payload(error(-1, '参数不完整'));
        }
        $paper = Paper::fetch(intval($input['id']));
        $record = Record::fetchRec(['paper' => intval($input['id']), 'user' => $user['id']]);
        if (!empty($record) && ($paper['way'] == 'question')) {
            $dataSet = Paper::preview(intval($input['id']), unserialize($record['question']));
        } else {
            $dataSet = Paper::preview(intval($input['id']));
        }
        if (is_error($dataSet)) {
            return payload(error(-11, $dataSet->getMessage()));
        }
        if (empty($record)) {
            $dataSet['remainTime'] = Paper::secToTime($paper['time']);
        } else {
            $dataSet['remainTime'] = Paper::secToTime(($paper['time'] * 60) - $record['exam_time']);
        }
        $answers = [];
        $question = [];
        foreach ($dataSet['question'] as $v) {
            $question = array_merge($question, $v);
        }
        $questionArr = Question::search(['ids' => $question], 0);
        $questionArr = Collection::key($questionArr, 'id');
        foreach ($dataSet['question'] as &$val) {
            foreach ($val as &$v) {
                if (isset($questionArr[$v])) {
                    $v = $questionArr[$v];
                    $v = Collection::elements(['id', 'type', 'name', 'options', 'knowledge', 'answer'], $v);
                    if ($v['type'] == 'handel') {
                        $v['handel'] = $v['answer'];
                    } else {
                        $v['handel'] = '';
                    }
                    if ($v['type'] == 'typing') {
                        $v['handel'] = $v['answer'];
                    }
                    unset($v['answer'], $v['type']);
                } else {
                    continue;
                }
            }
        }
        if (empty($record['result'])) {
            foreach ($dataSet['question'] as $k => $item) {
                $type = [];
                foreach ($item as $tmp) {
                    $type[$tmp['id']] = [
                        'id' => $tmp['id'],
                        'answer' => '',
                        'score' => 0,
                        'knowledge' => $tmp['knowledge'],
                        'handel' => $tmp['handel']
                    ];
                }
                $answers[$k] = $type;
            }
        } else {
            $answers = unserialize($record['result']);
        }
        $dataSet['result'] = $answers;
        $dataSet['consequence'] = $paper['result'];
        $dataSet['save'] *= 60;
        unset($questionArr);
        return payload(['dataSet' => $dataSet]);
    }

    /**
     * @param Request $request
     * @return Json
     * @throws \think\Exception
     */
    public function save(Request $request)
    {
        $input = $request->post();
        if (empty($input['type']) || empty($input['result']) || empty($input['id'])) {
            return payload(error(-1, '参数不完整'));
        }
        $user = User::fetchCurrent();
        $paper = Paper::fetch(intval($input['id']));
        $record = Record::fetchRec(['paper' => $input['id'], 'user' => $user['id']]);
        if ($record['status'] == 'end') {
            return payload(error(-99, '考试已结束'));
        }
        $data = [
            'result' => $input['result'],
            'time_beat' => time(),
        ];
        $examTime = (time() - $record['time_beat']) + $record['exam_time'];
        $remainTime = ($paper['time'] * 60) - $examTime;
        if (($remainTime <= 0) || ($input['type'] == 'end')) {
            $data['status'] = 'end';
            $data['exam_time'] = $paper['time'] * 60;
            $data['time_end'] = time();
            $fillIn = $paper['completion'] ? true : false;
            $questionType = unserialize($paper['question_type']);
            $questionType = array_map(function ($val) {
                $val = $val['point'];
                return $val;
            }, $questionType);
            $grade = Record::grade($data['result'], $questionType, $fillIn);
            $data['result'] = $grade['result'];
            $data['score'] = $grade['score'];
            $questionType = unserialize($paper['question_type']);
            $type = array_keys($questionType);
            $markType = Question::MARKTYPE;
            if ($fillIn) {
                unset($markType[array_search('fillIn', $markType)]);
            }
            $useMark = [];
            foreach ($type as $value) {
                if (in_array($value, $markType)) {
                    array_push($useMark, $value);
                }
            }
            if (empty($useMark)) {
                $data['mark_status'] = 'end';
            }
        } else {
            $data['exam_time'] = $examTime;
        }
        $data['result'] = serialize($data['result']);
        $res = Record::update(['id' => $record['id']], $data);
        if (!$res) {
            return payload(error(-1, '保存失败'));
        }
        if (isset($data['status']) && ($data['status'] == 'end') && ($input['type'] != 'end')) {
            return payload(error(-10, '考试结束'));
        }
        return payload(['id' => $record['id']]);
    }

    /**
     * @param Request $request
     * @return Json
     * @throws \think\Exception
     */
    public function statisticsDetail(Request $request)
    {
        $input = $request->post();
        if (empty($input['id'])) {
            return payload(error(-1, '参数不完整'));
        }
        $records = Record::fetch(intval($input['id']));
        $paper = Paper::fetch($records['paper_id']);
        $strategies = unserialize($paper['strategies']);
        $questionType = unserialize($paper['question_type']);
        $questionType = array_map(
            function ($q) {
                $q = $q['point'];
                return $q;
            },
            $questionType
        ); //题型对应分值
        $knowledge = [];
        foreach ($strategies as $val) {
            $knowledge[$val['knowledge']][] = $val;
        }
        $newKnowledge = [];
        foreach ($knowledge as $k) {
            if (!isset($newKnowledge[$k[0]['knowledge']])) {
                $newKnowledge[$k[0]['knowledge']] = [
                    'knowledge' => $k[0]['knowledge'],
                    'subject' => $k[0]['subject'],
                    'knowledgeTitle' => $k[0]['knowledgeTitle'],
                    'subjectTitle' => $k[0]['subjectTitle'],
                    'num' => 0,
                    'score' => 0,
                    'userScore' => 0,
                    'percent' => 0,
                    'pass' => 0,
                ];
                foreach ($k as $v) {
                    if ($paper['mode'] == 'hand') {
                        $num = count($v['strategy']);
                    } else {
                        $num = array_sum($v['strategy']);
                    }
                    $newKnowledge[$k[0]['knowledge']]['num'] += $num;
                    $score = $num * $questionType[$v['type']];
                    $newKnowledge[$k[0]['knowledge']]['score'] += $score;
                }
            }
        }
        $result = unserialize($records['result']);
        $arr = [];
        foreach ($result as $value) {
            $arr = array_merge($arr, $value);
        }
        $result = $arr;
        $questionNum = 0;
        foreach ($result as $know) {
            if ($know['score'] > 0) {
                $newKnowledge[$know['knowledge']]['userScore'] += $know['score'];
                $newKnowledge[$know['knowledge']]['pass']++;
            }
            $questionNum++;
        }
        $newKnowledge = array_map(
            function ($last) {
                $last['percent'] = sprintf("%.2f", $last['pass'] / $last['num']) * 100;
                return $last;
            },
            $newKnowledge
        );
        $user = UserModel::fetch($records['user_id']);
        $returnData = [
            'title' => $paper['title'],
            'totalPoints' => $paper['total_points'],
            'throughPoints' => $paper['through_points'],
            'timeEnd' => $records['time_end'],
            'score' => $records['score'],
            'userId' => $user['uid'],
            'name' => '',
            'questionNum' => $questionNum,
            'dataSet' => array_values($newKnowledge)
        ];
        if (!empty($user['name'])) {
            $returnData['name'] = $user['name'];
        }
        return payload(['data' => $returnData]);
    }
}