package com.yunfeiyun.agmp.common.core.controller;

import com.alibaba.fastjson2.JSONObject;
import com.yunfeiyun.agmp.common.constant.ErrorCode;
import com.yunfeiyun.agmp.common.core.domain.AjaxResult;
import com.yunfeiyun.agmp.common.core.domain.entity.PtsUserBind;
import com.yunfeiyun.agmp.common.core.domain.entity.SysUser;
import com.yunfeiyun.agmp.common.core.domain.model.*;
import com.yunfeiyun.agmp.common.enums.RedisCacheKey;
import com.yunfeiyun.agmp.common.framework.manager.RedisCacheManager;
import com.yunfeiyun.agmp.common.framework.web.service.ISysUserService;
import com.yunfeiyun.agmp.common.framework.web.service.PortalService;
import com.yunfeiyun.agmp.common.framework.web.service.TokenService;
import com.yunfeiyun.agmp.common.utils.DateUtils;
import com.yunfeiyun.agmp.common.utils.ip.IpUtils;
import com.yunfeiyun.agmp.common.utils.spring.SpringUtils;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;

/**
 * sso单点认证的接口
 *
 * @author 杨晓辉
 */
@CrossOrigin
@RestController
@RequestMapping("/sso")
public class PortalSsoAuthController {

    private static final Logger log = LoggerFactory.getLogger(PortalSsoAuthController.class);

    @Bean
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }

    @Autowired
    RestTemplate restTemplate;

    //农事系统自己用
    @PostMapping("/verifyToken")
    public AjaxResult verifySYSToken(@RequestBody PtsTokenKey ptsTokenKey){
        log.warn("ptsToken={} " , ptsTokenKey.getPtsToken());
        HashMap<String, String> params = new HashMap<>();
        if(ptsTokenKey ==null || ptsTokenKey.getPtsToken() == null || !StringUtils.hasText(ptsTokenKey.getPtsToken())){
            return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
        }
        PortalInfo portalInfo = SpringUtils.getBean(PortalService.class).getSsoInfo();
        params.put("ptsToken", ptsTokenKey.getPtsToken());
        params.put("sysId", portalInfo.getAppName());
        AjaxResult response = null;
        try {
             response = restTemplate.postForObject(portalInfo.getSsoTokenUrl(), params, AjaxResult.class );
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
        }
        log.warn("ptsToken={}  访问地址={} 门户返回值={}" , ptsTokenKey.getPtsToken() , portalInfo.getSsoTokenUrl(),response);
        if(!ErrorCode.SUCCESS.getCode().equals(response.get("code"))){
            return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
        }
        JSONObject data = JSONObject.from(response.get("data"));
        try {
            PortalUser portalUser = PortalUser.toBind(data);
            if (portalUser.getUserBind() == null || portalUser.getUserBind().getUserId() == null || portalUser.getUserBind().getUserId().equals("") || "-1".equals(portalUser.getUserBind().getUserId())) {  // 没有绑定子系统用户,滚出去
                log.warn("ptsToken={}  访问地址={} 未绑定系统用户 请退出", ptsTokenKey.getPtsToken(), portalInfo.getSsoTokenUrl());
                return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
            } else {
                //查询自己的用户id显示
                portalUser.setToken(ptsTokenKey.getPtsToken());  //重新写自己的ssoToken
                IBaseUser sysLoginUser = SpringUtils.getBean(ISysUserService.class).selectUserById(portalUser.getUserBind().getUserId());
                if (sysLoginUser != null) {
                    //更新缓存信息
                    SysUser sysUser = new SysUser("");
                    sysUser.setUserId(portalUser.getUserId());
                    sysUser.setUserLastloginip(IpUtils.getIpAddr());
                    sysUser.setUserLastlogindate(DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:ss").toString());
                    SpringUtils.getBean(ISysUserService.class).updateUserProfile(sysUser);
                    LoginUser loginUser = new LoginUser();
                    loginUser.setUserId(portalUser.getUserId());
                    loginUser.setUser(sysLoginUser);
                    loginUser.setIpaddr(portalUser.getIpaddr());
                    loginUser.setBrowser(portalUser.getBrowser());
                    loginUser.setDeptId(portalUser.getBrowser());
                    loginUser.setExpireTime(portalUser.getExpireTime());
                    loginUser.setLoginTime(portalUser.getLoginTime());
                    loginUser.setOs(portalUser.getOs());
                    loginUser.setLoginLocation(portalUser.getLoginLocation());
                    //生成农事的自己会话Token
                    String token = SpringUtils.getBean(TokenService.class).loginPTS(portalUser.getUserLoginname(), ptsTokenKey.getPtsToken(), portalUser.getSsoTokenKey());
                    portalUser.getUserBind().setUserBindToken(token);  //赛成自己的
                    log.warn("系统={} 接收门户回传ssoTokenKey={}   生成自己的sysToken={}", portalInfo.getAppName(), portalUser.getSsoTokenKey(), token);

                    ptsTokenKey.setSysId(ptsTokenKey.getSysName());
                    ptsTokenKey.setSysToken(token);
                    ptsTokenKey.setLogoutUrl(portalInfo.getAppLogoutUrl());
                    SessionJoinCache.registerSession(ptsTokenKey);
                    return AjaxResult.success(portalUser);
                } else {
                    log.warn("ptsToken={}  访问地址={} 未绑定系统用户 请退出", ptsTokenKey.getPtsToken(), portalInfo.getSsoTokenUrl());
                    return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
                }

            }
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
        }
    }


    //农事系统自己用
    @PostMapping("/logoutToken")
    public AjaxResult logoutSYSToken(@RequestBody PtsTokenKey ptsTokenKey){
        Claims claims = SpringUtils.getBean(TokenService.class).parseSsoToken(ptsTokenKey.getSysToken());
        String userIdCacheKey = (String) claims.get(SpringUtils.getBean(PortalService.class).getClaimsKey());
        String userSysTokenKey = SpringUtils.getBean(TokenService.class).getTokenKey(userIdCacheKey);
        log.warn("删会话userSysTokenKey={}  ptsToken={} " , userSysTokenKey ,  ptsTokenKey.toString());
        userSysTokenKey = userSysTokenKey.indexOf("FMS_login_tokens:") > -1 ? userSysTokenKey.substring("FMS_login_tokens:".length()) : userSysTokenKey;
        SpringUtils.getBean(TokenService.class).delLoginUser(userSysTokenKey);
        return null;
    }


    //sso服务器自己用
    @PostMapping("/auth/verifyToken")
    public AjaxResult verifyPTSToken(@RequestBody PtsTokenKey ptsTokenKey){
        log.warn("集成服务接收到子系统服务标识={} 待验证ptsToken={} "  ,ptsTokenKey.getSysId() , ptsTokenKey.getPtsToken() );
        PortalInfo portalInfo = SpringUtils.getBean(PortalService.class).getSsoInfo();
        Claims claims = SpringUtils.getBean(TokenService.class).parseSsoToken(ptsTokenKey.getPtsToken());
        // 解析对应的权限以及用户信息
        String userIdCacheKey = (String) claims.get(SpringUtils.getBean(PortalService.class).getClaimsKey());
        String userSsoTokenKey = SpringUtils.getBean(TokenService.class).getTokenKey(userIdCacheKey);
        LoginUser ssoUser = SpringUtils.getBean(RedisCacheManager.class).getCacheObject(RedisCacheKey.SYS_LOGIN_TOKEN,userSsoTokenKey);
        if(ssoUser == null){
            log.warn("集成服务 缓存PTS的ssoTokenKey={} , Token={} 失效，未登录"  ,userSsoTokenKey ,ptsTokenKey.getPtsToken() );
            return AjaxResult.error(ErrorCode.AUTH_SSO.getCode());
        }
        List<IBaseUserBind> ptsUserBinds =  SpringUtils.getBean(ISysUserService.class).selectPtsUserBind(ssoUser.getUserId() , ptsTokenKey.getSysId() , portalInfo.isOrgEnabled() );
        IBaseUserBind userBind = null;
        if(ptsUserBinds == null || ptsUserBinds.size() == 0){
            userBind = new PtsUserBind();
            userBind.setUserId("-1");
            userBind.setUserBindSys(ptsTokenKey.getSysId());
        }else{
            userBind = (PtsUserBind)ptsUserBinds.get(0);
        }
        log.warn("集成服务userId={}, 缓存PTS的ssoTokenKey={} , 子系统用户={}" , ssoUser.getUserId() ,userSsoTokenKey , userBind.toString() );
        return AjaxResult.success(PortalUser.userBind( portalInfo.getAppName() , userIdCacheKey , ssoUser , userBind));
    }





    //sso服务器自己用
    @PostMapping("/auth/registerSession")
    public AjaxResult registerSession(@RequestBody PtsTokenKey ptsTokenKey){
        log.warn("集成服务接收到子系统 创建会话服务标识={} "  , ptsTokenKey != null ?  ptsTokenKey.toString() : "ptsTokenKey不存在" );
        if(ptsTokenKey != null && ptsTokenKey.getPtsToken() !=null ){
            Claims claims = SpringUtils.getBean(TokenService.class).parseSsoToken(ptsTokenKey.getPtsToken());
            // 解析对应的权限以及用户信息
            String userIdCacheKey = (String) claims.get(SpringUtils.getBean(PortalService.class).getClaimsKey());
            String userSsoTokenKey = SpringUtils.getBean(TokenService.class).getTokenKey(userIdCacheKey);
            SessionJoinCache.createSession(ptsTokenKey.getSysId(), userSsoTokenKey , ptsTokenKey.getSysToken() ,  ptsTokenKey.getLogoutUrl() );
        }else{
            log.warn("集成服务接收到子系统 创建会话服务标识={}  子系统注册会话失败"  , ptsTokenKey != null ?  ptsTokenKey.toString() : "ptsTokenKey不存在" );
        }
        return AjaxResult.success();
    }




    //sso服务器自己用
    @PostMapping("/auth/logout")
    public AjaxResult logoutPTSToken(@RequestBody PtsTokenKey ptsTokenKey){
        log.warn("集成服务接收到子系统服务标识={} 待销毁ptsToken={} "  , ptsTokenKey.getSysId() , ptsTokenKey.getPtsToken() );
        if(ptsTokenKey != null && ptsTokenKey.getPtsToken() != null){
            Claims claims = SpringUtils.getBean(TokenService.class).parseSsoToken(ptsTokenKey.getPtsToken());
            // 解析对应的权限以及用户信息
            String userIdCacheKey = (String) claims.get(SpringUtils.getBean(PortalService.class).getClaimsKey());
            String userSsoTokenKey = SpringUtils.getBean(TokenService.class).getTokenKey(userIdCacheKey);
            SessionJoinCache.destroySession(  userSsoTokenKey );
        }else{
            log.warn("集成服务接收到子系统服务标识={} 待销毁ptsToken={}  子系统注销会话失败 "  , ptsTokenKey.getSysId() , ptsTokenKey.getPtsToken() );
        }

        return AjaxResult.success();
    }

}
