package com.pj.project.sso;

import cn.dev33.satoken.context.model.SaRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.dtflys.forest.Forest;
import com.pj.current.satoken.StpUserUtil;
import com.pj.project.sys_client.SysClientUtil;
import com.pj.project.sys_client_visit.SysClientVisitUtil;
import com.pj.project.sys_user_acc.SysUserAccService;
import com.pj.project.sys_user_acc.SysUserAccUtil;
import com.pj.utils.sg.AjaxJson;

import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.spring.SpringMVCUtil;
import cn.dev33.satoken.sso.SaSsoProcessor;
import cn.dev33.satoken.sso.SaSsoUtil;
import cn.dev33.satoken.sso.exception.SaSsoException;

/**
 * Sa-Token-SSO Server端 Controller 
 */
@RestController
public class SsoServerController {

    /*
     * 此模块只处理SSO路由跳转，具体的登录接口在 sys_user_acc 模块
     */
    
	// 
    @Autowired
    SysUserAccService sysUserAccService;
    
    // SSO-Server端：处理所有SSO相关请求 
    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoProcessor.instance.serverDister();
    }
    
    // 重写 /sso/auth 统一认证请求处理，增加日志记录 
    @RequestMapping("/sso/auth")
    public Object ssoAuth() {
        // 如果登录时没有提供redirect参数，则进入平台中心首页 /home，而不是重定向到 client 端
        SaRequest req = SaHolder.getRequest();
        if(req.isPath("/sso/auth") && req.hasParam("redirect") == false && StpUserUtil.isLogin()) {
            return SaHolder.getResponse().redirect("/home");
        }
    	// 1. 记录一下登录日志: xx 账号登录了 xx 应用
		long loginId = StpUserUtil.getLoginId(0L);
    	if(loginId != 0L) {

    		// 1. 校验 redirect 是否有效
    		String redirect = SaHolder.getRequest().getParam("redirect");
    		Long clientId = SysClientUtil.getClientIdByUrl(redirect);
    		if(clientId == null) {
    			// SpringMVCUtil.getRequest().setAttribute("errorMessage", "无效 redirect：" + redirect);
    			// return new ModelAndView("login.html");
    			throw new SaSsoException("无效 redirect：" + redirect);
    		}
    		
    		// 2. 判断这个用户是否被禁止登录此应用，如果已被禁止，则立即截断登录 
    		if(SysClientVisitUtil.isSureLogin(loginId, redirect) == false) {
    			SpringMVCUtil.getRequest().setAttribute("errorMessage", "当前账号暂无权限登入此应用，请更换账号");
    			return new ModelAndView("login.html");
    		}
    		
    		// 3. 记录登录日志 
    		sysUserAccService.successLogin(loginId, redirect);
    	}
    	
    	// 2. 返回处理结果 
        return SaSsoProcessor.instance.ssoAuth();
    }
    
    

    // 自定义接口：获取userinfo
    @RequestMapping("/sso/userinfo")
    public Object userinfo(Long loginId) {
        // 校验签名，防止敏感信息外泄
        SaSsoUtil.checkSign(SaHolder.getRequest());

        // 返回信息
        Object user = SysUserAccUtil.getUserById(loginId);
        return AjaxJson.getSuccessData(user);
    }

    // 配置SSO相关参数 
    @Autowired
    private void configSso(SaSsoConfig sso) {
        // 配置：未登录时返回的View 
        sso.setNotLoginView(() -> {
            return new ModelAndView("login.html");
        });
        
        // 配置 Http 请求处理器 （在模式三的单点注销功能下用到，如不需要可以注释掉） 
        sso.setSendHttp(url -> {
            try {
                // 发起 http 请求 
                System.out.println("------ 发起请求：" + url);
                return Forest.get(url).executeAsString();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        });
    }

}
