package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.boot.tools.signature.SignatureEntity;
import com.qmth.boot.tools.signature.SignatureType;
import com.qmth.distributed.print.business.service.SsoService;
import com.qmth.teachcloud.common.bean.params.OpenParams;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.OrgTypeEnum;
import com.qmth.teachcloud.common.enums.RoleTypeEnum;
import com.qmth.teachcloud.common.enums.userPush.SpecialPrivilegeEnum;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.sync.CloudMarkingTaskUtils;
import com.qmth.teachcloud.common.util.JacksonUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Date: 2021/5/20.
 */
@Service
public class SsoServiceImpl implements SsoService {
    private final static Logger log = LoggerFactory.getLogger(SsoServiceImpl.class);

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    CloudMarkingTaskUtils stmmsUtils;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    SysOrgService sysOrgService;

    @Resource
    SysRoleService sysRoleService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Override
    public Map<String, Object> markerLoginInfo() {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            SpecialPrivilegeEnum userSpecialPrivilege = sysUserService.findUserSpecialPrivilegeByUserId(sysUser.getId(), sysUser.getSchoolId());
            if (SpecialPrivilegeEnum.UNIDENTIFIED.equals(userSpecialPrivilege)
                    || SpecialPrivilegeEnum.SUBJECT_HEADER.equals(userSpecialPrivilege)) {
                throw ExceptionResultEnum.ERROR.exception("该用户没有评卷员角色，无法登录");
            }
            // 顶级机构
            SysOrg rootOrg = sysOrgService.findRootOrg(sysUser.getSchoolId());
            List<SysOrg> sysOrgList = sysOrgService.findByConnectByParentId(sysUser.getOrgId(), false, false);
            if(sysOrgList.isEmpty()){
                throw ExceptionResultEnum.ERROR.exception(String.format("未找到用户账号[%s]所属机构及上级机构", sysUser.getLoginName()));
            }
            SysOrg collegeOrg = sysOrgList.stream().filter(m->m.getParentId().equals(rootOrg.getId())).findFirst().orElseGet(null);
            if(collegeOrg == null){
                throw ExceptionResultEnum.ERROR.exception(String.format("未找到用户账号[%s]所属学院", sysUser.getLoginName()));
            }
            return stmmsUtils.markLogin(sysUser, collegeOrg.getCode());
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    @Override
    public Map<String, Object> markerLeaderLoginInfo() {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            SpecialPrivilegeEnum userSpecialPrivilege = sysUserService.findUserSpecialPrivilegeByUserId(sysUser.getId(), sysUser.getSchoolId());
            if (SpecialPrivilegeEnum.UNIDENTIFIED.equals(userSpecialPrivilege)
                    || SpecialPrivilegeEnum.MARKER.equals(userSpecialPrivilege)) {
                throw ExceptionResultEnum.ERROR.exception("该用户没有科组长角色，无法登录");
            }
            // 顶级机构
            SysOrg rootOrg = sysOrgService.findRootOrg(sysUser.getSchoolId());
            List<SysOrg> sysOrgList = sysOrgService.findByConnectByParentId(sysUser.getOrgId(), false, false);
            if(sysOrgList.isEmpty()){
                throw ExceptionResultEnum.ERROR.exception(String.format("未找到用户账号[%s]所属机构及上级机构", sysUser.getLoginName()));
            }
            SysOrg collegeOrg = sysOrgList.stream().filter(m->m.getParentId().equals(rootOrg.getId())).findFirst().orElseGet(null);
            if(collegeOrg == null){
                throw ExceptionResultEnum.ERROR.exception(String.format("未找到用户账号[%s]所属学院", sysUser.getLoginName()));
            }
            return stmmsUtils.markLeaderLogin(sysUser, collegeOrg.getCode());
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 教研分析单点登录
     *
     * @param loginName
     * @param role
     * @param orgName
     * @param realName
     * @param mobileNumber
     * @param enable
     * @param returnUrl
     * @return
     * @throws IOException
     */
    @Override
    public Map<String, Object> analysisLogin(String loginName, RoleTypeEnum role, String orgName, String realName, String mobileNumber, Boolean enable, String returnUrl) throws IOException {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        BasicSchool basicSchool = commonCacheService.schoolCache(sysUser.getSchoolId());

        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
        sysUserQueryWrapper.lambda().eq(SysUser::getLoginName, loginName)
                .eq(SysUser::getSchoolId, basicSchool.getId());
        SysUser sysUserCas = sysUserService.getOne(sysUserQueryWrapper);
        Optional.ofNullable(sysUserCas).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("用户信息为空"));

        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        sysRoleQueryWrapper.lambda().eq(SysRole::getType, role);
        SysRole sysRole = sysRoleService.getOne(sysRoleQueryWrapper);
        Optional.ofNullable(sysRole).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("角色信息为空"));

        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.lambda().eq(SysUserRole::getUserId, sysUserCas.getId())
                .eq(SysUserRole::getRoleId, sysRole.getId());
        SysUserRole sysUserRole = sysUserRoleService.getOne(sysUserRoleQueryWrapper);
        Optional.ofNullable(sysUserRole).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("用户没有该角色"));

        if (role == RoleTypeEnum.PRESIDENT || role == RoleTypeEnum.TEACHER) {
//            List<SysOrg> sysOrgList = sysOrgService.findByConnectByParentId(sysUserCas.getOrgId(), false, true);
            SysOrg sysOrg = sysOrgService.findCollegeLevelOrgByOrgId(sysUserCas.getOrgId());
//            if (CollectionUtils.isEmpty(sysOrgList)) {
//                throw ExceptionResultEnum.ERROR.exception("未找到学院信息");
//            } else {
//                List<SysOrg> sysOrgSchool = sysOrgList.stream().filter(s -> s.getType() == OrgTypeEnum.SCHOOL).collect(Collectors.toList());
//                if (!CollectionUtils.isEmpty(sysOrgSchool)) {
//                    for (SysOrg s : sysOrgList) {
//                        if (Objects.nonNull(s.getParentId()) && s.getParentId().longValue() == sysOrgSchool.get(0).getId().longValue()) {
//                            orgName = s.getName();
//                            break;
//                        }
//                    }
//                } else {
//                    throw ExceptionResultEnum.ERROR.exception("未找到顶级学校信息");
//                }
//            }
            if (Objects.isNull(sysOrg)) {
                throw ExceptionResultEnum.ERROR.exception("未找到顶级机构");
            }
        } else if (role == RoleTypeEnum.OFFICE_TEACHER && Objects.nonNull(sysUserCas.getOrgId())) {
            SysOrg sysOrg = commonCacheService.orgCache(sysUserCas.getOrgId());
            if (Objects.isNull(sysOrg)) {
                throw ExceptionResultEnum.ERROR.exception("未找到学校信息");
            } else if (Objects.nonNull(sysOrg) && sysOrg.getType() != OrgTypeEnum.SCHOOL) {
                throw ExceptionResultEnum.ERROR.exception("教务处老师应放在顶级机构");
            }
            orgName = sysOrg.getName();
        }

        Map<String, Object> map = new HashMap<>();
        map.computeIfAbsent("loginName", v -> loginName);
        map.computeIfAbsent("role", v -> role);
        map.put("orgName", orgName);
        map.computeIfAbsent("realName", v -> realName);
        map.computeIfAbsent("mobileNumber", v -> mobileNumber);
        map.computeIfAbsent("returnUrl", v -> returnUrl);

        Long timestamp = System.currentTimeMillis();
        String accessToken = SignatureEntity.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.TEACHCLOUD_REPORT_SSO_LOGIN_API, timestamp, basicSchool.getAccessKey(), basicSchool.getAccessSecret());
        map.computeIfAbsent("time", v -> timestamp);
        map.computeIfAbsent("authorization", v -> accessToken);

        SysConfig sysConfig = commonCacheService.addSysConfigCache(basicSchool.getId(), SystemConstant.TEACHCLOUD_REPORT_HOST_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未配置教研分析地址"));
        String hostUrl = sysConfig.getConfigValue();

        hostUrl = SystemConstant.getLocalFileHost(hostUrl);
        map.put("redirectUrl", hostUrl + SystemConstant.TEACHCLOUD_REPORT_SSO_LOGIN_API);
        System.out.println(JSON.toJSONString(map));
        return map;
    }

    /**
     * 题库单点登录
     *
     * @param loginName
     * @param role
     * @param returnUrl
     * @param params
     * @return
     * @throws IOException
     */
    @Override
    public Map<String, Object> questionLibraryLogin(String loginName, String realName, RoleTypeEnum role, String returnUrl, String params) throws IOException {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        BasicSchool basicSchool = commonCacheService.schoolCache(sysUser.getSchoolId());

        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
        sysUserQueryWrapper.lambda().eq(SysUser::getLoginName, loginName)
                .eq(SysUser::getSchoolId, basicSchool.getId());
        SysUser sysUserCas = sysUserService.getOne(sysUserQueryWrapper);
        Optional.ofNullable(sysUserCas).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("用户信息为空"));

        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        sysRoleQueryWrapper.lambda().eq(SysRole::getType, role);
        SysRole sysRole = sysRoleService.getOne(sysRoleQueryWrapper);
        Optional.ofNullable(sysRole).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("角色信息为空"));

        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.lambda().eq(SysUserRole::getUserId, sysUserCas.getId())
                .eq(SysUserRole::getRoleId, sysRole.getId());
        SysUserRole sysUserRole = sysUserRoleService.getOne(sysUserRoleQueryWrapper);
        Optional.ofNullable(sysUserRole).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("用户没有该角色"));

        long timestamp = System.currentTimeMillis();
        SysConfig sysConfig = commonCacheService.addSysConfigCache(basicSchool.getId(), SystemConstant.QUESTION_HOST_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未配置题库地址"));
        String questionLoginUrl = sysConfig.getConfigValue();
        if (questionLoginUrl.contains(SystemConstant.PATH_MATCH)) {
            questionLoginUrl = questionLoginUrl.replace(SystemConstant.PATH_MATCH, basicSchool.getCode());
        }
        questionLoginUrl = questionLoginUrl + SystemConstant.QUESTION_CAS_ADMIN_LOGIN_OPEN_API;
        String path = SystemConstant.QUESTION_CAS_ADMIN_LOGIN_OPEN_API;
        String signature = SignatureEntity.build(SignatureType.SECRET, SystemConstant.GET, path, timestamp, basicSchool.getAccessKey(), basicSchool.getAccessSecret());
        signature = URLEncoder.encode(signature, SystemConstant.CHARSET_NAME);

        StringJoiner stringJoiner = new StringJoiner("")
                .add(questionLoginUrl)
                .add(SystemConstant.GET_UNKNOWN).add(SystemConstant.HEADER_TIME).add(SystemConstant.GET_EQUAL).add(String.valueOf(timestamp))
                .add(SystemConstant.GET_SYMBOL).add(SystemConstant.SIGNATURE).add(SystemConstant.GET_EQUAL).add(signature)
                .add(SystemConstant.GET_SYMBOL).add(SystemConstant.USER).add(SystemConstant.GET_EQUAL).add(loginName);

        if (Objects.nonNull(returnUrl) && !Objects.equals(returnUrl, "")) {
            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.RETURN_URL).add(SystemConstant.GET_EQUAL).add(returnUrl);
        }

        Map<String, Object> map = new HashMap<>();
        if (Objects.nonNull(params) && !Objects.equals(params, "")) {
            OpenParams openParams = JacksonUtil.readJson(params, OpenParams.class);
            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.PARAMS).add(SystemConstant.GET_EQUAL).add(JacksonUtil.parseJson(openParams));
            map.computeIfAbsent(SystemConstant.PARAMS, v -> JacksonUtil.parseJson(openParams));
        }
        map.computeIfAbsent("loginName", v -> loginName);
        map.computeIfAbsent("realName", v -> realName);
        map.computeIfAbsent("role", v -> role);
        map.computeIfAbsent("returnUrl", v -> returnUrl);
        map.put("redirectUrl", stringJoiner.toString());
        return map;
    }
}
