package jnpf.cultivate.controller.web.exam;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageInfo;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.vo.PageListVO;
import jnpf.config.ConfigValueUtil;
import jnpf.cultivate.service.FtbCultivateExamService;
import jnpf.cultivate.service.FtbCultivateExamUserService;
import jnpf.cultivate.service.FtbCultivateLearnTaskListService;
import jnpf.cultivate.utils.UserApiV2Util;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.model.cultivate.dto.statistics.CultivatePermissionModuleParam;
import jnpf.model.cultivate.dto.statistics.ExamStatisticsForOrgDTO;
import jnpf.model.cultivate.dto.statistics.ExamStatisticsForPersonDTO;
import jnpf.model.cultivate.dto.statistics.FtbCultivateStatisticsDTO;
import jnpf.model.cultivate.req.exam.*;
import jnpf.model.cultivate.resp.*;
import jnpf.model.cultivate.vo.common.InnerPowerUserVO;
import jnpf.util.*;
import jnpf.util.data.DataSourceContextHolder;
import jnpf.util.excel.EasyExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * web用户考试模块
 *
 * @author xuguilin
 */
@RestController
@Slf4j
@RequestMapping("/user-exam")
public class FtbCultivateExamUserController {
    @Autowired
    private ConfigValueUtil configValueUtil;
    /**
     * 考试用户服务
     */
    @Autowired
    private FtbCultivateExamUserService examUserService;

    /**
     * 考试服务
     */
    @Autowired
    private FtbCultivateExamService examService;

    @Autowired
    private FtbCultivateLearnTaskListService learnTaskListService;

    @Autowired
    private UserApiV2Util userApiV2Util;

    /**
     * 权限前缀
     */
//    private static final String EXAM_PERMISSION_PRE = "examList::";


    /**
     * web考试列表-批阅--列出考试用户列表
     *
     * @param req
     * @return
     */
    @GetMapping("/pageLists")
    public ActionResult<PageListVO<ExamListUserVo>> pageLists(@Valid QueryExamUserReq req) {
        PageInfo<ExamListUserVo> pageVo = examUserService.getPageList(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

    /**
     * 根据当前用户获取数据权限的用户
     *
     * @return
     */
    @GetMapping("/getPermissionUser")
    public ActionResult<InnerPowerUserVO> getPermissionUser(CultivatePermissionModuleParam dto) {
        return ActionResult.success(userApiV2Util.getLoginManagerUserIdsForEncode());
    }


    /**
     * web考试列表-批阅-考试用户列表-查看用户的考试试卷信息
     *
     * @param userExamId 考试用户ID
     * @return
     */
    @GetMapping("/get/{userExamId}")
    public ActionResult<UserExamDetailVo> get(@PathVariable("userExamId") String userExamId) {
        return ActionResult.success(examUserService.getUserExamDetail(userExamId, true));
    }

    /**
     * web考试列表-批阅-考试用户列表-发起重新考试
     *
     * @param req 考试用户ID
     * @return
     */
    @PostMapping("/restartExam")
    public ActionResult<Boolean> restartExam(@Valid @RequestBody WebRestartExamReq req) {
        examUserService.webRestartExam(req);
        return ActionResult.success("操作成功", true);
    }


    /**
     * 批阅考试
     *
     * @param req
     * @return
     */
    @PostMapping("/readOver")
//    @SaCheckPermission(EXAM_PERMISSION_PRE + "btn_exam_read_over")
    public ActionResult<Boolean> readOver(@RequestBody ReadOverExamReq req) {
        examUserService.readOver(req);
        return ActionResult.success(true);
    }


    /**
     * 检测是否可以删除用户考试
     *
     * @param id 用户考试ID
     * @return
     */
    @GetMapping("/check-can-del/{id}")
    public ActionResult<CanDeleteMsg> checkCanDel(@PathVariable("id") String id) {
        return ActionResult.success(examUserService.checkUserExamCanDelete(id));
    }


    /**
     * 删除用户考试
     *
     * @param id       用户考试ID
     * @param isRepeat 0 直接删除，1 删除后重新创建考试记录
     * @return
     */
    @DeleteMapping("/del/{id}")
    public ActionResult<Boolean> del(@PathVariable("id") String id, @RequestParam(name = "isRepeat", defaultValue = "0") Integer isRepeat) {
        if (isRepeat == 1) {
            //删除并重新创建考试记录，让用户重新考试
            examUserService.deleteAndCreateExam(id);
        } else {
            //直接删除
            examUserService.deleteData(id);
        }
        return ActionResult.success(true);
    }


    /**
     * 考试排行版
     *
     * @param examId 考试id
     * @return
     */
    @GetMapping("/ranking/{examId}")
    public ActionResult<PageListVO<UserRankingVo>> rankingList(@PathVariable("examId") String examId,
                                                               QueryExamRankListReq req) {
        PageInfo<UserRankingVo> pageVo = examUserService.rankIngList(examId, req);

        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));

    }


    /**
     * 查询考试统计
     *
     * @param req
     * @return
     */
    @GetMapping("/statistics")
    public ActionResult<ExamStatisticsVo> statistics(FtbCultivateStatisticsDTO req) {
        return ActionResult.success(examUserService.statistics(req));
    }

    /**
     * 检测过期的考试，并修改状态为过期
     *
     * @return
     */
    @NoDataSourceBind
    @GetMapping("/checkAndUpdateExpireUserExamStatus")
    public ActionResult<Integer> checkAndUpdateExpireUserExamStatus(@RequestParam("tenantId") String tenantId) {

        // 判断是否为多租户
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                //切换成租户库
                try {
                    TenantDataSourceUtil.switchTenant(tenantId);
                } catch (LoginException e) {
                    log.error("检测过期的考试, 切换租户失败, {}", tenantId);
                }
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }
        //1检测和修改用户的过期考试
        Integer num = examUserService.checkAndUpdateExpireUserExamStatus();
        //2检测和修改常规考试过期
        examService.changeExamStatus();
        return ActionResult.success(num);
    }

    /**
     * 员工首页-查询考试成绩列表
     *
     * @param req
     * @return
     */
    @GetMapping("/queryCultivateExamList")
    public ActionResult<PageListVO<MyExamListVo>> queryCultivateExamList(@Valid QueryCultivateExamReq req) {
        String loginUserId = UserProvider.getLoginUserId();
        if (StringUtils.isEmpty(req.getUserId())) {
            req.setUserId(loginUserId);
        }
        PageInfo<MyExamListVo> pageVo = examUserService.queryExamList(req);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }


    /**
     * 考试统计，组织维度
     */
    @GetMapping("/queryExamStatisticsForOrg")
    public ActionResult<List<ExamStatisticsForOrgVo>> queryExamStatisticsForOrg(ExamStatisticsForOrgDTO dto) {
        return ActionResult.success("成功", examUserService.queryExamStatisticsForOrg(dto, new ArrayList<>()));
    }

    /**
     * 考试统计，组织维度,导出
     */
    @GetMapping("/queryExamStatisticsForOrg/export")
    public void exportOrg(ExamStatisticsForOrgDTO dto, HttpServletResponse response) throws IOException {
        String fileName = "考试统计_组织维度_" + DateUtil.format(new Date(), "yyyyMMdd");
        List<String> userIds = new ArrayList<>();
        List<ExamStatisticsForOrgVo> list = examUserService.queryExamStatisticsForOrg(dto, userIds);
        List<ExamStatisticsForOrgExcelVo> excelList = BeanUtil.copyToList(list, ExamStatisticsForOrgExcelVo.class);
        EasyExcelUtils.exportExcel(response, fileName, excelList, ExamStatisticsForOrgExcelVo.class);
    }

    /**
     * 考试统计，个人维度
     */
    @PostMapping("/queryExamStatisticsForPerson")
    public ActionResult<PageListVO<ExamStatisticsForPersonVo>> queryExamStatisticsForPerson(@RequestBody ExamStatisticsForPersonDTO dto) {
        PageInfo<ExamStatisticsForPersonVo> pageVo = examUserService.queryExamStatisticsForPerson(dto);
        return ActionResult.page(pageVo.getList(), FtbUtil.getPagination(pageVo));
    }

    /**
     * 考试统计，个人维度,导出
     */
    @PostMapping("/queryExamStatisticsForPerson/export")
    public void exportPerson(@RequestBody ExamStatisticsForPersonDTO dto, HttpServletResponse response) throws IOException {

        PageInfo<ExamStatisticsForPersonVo> pageVo = examUserService.queryExamStatisticsForPerson(dto);
        List<ExamStatisticsForPersonVo> list = pageVo.getList();
        List<ExamStatisticsForPersonExcelVo> excelVOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(list)) {
            for (ExamStatisticsForPersonVo vo : list) {
                excelVOList.add(QuestionAnalysisUtil.convertToExcelPersonvo(vo));
            }
        }
        String fileName = "考试统计_个人维度_" + DateUtil.format(new Date(), "yyyyMMdd");
        EasyExcelUtils.exportExcel(response, fileName, excelVOList, ExamStatisticsForPersonExcelVo.class);
    }

    /**
     * 处理老数据
     */
    @GetMapping("/dealExamUserPositionForOldData")
    @NoDataSourceBind
    @Deprecated(since = "已经作废，之前上线用户处理老数据的")
    public void dealExamUserPositionForOldData(@RequestParam("tenantId") String tenantId) {
        // 判断是否为多租户
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                //切换成租户库
                try {
                    TenantDataSourceUtil.switchTenant(tenantId);
                } catch (LoginException e) {
                    throw new RuntimeException("切换租户失败");
                }
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }

        examUserService.dealExamUserPositionForOldData();
    }

}
