package com.qmth.themis.backend.api;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.qmth.themis.backend.config.DictionaryConfig;
import com.qmth.themis.business.config.SystemConfig;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.AuthDto;
import com.qmth.themis.business.dto.response.RoomCodeQueryDto;
import com.qmth.themis.business.dto.response.TEExamQueryDto;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.DownloadFileEnum;
import com.qmth.themis.business.enums.RoleEnum;
import com.qmth.themis.business.enums.UploadFileEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.EhcacheUtil;
import com.qmth.themis.business.util.RedisUtil;
import com.qmth.themis.business.util.ServletUtil;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 系统信息 前端控制器
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/27
 */
@Api(tags = "系统信息Controller")
@RestController
@RequestMapping("/${prefix.url.admin}/sys")
public class SysController {

    @Resource
    TBPrivilegeService tbPrivilegeService;

    @Resource
    TBAttachmentService tbAttachmentService;

    @Resource
    TBTaskHistoryService tbTaskHistoryService;

    @Resource
    DictionaryConfig dictionaryConfig;

    @Resource
    SystemConfig systemConfig;

    @Resource
    TBOrgService tbOrgService;

    @Resource
    TBRoleService tbRoleService;

    @Resource
    TEExamActivityService teExamActivityService;

    @Resource
    TEExamService teExamService;

    @Resource
    TBExamInvigilateUserService tbExamInvigilateUserService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    RedisUtil redisUtil;

    @ApiOperation(value = "菜单查询接口")
    @RequestMapping(value = "/getMenu", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "菜单信息", response = TBPrivilege.class)})
    public Result getMenu() {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        if (Objects.isNull(tbUser)) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
        }
        return ResultUtil.ok(tbPrivilegeService.getMenu(tbUser.getId()));
    }

    @ApiOperation(value = "获取环境接口")
    @RequestMapping(value = "/env", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "环境信息", response = Result.class)})
    public Result env(@ApiParam(value = "机构id", required = true) @RequestParam Long orgId) {
        if (Objects.isNull(orgId) || Objects.equals(orgId, "")) {
            throw new BusinessException(ExceptionResultEnum.ORG_ID_IS_NULL);
        }
//        SchoolDto schoolDto = (SchoolDto) redisTemplate.opsForValue().get(SystemConstant.SCHOOL_CACHE + orgId);
//        Map map = new HashMap();
//        map.put(SystemConstant.ENV_FILEHOST, schoolDto.getFileHost());
//        return ResultUtil.ok(map);
        return ResultUtil.ok(Collections.singletonMap("success", true));
    }

    @ApiOperation(value = "上传文件接口")
    @RequestMapping(value = "/file/upload", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "{\"id\":0}", response = Result.class)})
    public Result fileUpload(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file, @ApiParam(value = "上传文件类型", required = true) @RequestParam UploadFileEnum type) throws IOException {
        if (Objects.isNull(file) || Objects.equals(file, "")) {
            throw new BusinessException(ExceptionResultEnum.ATTACHMENT_IS_NULL);
        }
        if (Objects.isNull(type) || Objects.equals(type, "")) {
            throw new BusinessException(ExceptionResultEnum.FILE_TYPE_IS_NULL);
        }
        Map<String, Object> mapParameter = systemConfig.getOssEnv(type.getId());
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        TBAttachment tbAttachment = tbAttachmentService.saveAttachment(file, ServletUtil.getRequestMd5(), ServletUtil.getRequestPath(), mapParameter, tbUser.getOrgId(), tbUser.getId());
        if (Objects.isNull(tbAttachment)) {
            throw new BusinessException(ExceptionResultEnum.ATTACHMENT_ERROR);
        }
        JSONObject jsonObject = JSONObject.parseObject(tbAttachment.getRemark());
        String attachmentType = String.valueOf(jsonObject.get("type"));
        String url = null;
        if (Objects.equals(attachmentType, SystemConstant.LOCAL)) {
            url = "http://" + dictionaryConfig.sysDomain().getFileHost() + File.separator + jsonObject.get("path");
        } else {
            url = dictionaryConfig.aliYunOssDomain().getUrl() + File.separator + jsonObject.get("path");
        }
        Map map = new HashMap();
        map.put(SystemConstant.ID, tbAttachment.getId());
        map.put("name", tbAttachment.getName());
        map.put(SystemConstant.TYPE, tbAttachment.getType());
        map.put("url", url);
        return ResultUtil.ok(map);
    }

    @ApiOperation(value = "文件下载接口")
    @RequestMapping(value = "/file/download", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"url\":string}", response = Result.class)})
    public Result fileDownload(@ApiParam(value = "任务id", required = true) @RequestParam Long id, @ApiParam(value = "下载文件类型", required = true) @RequestParam DownloadFileEnum type) {
        if (Objects.isNull(id) || Objects.equals(id, "")) {
            throw new BusinessException(ExceptionResultEnum.TASK_ID_IS_NULL);
        }
        if (Objects.isNull(type) || Objects.equals(type, "")) {
            throw new BusinessException(ExceptionResultEnum.FILE_TYPE_IS_NULL);
        }
        if (Objects.isNull(DownloadFileEnum.convertToName(type.getId()))) {
            throw new BusinessException(ExceptionResultEnum.DOWNLOAD_FILE_TYPE_ERROR);
        }
        TBTaskHistory tbTaskHistory = tbTaskHistoryService.getById(id);
        if (Objects.isNull(tbTaskHistory)) {
            throw new BusinessException(ExceptionResultEnum.TASK_NO);
        }
        boolean oss = dictionaryConfig.sysDomain().isOss();
        JSONObject jsonObject = null;
        switch (type.getId()) {
            case 0:
                jsonObject = JSONObject.parseObject(tbTaskHistory.getImportFilePath());
                break;
            case 1:
                jsonObject = JSONObject.parseObject(tbTaskHistory.getReportFilePath());
                break;
            default:
                jsonObject = JSONObject.parseObject(tbTaskHistory.getResultFilePath());
                break;
        }
        if (Objects.isNull(jsonObject) || Objects.isNull(jsonObject.get("path"))) {
            throw new BusinessException("下载文件地址不存在");
        }
        String filePath = String.valueOf(jsonObject.get("path"));
        String url = null;
        if (oss) {
            url = dictionaryConfig.aliYunOssDomain().getUrl() + File.separator + filePath;
        } else {
            url = "http://" + dictionaryConfig.sysDomain().getFileHost() + File.separator + filePath;
        }
        Map map = new HashMap();
        map.put("url", url);
        return ResultUtil.ok(map);
    }

    @ApiOperation(value = "根据机构代码查询机构信息接口")
    @RequestMapping(value = "/org/queryByOrgCode", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "机构信息", response = TBOrg.class)})
    public Result queryByOrgCode(@ApiParam(value = "机构code", required = true) @RequestParam String code) {
        if (Objects.isNull(code) || Objects.equals(code, "")) {
            throw new BusinessException(ExceptionResultEnum.ORG_CODE_IS_NULL);
        }
        TBOrg tbOrg = (TBOrg) EhcacheUtil.get(SystemConstant.orgCodeCache, code);
        if (Objects.isNull(tbOrg)) {
            QueryWrapper<TBOrg> tbOrgQueryWrapper = new QueryWrapper<>();
            tbOrgQueryWrapper.lambda().eq(TBOrg::getCode, code);
            tbOrg = tbOrgService.getOne(tbOrgQueryWrapper);
            if (Objects.nonNull(tbOrg)) {
                EhcacheUtil.put(SystemConstant.orgCodeCache, code, tbOrg);
            }
        }
        if (Objects.isNull(tbOrg)) {
            throw new BusinessException(ExceptionResultEnum.ORG_NO);
        }
        Map map = new HashMap<>();
        map.put("logo", tbOrg.getLogo());
        return ResultUtil.ok(map);
    }

    @ApiOperation(value = "机构查询接口")
    @RequestMapping(value = "/org/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "机构信息", response = TBOrg.class)})
    public Result query(@ApiParam(value = "机构id", required = false) @RequestParam(required = false) Long id, @ApiParam(value = "机构编码", required = false) @RequestParam(required = false) String code, @ApiParam(value = "机构名称", required = false) @RequestParam(required = false) String name, @ApiParam(value = "是否启用", required = false) @RequestParam(required = false) Integer enable) {
        QueryWrapper<TBOrg> tbOrgQueryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(id)) {
            tbOrgQueryWrapper.lambda().eq(TBOrg::getId, id);
        }
        if (Objects.nonNull(code)) {
            tbOrgQueryWrapper.lambda().eq(TBOrg::getCode, code);
        }
        if (Objects.nonNull(name)) {
            tbOrgQueryWrapper.lambda().like(TBOrg::getName, name);
        }
        if (Objects.nonNull(enable)) {
            tbOrgQueryWrapper.lambda().eq(TBOrg::getEnable, enable);
        }
        List<TBOrg> tbOrgList = tbOrgService.list(tbOrgQueryWrapper);
//        tbOrgList.forEach(s -> {
//            if (Objects.nonNull(s.getLogo()) && !Objects.equals(s.getLogo(), "")) {
//                s.setLogo(systemConfig.getProperty("aliyun.oss.url") + File.separator + s.getLogo());
//            }
//        });
        return ResultUtil.ok(tbOrgList);
    }

    @ApiOperation(value = "角色查询接口")
    @RequestMapping(value = "/role/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "角色信息", response = TBRole.class)})
    public Result roleList() {
        List<TBRole> tbRoleList = (List<TBRole>) EhcacheUtil.get(SystemConstant.roleCache, SystemConstant.roleCache);
        if (Objects.isNull(tbRoleList)) {
            QueryWrapper<TBRole> tbRoleQueryWrapper = new QueryWrapper<>();
            tbRoleQueryWrapper.lambda().notIn(TBRole::getRoleCode, RoleEnum.SUPER_ADMIN.name(), RoleEnum.STUDENT.name());
            tbRoleList = tbRoleService.list(tbRoleQueryWrapper);
            if (Objects.nonNull(tbRoleList)) {
                EhcacheUtil.put(SystemConstant.roleCache, SystemConstant.roleCache, tbRoleList);
            }
        }
        return ResultUtil.ok(tbRoleList);
    }

    @ApiOperation(value = "考试场次查询接口")
    @RequestMapping(value = "/examActivity/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "角色信息", response = TEExamActivity.class)})
    public Result examActivityQuery() {
        return ResultUtil.ok(teExamActivityService.list());
    }

    @ApiOperation(value = "考试批次查询接口")
    @RequestMapping(value = "/exam/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "角色信息", response = TEExamQueryDto.class)})
    public Result examQuery(@ApiParam(value = "用户id", required = false) @RequestParam(required = false) Long userId) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        List<TEExam> teExamList = null;
        if (Objects.nonNull(userId) && !Objects.equals(userId, "")) {
            teExamList = teExamService.examPrivilegeQuery(userId);
        } else {
            QueryWrapper<TEExam> teExamQueryWrapper = new QueryWrapper<>();
            teExamQueryWrapper.lambda().eq(TEExam::getOrgId, tbUser.getOrgId()).orderByDesc(TEExam::getCreateTime);
            teExamList = teExamService.list(teExamQueryWrapper);
        }
        List<TEExamQueryDto> teExamQueryDtoList = null;
        if (Objects.nonNull(teExamList)) {
            Gson gson = new Gson();
            teExamQueryDtoList = gson.fromJson(gson.toJson(teExamList), new TypeToken<List<TEExamQueryDto>>() {
            }.getType());
        }
        return ResultUtil.ok(teExamQueryDtoList);
    }

    @ApiOperation(value = "考场查询接口")
    @RequestMapping(value = "/examRoom/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "角色信息", response = RoomCodeQueryDto.class)})
    public Result examRoomQuery(@ApiParam(value = "考场名称", required = false) @RequestParam(required = false) String roomName) {
        return ResultUtil.ok(teExamStudentService.examRoomQuery(roomName));
    }

    @ApiOperation(value = "根据权限获取场次和考场接口")
    @RequestMapping(value = "/exam/privilegeQuery", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "场次和考场信息", response = Result.class)})
    public Result examPrivilegeQuery(@ApiParam(value = "考试id", required = true) @RequestParam Long examId) {
        if (Objects.isNull(examId) || Objects.equals(examId, "")) {
            throw new BusinessException(ExceptionResultEnum.EXAM_ID_IS_NULL);
        }
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
        if (Objects.isNull(tbSession)) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
        }
        //首先查询当前用户所要监控的roomCode
        QueryWrapper<TBExamInvigilateUser> examInvigilateUserQueryWrapper = new QueryWrapper<>();
        AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
        examInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getOrgId, tbUser.getOrgId())
                .eq(TBExamInvigilateUser::getExamId, examId);
        if (authDto.getRoleCodes().toString().contains(RoleEnum.INVIGILATE.name())) {
            examInvigilateUserQueryWrapper.lambda().eq(TBExamInvigilateUser::getUserId, tbUser.getId());
        }
        List<TBExamInvigilateUser> tbExamInvigilateUserList = tbExamInvigilateUserService.list(examInvigilateUserQueryWrapper);
        Set<String> roomCodeSet = null;
        if (Objects.nonNull(tbExamInvigilateUserList) && tbExamInvigilateUserList.size() > 0) {
            Map<String, TBExamInvigilateUser> tbExamInvigilateUserMap = tbExamInvigilateUserList.stream()
                    .collect(Collectors.toMap(TBExamInvigilateUser::getRoomCode, Function.identity(), (dto1, dto2) -> dto1));
            roomCodeSet = new HashSet<>();
            tbExamInvigilateUserList.clear();
            Set<String> finalRoomCodeSet = roomCodeSet;
            List<TBExamInvigilateUser> finalTbExamInvigilateUserList = tbExamInvigilateUserList;
            tbExamInvigilateUserMap.forEach((k, v) -> {
                finalRoomCodeSet.add(k);
                finalTbExamInvigilateUserList.add(v);
            });
        } else {
            tbExamInvigilateUserList = null;
        }
        List<TEExamActivity> teExamActivityList = null;
        Set<Map> courseSet = null;
        if (Objects.nonNull(roomCodeSet)) {
            //根据roomCode获取当前老师所要监考的全部应考学生数
            QueryWrapper<TEExamStudent> teExamStudentQueryWrapper = new QueryWrapper<>();
            teExamStudentQueryWrapper.lambda().eq(TEExamStudent::getExamId, examId)
                    .in(TEExamStudent::getRoomCode, roomCodeSet);
            List<TEExamStudent> teExamStudentList = teExamStudentService.list(teExamStudentQueryWrapper);
            Set<Long> examActivityIdSet = null;
            if (Objects.nonNull(teExamStudentList) && teExamStudentList.size() > 0) {
                examActivityIdSet = new HashSet<>();
                courseSet = new HashSet<>();
                Set<Long> finalExamActivityIdSet = examActivityIdSet;
                Set<Map> finalCourseSet = courseSet;
                teExamStudentList.forEach(s -> {
                    finalExamActivityIdSet.add(s.getExamActivityId());
                    Map map = new HashMap();
                    map.put("courseCode", s.getCourseCode());
                    map.put("courseName", s.getCourseName());
                    finalCourseSet.add(map);
                });
                teExamActivityList = teExamActivityService.listByIds(examActivityIdSet);
            }
        }
        Map map = new HashMap();
        map.put("examActivitys", teExamActivityList);
        map.put("examRooms", tbExamInvigilateUserList);
        map.put("examCourses", courseSet);
        return ResultUtil.ok(map);
    }

    @ApiOperation(value = "获取播放域接口")
    @RequestMapping(value = "/getPlayUrls", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "播放域接口", response = Result.class)})
    public Result getPlayUrls() {
        return ResultUtil.ok(dictionaryConfig.tencentYunDomain().getUrls());
    }
}
