package com.qmth.teachcloud.report.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.boot.api.annotation.Aac;
import com.qmth.boot.api.annotation.BOOL;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.teachcloud.common.bean.auth.AuthBean;
import com.qmth.teachcloud.common.bean.result.LoginResult;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.RedisUtil;
import com.qmth.teachcloud.common.util.Result;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.report.business.bean.params.LoginParam;
import com.qmth.teachcloud.report.business.bean.result.EditResult;
import com.qmth.teachcloud.report.business.service.ReportCommonService;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Date: 2021/3/30.
 */
@Api(tags = "系统Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.common}")
public class SysController {
    private final static Logger log = LoggerFactory.getLogger(SysController.class);

    @Resource
    private SysUserService sysUserService;

    @Resource
    private BasicVerifyCodeService basicVerifyCodeService;

    @Resource
    private DictionaryConfig dictionaryConfig;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    TBSessionService tbSessionService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    ReportCommonService reportCommonService;

    @Resource
    TBTaskService tbTaskService;

    @Resource
    BasicAttachmentService basicAttachmentService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    SysConfigService sysConfigService;

    /**
     * 登录
     *
     * @param login
     * @return
     */
    @ApiOperation(value = "登录")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = LoginResult.class)})
    @Aac(auth = BOOL.FALSE)
    public Result login(@ApiParam(value = "用户信息", required = true) @Valid @RequestBody LoginParam login, BindingResult bindingResult) throws NoSuchAlgorithmException {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }

        BasicSchool basicSchool = null;
        if (!Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) {
            basicSchool = commonCacheService.schoolCache(login.getSchoolCode());
            if (Objects.isNull(basicSchool)) {
                throw ExceptionResultEnum.SCHOOL_NO_DATA.exception();
            }
            if (Objects.nonNull(basicSchool.getEnable()) && !basicSchool.getEnable()) {
                throw ExceptionResultEnum.SCHOOL_ENABLE.exception();
            }
        }
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SysUser::getLoginName, login.getLoginName());
        if (!Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) {
            wrapper.lambda().eq(SysUser::getSchoolId, basicSchool.getId());
        }
        List<SysUser> userList = sysUserService.list(wrapper);
        //用户不存在
        if (Objects.isNull(userList) || userList.size() == 0) {
            throw ExceptionResultEnum.USER_NO_DATA.exception();
        }
        if (Objects.equals(login.getSchoolCode().toUpperCase(), RoleTypeEnum.ADMIN.name())) {
            userList.forEach(o -> {
                AuthBean authBean = teachcloudCommonService.getUserAuth(o.getId());
                if (Objects.nonNull(authBean) && Objects.nonNull(authBean.getRoleList()) && authBean.getRoleList().size() > 0) {
                    Set<RoleTypeEnum> roleType = authBean.getRoleList().stream().map(s -> s.getType()).collect(Collectors.toSet());
                    if (!roleType.contains(RoleTypeEnum.ADMIN) && !roleType.contains(RoleTypeEnum.CUSTOMER)) {
                        throw ExceptionResultEnum.ERROR.exception("学校代码为admin只允许超级管理员登录");
                    }
                }
            });
        }
        if (userList.size() > 1) {
            throw ExceptionResultEnum.ERROR.exception("查询的用户有多条");
        }
        SysUser sysUser = userList.get(0);
        if (Objects.nonNull(sysUser.getSchoolId()) && sysUser.getSchoolId().longValue() != basicSchool.getId().longValue()) {
            throw ExceptionResultEnum.ERROR.exception("用户学校不匹配");
        }
        //校验验证码
        SysConfig value = sysConfigService.getByKey("sys.code.enable");
        if (Objects.nonNull(value) && value.getConfigValue().equals("true")) {
            String code = login.getCode();
            if (Objects.isNull(code)) {
                throw ExceptionResultEnum.ERROR.exception("验证码为空");
            }
            if (!dictionaryConfig.smsDomain().getSmsNormalCode().equals(code)) {
                QueryWrapper<BasicVerifyCode> codeWrapper = new QueryWrapper<>();
                codeWrapper.lambda().eq(BasicVerifyCode::getMobileNumber, sysUser.getMobileNumber()).eq(BasicVerifyCode::getUserId, sysUser.getId());
                BasicVerifyCode accessControl = basicVerifyCodeService.getOne(codeWrapper);
                if (accessControl == null || (accessControl != null && !accessControl.getVerifyCode().equals(code))) {
                    throw ExceptionResultEnum.ERROR.exception("短信验证码错误，请仔细核对后再次输入");
                }

                if (new Date(accessControl.getExpireTime()).before(new Date())) {
                    throw ExceptionResultEnum.ERROR.exception("短信验证码已过期");
                }
            }
        }
        return ResultUtil.ok(teachcloudCommonService.login(login.getPassword(), sysUser, AppSourceEnum.SYSTEM));
    }

    /**
     * 登出
     *
     * @return
     */
    @ApiOperation(value = "登出")
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)})
    public Result logout() {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
        AuthBean authBean = commonCacheService.userAuthCache(sysUser.getId());
        if (Objects.isNull(authBean)) {
            throw ExceptionResultEnum.NOT_LOGIN.exception();
        }
        tbSessionService.removeById(tbSession.getId());
        redisUtil.deleteUserSession(tbSession.getId());
        commonCacheService.removeUserCache(sysUser.getId());
        commonCacheService.removeUserAuthCache(sysUser.getId());
        commonCacheService.removeUserMenuCache(sysUser.getId());
        commonCacheService.removeUserRolePrivilegeCache(sysUser.getId());
        return ResultUtil.ok(new EditResult(sysUser.getId()));
    }

    /**
     * 发送验证码
     *
     * @param loginParam
     * @return
     */
    @ApiOperation(value = "发送验证码")
    @RequestMapping(value = "/get_verify_code", method = RequestMethod.POST)
    @Aac(auth = BOOL.FALSE)
    public Object getverifyCode(@RequestBody LoginParam loginParam) {
        String loginName = loginParam.getLoginName();
        String password = loginParam.getPassword();
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(loginParam.getSchoolCode())) {
            BasicSchool basicSchool = commonCacheService.schoolCache(loginParam.getSchoolCode());
            wrapper.lambda().eq(SysUser::getSchoolId, basicSchool.getId());
        }
        wrapper.lambda().eq(SysUser::getLoginName, loginName);
        SysUser user = sysUserService.getOne(wrapper);
        //用户不存在
        if (Objects.isNull(user)) {
            throw ExceptionResultEnum.ERROR.exception("用户不存在");
        }
        if (!password.equals(user.getPassword())) {
            throw ExceptionResultEnum.ERROR.exception("密码错误");
        }
        String mobileNumber = user.getMobileNumber();
        if (Objects.isNull(mobileNumber)) {
            throw ExceptionResultEnum.ERROR.exception("用户未绑定手机号码");
        }
        basicVerifyCodeService.sendVeirfyCode(mobileNumber, user);
        return ResultUtil.ok(mobileNumber, "");
    }

    @ApiOperation(value = "根据机构代码查询机构信息接口")
    @RequestMapping(value = "/school/query_by_school_code", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "学校信息", response = EditResult.class)})
    @Aac(auth = BOOL.FALSE)
    public Result queryBySchoolCode(@ApiParam(value = "机构code", required = true) @RequestParam String code) {
        if (Objects.nonNull(code) && code.contains("#")) {
            code = code.substring(0, code.indexOf("#"));
        }
        if (!Objects.equals(code.toUpperCase(), RoleTypeEnum.ADMIN.name())) {
            BasicSchool basicSchool = commonCacheService.schoolCache(code);
            if (Objects.isNull(basicSchool)) {
                throw ExceptionResultEnum.SCHOOL_NO_DATA.exception();
            }
            Map<String, String> map = new HashMap<>();
            map.put(SystemConstant.LOGO, basicSchool.getLogo());
            map.put("name", basicSchool.getName());
            return ResultUtil.ok(map);
        } else {
            Map<String, String> map = new HashMap<>();
            map.put(SystemConstant.LOGO, dictionaryConfig.sysDomain().getAdminLogoUrl());
            map.put("name", null);
            return ResultUtil.ok(map);
        }
    }

    @ApiOperation(value = "文件上传接口")
    @RequestMapping(value = "/file/upload", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)})
    public Result fileUpload(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
                             @ApiParam(value = "上传文件类型", required = true) @RequestParam UploadFileEnum type) {
        BasicAttachment basicAttachment = null;
        try {
            basicAttachment = reportCommonService.saveAttachment(file, ServletUtil.getRequestMd5(), type);
            if (Objects.isNull(basicAttachment)) {
                throw ExceptionResultEnum.ATTACHMENT_ERROR.exception();
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (Objects.nonNull(basicAttachment)) {
                basicAttachmentService.deleteAttachment(basicAttachment);
            }
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }

        return ResultUtil.ok(new EditResult(basicAttachment.getId(), teachcloudCommonService.filePreview(basicAttachment.getPath()), basicAttachment.getPages()));
    }

    @ApiOperation(value = "文件下载接口")
    @RequestMapping(value = "/file/download", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)})
    public Result fileDownload(@ApiParam(value = "任务id", required = true) @RequestParam String id,
                               @ApiParam(value = "下载文件类型", required = true) @RequestParam DownloadFileEnum type) {
        TBTask tbTask = tbTaskService.getById(Long.parseLong(id));
        if (Objects.isNull(tbTask)) {
            throw ExceptionResultEnum.TASK_NO_DATA.exception();
        }
        String path = null;
        switch (type.ordinal()) {
            case 0:
                path = tbTask.getImportFilePath();
                break;
            case 1:
                path = tbTask.getReportFilePath();
                break;
            default:
                path = tbTask.getResultFilePath();
                break;
        }
        if (Objects.isNull(path)) {
            throw ExceptionResultEnum.PATH_NO_DATA.exception();
        }
        return ResultUtil.ok(new EditResult(teachcloudCommonService.filePreview(path)));
    }

    @ApiOperation(value = "文件预览接口")
    @RequestMapping(value = "/file/preview", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = EditResult.class)})
    public Result filePreview(@ApiParam(value = "附件id", required = false, defaultValue = "") @RequestParam(value = "id", required = false, defaultValue = "") String id) {
        if (StringUtils.isBlank(id)) {
            throw ExceptionResultEnum.ERROR.exception("没有附件");
        } else {
            BasicAttachment basicAttachment = basicAttachmentService.getById(Long.parseLong(id));
            return ResultUtil.ok(new EditResult(teachcloudCommonService.filePreview(basicAttachment.getPath())));
        }
    }

    @ApiOperation(value = "查询用户权限")
    @RequestMapping(value = "/get_menu", method = RequestMethod.POST)
    public Result getMenu() {
        return ResultUtil.ok(sysUserRoleService.listByUserId());
    }

    @ApiOperation(value = "获取服务器时间")
    @RequestMapping(value = "/get_system_time", method = RequestMethod.POST)
    @Aac(auth = BOOL.FALSE)
    public Result getSystemTime() {
        return ResultUtil.ok(System.currentTimeMillis());
    }
}
