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.teachcloud.common.SignatureEntityTest;
import com.qmth.teachcloud.common.bean.dto.UserAuthenticationDto;
import com.qmth.teachcloud.common.bean.result.LoginResult;
import com.qmth.teachcloud.common.cache.ThirdUserAuthCacheUtil;
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.AppSourceEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.RoleTypeEnum;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.*;
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.annotation.Validated;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 教研分析单点登录前端控制器
 * </p>
 *
 * @author wangliang
 * @since 2022-04-26
 */
@Api(tags = "教研分析单点登录接口Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.sso}")
@Validated
public class SsoApiController {
    private final static Logger log = LoggerFactory.getLogger(SsoApiController.class);

    @Resource
    DictionaryConfig dictionaryConfig;

    @Resource
    SysUserService sysUserService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    SysOrgService sysOrgService;

    @Resource
    SysRoleService sysRoleService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    ReportCommonService reportCommonService;

    @ApiOperation(value = "单点登录接口")
    @ApiResponses({@ApiResponse(code = 200, message = "单点登录接口", response = Object.class)})
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @Aac(auth = BOOL.FALSE)
    @Transactional
    public void login(@ApiParam(value = "登录名", required = true) @RequestParam String loginName,
                      @ApiParam(value = "角色", required = true) @RequestParam RoleTypeEnum role,
                      @ApiParam(value = "学院名称", required = true) @RequestParam String orgName,
                      @ApiParam(value = "真实名", required = false) @RequestParam(required = false) String realName,
                      @ApiParam(value = "手机号码", required = false) @RequestParam(required = false) String mobileNumber,
                      @ApiParam(value = "是否启用", required = false) @RequestParam(required = false) Boolean enable,
                      @ApiParam(value = "返回url", required = true) @RequestParam String returnUrl,
                      @ApiParam(value = "时间戳", required = true) @RequestParam Long time,
                      @ApiParam(value = "鉴权", required = true) @RequestParam String authorization) throws IOException {
        BasicSchool basicSchool = AuthThirdUtil.hasPermission(time, authorization);
        //插入或者更新用户
        //查询用户是否存在
        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
        sysUserQueryWrapper.lambda().eq(SysUser::getSchoolId, basicSchool.getId())
                .eq(SysUser::getLoginName, loginName)
                .eq(SysUser::getEnable, true);
        SysUser sysUser = sysUserService.getOne(sysUserQueryWrapper);
        if (Objects.isNull(sysUser)) {//新增
            sysUser = new SysUser(basicSchool.getId(),
                    loginName,
                    Objects.nonNull(realName) ? realName : loginName,
                    Objects.nonNull(mobileNumber) ? mobileNumber : null, enable);
        } else {
            sysUser.setSchoolId(basicSchool.getId());
            if (Objects.nonNull(realName)) {
                sysUser.setRealName(realName);
            }
            if (Objects.nonNull(mobileNumber)) {
                sysUser.setMobileNumber(mobileNumber);
            }
            if (Objects.nonNull(enable)) {
                sysUser.setEnable(enable);
            }
        }

        //查询学院id
        QueryWrapper<SysOrg> sysOrgQueryWrapper = new QueryWrapper<>();
        sysOrgQueryWrapper.lambda().eq(SysOrg::getSchoolId, basicSchool.getId())
                .eq(SysOrg::getName, orgName)
                .eq(SysOrg::getEnable, true);
        SysOrg sysOrg = sysOrgService.getOne(sysOrgQueryWrapper);
        Optional.ofNullable(sysOrg).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("学院数据为空"));
        sysUser.setOrgId(sysOrg.getId());
        sysUserService.saveOrUpdate(sysUser);

        //新增用户和角色关系
        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        sysRoleQueryWrapper.lambda().eq(SysRole::getType, role)
                .eq(SysRole::getEnable, true);
        SysRole sysRole = sysRoleService.getOne(sysRoleQueryWrapper);
        Optional.ofNullable(sysRole).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("角色数据为空"));

        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.lambda().eq(SysUserRole::getUserId, sysUser.getId());
        int count = sysUserRoleService.count(sysUserRoleQueryWrapper);
        if (count > 0) {
            sysUserRoleService.remove(sysUserRoleQueryWrapper);
        }
        SysUserRole sysUserRole = new SysUserRole(sysUser.getId(), sysRole.getId());
        sysUserRoleService.save(sysUserRole);

        UserAuthenticationDto userAuthenticationDto = new UserAuthenticationDto(String.valueOf(sysUser.getId()), SystemConstant.getUuid());
        ThirdUserAuthCacheUtil.setAuthCode(userAuthenticationDto);
        String pattern = "{0}{1}{2}";
        String code = URLEncoder.encode(MessageFormat.format(pattern, userAuthenticationDto.getUid(), SignatureEntityTest.FIELD_JOINER, SignatureEntityTest.encrypt(userAuthenticationDto.getCode())), SystemConstant.CHARSET_NAME);
        ThirdUserAuthCacheUtil.setAuthReturnUrl(String.valueOf(sysUser.getId()), returnUrl);

        HttpServletResponse response = ServletUtil.getResponse();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.sendRedirect(dictionaryConfig.sysDomain().getLoginAuthenUrl() + code + "/" + AppSourceEnum.PRINT_THIRD);
    }

    @ApiOperation(value = "用户临时授权登录接口")
    @RequestMapping(value = "/user/authentication/login", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = LoginResult.class)})
    @Aac(auth = BOOL.FALSE)
    public Result login(@ApiParam(value = "授权码信息", required = true) @RequestParam String code,
                        @ApiParam(value = "应用来源", required = true) @RequestParam AppSourceEnum appSource) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        String[] values = StringUtils.split(URLDecoder.decode(code, SystemConstant.CHARSET_NAME), SignatureEntityTest.FIELD_JOINER);
        if (Objects.isNull(values) || values.length != 2) {
            throw ExceptionResultEnum.ERROR.exception("临时授权码出错，请重新获取");
        }
        log.info("values:{}", JacksonUtil.parseJson(values));
        SysUser sysUser = sysUserService.getById(Long.parseLong(values[0]));
        //用户不存在
        if (Objects.isNull(sysUser)) {
            throw ExceptionResultEnum.USER_NO_DATA.exception();
        }
        //停用
        if (!sysUser.getEnable()) {
            throw ExceptionResultEnum.USER_ENABLE.exception();
        }

        String userAuthCode = ThirdUserAuthCacheUtil.getAuthCode(values[0]);
        if (Objects.isNull(userAuthCode) || !Objects.equals(values[1], URLDecoder.decode(SignatureEntityTest.encrypt(userAuthCode), SystemConstant.CHARSET_NAME))) {
            throw ExceptionResultEnum.ERROR.exception("临时授权码已过期");
        }
        LoginResult loginResult = teachcloudCommonService.login(sysUser.getPassword(), sysUser, appSource);
        loginResult.setReturnUrl(ThirdUserAuthCacheUtil.getAuthReturnUrl(String.valueOf(sysUser.getId())));
        ThirdUserAuthCacheUtil.deleteAuthCode(values[0]);
        ThirdUserAuthCacheUtil.deleteCache(sysUser.getId());
        return ResultUtil.ok(loginResult);
    }

    @ApiOperation(value = "用户鉴权退出接口")
    @RequestMapping(value = "/user/authentication/logout", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = Result.class)})
    @Aac(auth = BOOL.FALSE)
    public void logout(@ApiParam(value = "时间戳", required = true) @RequestParam Long time,
                       @ApiParam(value = "鉴权", required = true) @RequestParam String authorization) throws IOException {
        TBSession tbSession = AuthThirdUtil.hasPermissionLogout(time, authorization);
        reportCommonService.thirdLogout(tbSession);
    }
}
