package openjoe.smart.sso.server.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import openjoe.smart.sso.base.constant.BaseConstant;
import openjoe.smart.sso.base.entity.Result;
import openjoe.smart.sso.server.manager.AbstractCodeManager;
import openjoe.smart.sso.server.manager.AbstractTicketGrantingTicketManager;
import openjoe.smart.sso.server.manager.AppManager;
import openjoe.smart.sso.server.manager.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * 单点登录管理
 *
 * @author Joe
 */
@Controller
@RequestMapping(BaseConstant.LOGIN_PATH)
public class SSOLoginController {

    @Autowired
    private AbstractCodeManager codeManager;
    @Autowired
    private AbstractTicketGrantingTicketManager tgtManager;
    @Autowired
    private UserManager userManager;
    @Autowired
    private AppManager appManager;

    /**
     * 登录页
     *
     * @param redirectUri
     * @param clientId
     * @param request
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    public String login(
            @RequestParam(value = BaseConstant.REDIRECT_URI) String redirectUri,
            @RequestParam(value = BaseConstant.CLIENT_ID) String clientId,
            HttpServletRequest request) throws UnsupportedEncodingException {
        String tgt = tgtManager.get(request);
        if (!StringUtils.hasLength(tgt)) {
            return goLoginPage(redirectUri, clientId, request);
        }
        return generateCodeAndRedirect(tgt, clientId, redirectUri);
    }

    /**
     * 登录提交
     *
     * @param redirectUri
     * @param clientId
     * @param username
     * @param password
     * @param request
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(method = RequestMethod.POST)
    public String login(
            @RequestParam(value = BaseConstant.REDIRECT_URI) String redirectUri,
            @RequestParam(value = BaseConstant.CLIENT_ID) String clientId,
            @RequestParam String username,
            @RequestParam String password,
            HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

        Result<Long> appResult = appManager.validate(clientId);
        if (!appResult.isSuccess()) {
            request.setAttribute("errorMessage", appResult.getMessage());
            return goLoginPage(redirectUri, clientId, request);
        }

        Result<Long> result = userManager.validate(username, password);
        if (!result.isSuccess()) {
            request.setAttribute("errorMessage", result.getMessage());
            return goLoginPage(redirectUri, clientId, request);
        }

        String tgt = tgtManager.getOrCreate(result.getData(), request, response);
        return generateCodeAndRedirect(tgt, clientId, redirectUri);
    }

    /**
     * 设置request的redirectUri和clientId参数，跳转到登录页
     *
     * @param redirectUri
     * @param request
     * @return
     */
    private String goLoginPage(String redirectUri, String clientId, HttpServletRequest request) {
        request.setAttribute(BaseConstant.REDIRECT_URI, redirectUri);
        request.setAttribute(BaseConstant.CLIENT_ID, clientId);
        return "/login";
    }

    /**
     * 创建授权码，跳转到redirectUri
     *
     * @param tgt
     * @param clientId
     * @param redirectUri
     * @return
     * @throws UnsupportedEncodingException
     */
    private String generateCodeAndRedirect(String tgt, String clientId, String redirectUri) throws UnsupportedEncodingException {
        // 创建授权码
        String code = codeManager.create(tgt, clientId);
        return "redirect:" + authRedirectUri(redirectUri, code);
    }

    /**
     * 将授权码拼接到回调redirectUri中
     *
     * @param redirectUri
     * @param code
     * @return
     * @throws UnsupportedEncodingException
     */
    private String authRedirectUri(String redirectUri, String code) throws UnsupportedEncodingException {
        StringBuilder sbf = new StringBuilder(redirectUri);
        if (redirectUri.indexOf("?") > -1) {
            sbf.append("&");
        } else {
            sbf.append("?");
        }
        sbf.append(BaseConstant.AUTH_CODE).append("=").append(code);
        return URLDecoder.decode(sbf.toString(), "utf-8");
    }

}