package com.chinaweal.aiccs.door.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.aiccs.aiccs.business.entity.TSTaskList;
import com.chinaweal.aiccs.common.util.ConstantsUtil;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.door.dto.XCRoleDTO;
import com.chinaweal.aiccs.door.dto.XCUserRoleDTO;
import com.chinaweal.aiccs.door.entity.TUserportal;
import com.chinaweal.aiccs.door.mapper.TUserportalMapper;
import com.chinaweal.aiccs.door.service.ITUserportalService;
import com.chinaweal.aiccs.org.entity.TUsermenu;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.TUsermenuService;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aiccs.org.service.UserBaseService;
import com.chinaweal.aiccs.outside.api.DoorApi;
import com.chinaweal.aiccs.outside.api.LangChaoDoorApi;
import com.chinaweal.aiccs.outside.api.XCDoorApi;
import com.chinaweal.aiccs.outside.dto.LangChaoTokenDto;
import com.chinaweal.aiccs.outside.util.DoorResult;
import com.chinaweal.aiccs.outside.util.GzcssTokenUtils;
import com.chinaweal.aiccs.redis.RedisService;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.aicorg.services.OrgUM;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.dtflys.forest.http.ForestResponse;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 信创门户信息数据表 服务实现类
 * </p>
 *
 * @author chinaweal
 * @since 2022-01-25
 */
@Service
@Slf4j
public class TUserportalServiceImpl extends ServiceImpl<TUserportalMapper, TUserportal> implements ITUserportalService {

    @Value("${door.enableTask}")
    private boolean enableTask;
    @Value("${door.redirectUrl}")
    private String redirectUrl;
    @Value("${xcDoor.enableTask}")
    private boolean enableTask_XC;
    @Value("${xcDoor.redirectUrl}")
    private String redirectUrl_XC;

    @Resource
    private UserBaseService userBaseService;
    @Resource
    private OrgUM orgUM;
    @Resource
    private TUsersService tUsersService;
    @Resource
    private DoorApi doorApi;
    @Resource
    private XCDoorApi xcDoorApi;
    @Resource
    private LangChaoDoorApi langChaoDoorApi;
    @Resource
    private TUsermenuService userMenuService;
    @Resource
    private RedisService redisService;
    @Resource
    private TUserportalMapper tUserportalMapper;

    @Override
    public AICUser casLogin(String ticket, String service) throws DocumentException {
        //1.获取cas的用户信息
        String xml = xcDoorApi.casServiceValidate(service, ticket);
        Document document = DocumentHelper.parseText(xml);
        Element rootElement = document.getRootElement();
        String doorUsername = rootElement.element("authenticationSuccess").element("user").getStringValue();

        //2.查询用户信息
        LambdaQueryWrapper<TUserportal> lqw = Wrappers.lambdaQuery();
        lqw.eq(TUserportal::getUsername, doorUsername);
        TUserportal tUserportal = getOne(lqw);

        //3.判断门户的用户是否存在
        if (tUserportal == null || StringUtils.isBlank(tUserportal.getLocaluserid())) {
            throw new BusinessException("信创门户单点登录失败: " + doorUsername + "。无法找到用户数据，请联系管理员！");
        }

        //4.登陆
        AICUser aicUser = orgUM.findUserByPrimaryKey(tUserportal.getLocaluserid());
        RestResult<AICUser> loginResult = userBaseService.login(aicUser.getEname(), "Hn9U-)gDqM");

        return loginResult.getData();
    }

    @Override
    @Transactional(value = "aicorgTransactionManager", rollbackFor = Exception.class)
    public AICUser casLogin_Unite(String ticket, String service) {
        //1.获取cas的用户信息
        ForestResponse<String> forestResponse = doorApi.casServiceValidate_Unite(service, ticket);
        if (!forestResponse.isSuccess()) {
            log.error("cas单点登录票据校验接口调用失败, status: {}", forestResponse.getStatusCode(), forestResponse.getException());
            throw new BusinessException(ResultCode.INTERFACE_OUTER_INVOKE_ERROR);
        }

        Map<String, String> resultMap = GzcssTokenUtils.parseCasXmlInfo(forestResponse.getResult());

        if ("0".equals(resultMap.get("code"))) {
            log.error("cas单点登录票据校验接口调用结果, status: {}", forestResponse.getStatusCode(), forestResponse.getException());
            throw new BusinessException("cas单点登录票据校验接口调用失败: " + resultMap.get("data"));
        }

        //2.查询用户信息
        LambdaQueryWrapper<TUserportal> lqw = Wrappers.lambdaQuery();
        lqw.eq(TUserportal::getUsername, resultMap.get("data"));
        TUserportal tUserportal = getOne(lqw);

        //3.判断门户的用户是否存在
        if (tUserportal == null || StringUtils.isBlank(tUserportal.getLocaluserid())) {
            throw new BusinessException("统一门户单点登录失败: " + resultMap.get("data") + "。无法找到用户数据，请联系管理员！");
        }

        //4.登陆
        AICUser aicUser = orgUM.findUserByPrimaryKey(tUserportal.getLocaluserid());
        RestResult<AICUser> loginResult = userBaseService.login(aicUser.getEname(), "Hn9U-)gDqM");

        return loginResult.getData();
    }


    @Override
    public void saveUserByPortal(TUserportal tUserportalDto) {
        TUserportal tUserportal = this.getById(tUserportalDto.getId());
        if (tUserportal == null) {
            tUserportal = new TUserportal();
            BeanUtil.copyProperties(tUserportalDto, tUserportal);
        } else {
            // 判断手机号是否修改
            if (!Objects.equals(tUserportalDto.getPhone(), tUserportal.getPhone())) {
                tUserportal.setLocaluserid(null);
            }
            tUserportal.setPhone(tUserportalDto.getPhone());
            tUserportal.setUsername(tUserportalDto.getUsername());
            tUserportal.setRealname(tUserportalDto.getRealname());
        }

        // 关联t_user表 不新增本地用户（原因:机构、部门数据无法匹配），根据手机号码匹配
        if (StringUtils.isBlank(tUserportal.getLocaluserid())) {
            TUsers tUsers = tUsersService.selectTusersByUsername(tUserportalDto.getPhone());
            if (tUsers != null && !"1".equals(tUsers.getDeleted())) {
                tUserportal.setLocaluserid(tUsers.getUserid());
            } else {
                log.info("来自信创用户无法匹配t_user表用户");
            }
        } else {
            TUsers tUsers = tUsersService.selectTusersByUsername(tUserportalDto.getPhone());
            tUsers.setRealname(tUserportal.getRealname());
            tUsersService.updateById(tUsers);
        }
        saveOrUpdate(tUserportal);
    }

    @Override
    public TUserportal getByLocalUserId(String userId) {
        return this.lambdaQuery().eq(TUserportal::getLocaluserid, userId).one();
    }

    @Override
    public void doorTaskSend(TSTaskList taskListModel) {
        if (!enableTask) return;

        TUserportal tUserportal = getByLocalUserId(taskListModel.getSenderuserid());

        if (tUserportal != null) {
            doorApi.tasksSend(GzcssTokenUtils.getDoorTask(taskListModel.getTasklistid(),
                    taskListModel.getBusname(),
                    taskListModel.getLinkname(),
                    tUserportal.getId(),
                    tUserportal.getId(),
                    redirectUrl,
                    false));
        }

    }

    @Override
    public void doorTaskSend_XC(TSTaskList taskListModel) {
        if (!enableTask_XC) return;

        TUserportal tUserportal = getByLocalUserId(taskListModel.getSenderuserid());

        if (tUserportal != null) {
            xcDoorApi.tasksSend(GzcssTokenUtils.getDoorTask_XC(taskListModel.getTasklistid(),
                    taskListModel.getBusname(),
                    taskListModel.getLinkname(),
                    tUserportal.getId(),
                    tUserportal.getId(),
                    redirectUrl_XC,
                    false));
        }

    }

    @Override
    public void doorTaskSendUpdate(TSTaskList taskListModel, boolean isEnd) {
        if (!enableTask) return;

        TUserportal sender = getByLocalUserId(taskListModel.getSenderuserid());
        TUserportal signer = getByLocalUserId(taskListModel.getSignuserid());

        if (sender != null && signer != null) {
            doorApi.tasksSendUpdate(GzcssTokenUtils.getDoorTask(taskListModel.getTasklistid(),
                    taskListModel.getBusname(),
                    taskListModel.getLinkname(),
                    sender.getId(),
                    signer.getId(),
                    redirectUrl,
                    isEnd));
        }

    }

    @Override
    public void doorTaskSendUpdate_XC(TSTaskList taskListModel, boolean isEnd) {
        if (!enableTask_XC) return;

        TUserportal sender = getByLocalUserId(taskListModel.getSenderuserid());
        TUserportal signer = getByLocalUserId(taskListModel.getSignuserid());

        if (sender != null && signer != null) {
            xcDoorApi.tasksSendUpdate(GzcssTokenUtils.getDoorTask_XC(taskListModel.getTasklistid(),
                    taskListModel.getBusname(),
                    taskListModel.getLinkname(),
                    sender.getId(),
                    signer.getId(),
                    redirectUrl_XC,
                    isEnd));
        }
    }

    @Override
    public void saveUserRole(XCUserRoleDTO xcUserRoleDTO, TUserportal tUserportal) {

        if (tUserportal == null) {
            tUserportal = this.getById(xcUserRoleDTO.getUserId());
        }

        if (tUserportal == null || StringUtils.isBlank(tUserportal.getLocaluserid())) {
            throw new BusinessException("用户不存在或没有找到本地相关联用户。 id：" + xcUserRoleDTO.getUserId());
        }

        ForestResponse<DoorResult<XCRoleDTO>> forestResponse = xcDoorApi.queryRoleById(xcUserRoleDTO.getRoleId());

        if (forestResponse.isSuccess()) {
            DoorResult<XCRoleDTO> doorResult = forestResponse.getResult();

            if (doorResult.isQuerySuccess()) {

                XCRoleDTO roleDTO = doorResult.getResult();

                if (StringUtils.isBlank(roleDTO.getDescription())) {
                    throw new BusinessException("没有找到sys_menu主键。 roleName：" + roleDTO.getRoleName());
                }

                Optional<TUsermenu> userMenuOpt = userMenuService.lambdaQuery()
                        .eq(TUsermenu::getUserID, tUserportal.getLocaluserid())
                        .eq(TUsermenu::getSysMenuID, roleDTO.getDescription()).oneOpt();

                // 没有数据更新插入数据
                if (!userMenuOpt.isPresent()) {
                    userMenuService.save(new TUsermenu()
                            .setUserID(tUserportal.getLocaluserid())
                            .setSysMenuID(roleDTO.getDescription())
                            .setMenuStatus("1"));
                }
            }

        }

    }

    @Override
    @Transactional(value = "aicorgTransactionManager", rollbackFor = Exception.class)
    public AICUser casLogin_LangChao(String code, String service) {
        //1.获取cas的用户信息
        ForestResponse<LangChaoTokenDto> forestResponse = langChaoDoorApi.getToken(code, "authorization_code", "zwtxyjg", "8dkj1ws7", URLUtil.encode(service));
        if (!forestResponse.isSuccess()) {
            log.error("浪潮OAuth2.0单点登录接口调用失败, status: {}", forestResponse.getStatusCode(), forestResponse.getException());
            throw new BusinessException(ResultCode.INTERFACE_OUTER_INVOKE_ERROR);
        }

        LangChaoTokenDto langChaoTokenDto = forestResponse.getResult();

        //2.查询用户信息
        LambdaQueryWrapper<TUserportal> lqw = Wrappers.lambdaQuery();
        lqw.eq(TUserportal::getUsername, langChaoTokenDto.getOpenid());
        TUserportal tUserportal = getOne(lqw, false);

        //3.判断门户的用户是否存在
        if (tUserportal == null || StringUtils.isBlank(tUserportal.getLocaluserid())) {
            throw new BusinessException("浪潮门户单点登录失败: " + langChaoTokenDto.getOpenid() + "。无法找到用户数据，请联系管理员！");
        }

        //4.登陆
        AICUser aicUser = orgUM.findUserByPrimaryKey(tUserportal.getLocaluserid());
        RestResult<AICUser> loginResult = userBaseService.login(aicUser.getEname(), "Hn9U-)gDqM");

        // 5.存储浪潮令牌信息
        redisService.set(ConstantsUtil.LANG_CHAO_ACCESS_TOKEN_KEY + aicUser.getEname(), JSON.toJSONString(langChaoTokenDto), (int) langChaoTokenDto.getExpires_in());

        return loginResult.getData();
    }

    @Override
    public void updateByUserName(String realname) {
        userBaseService.updateByUserName(realname);
    }

}
