package com.hz.pm.api.user.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.hz.pm.api.meeting.entity.config.WebProperties;
import com.hz.pm.api.user.manage.AgentLoginManage;
import com.hz.pm.api.user.manage.AuthCodeLoginManage;
import com.hz.pm.api.user.model.vo.AuthCodeVO;
import com.hz.pm.api.user.util.LoginUserUtil;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.StrPool;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.user.security.auth.constants.SessionTimeConst;
import com.ningdatech.log.annotation.WebLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 * 用户鉴权表 前端控制器
 * </p>
 *
 * @author Liuxinxin
 * @since 2023-01-04
 */
@RestController
@RequestMapping("/api/v1/user/auth")
@Api(tags = {"用户鉴权-相关接口"})
@RequiredArgsConstructor
public class UserAuthController {

    private final ObjectMapper objectMapper;
    private final AuthCodeLoginManage authCodeLoginManage;
    private final AgentLoginManage agentLoginManage;

    private static final String AUTH_CODE_LOGIN_PATH = "/api/v1/user/auth/authCodeLogin";

    @PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperation(value = "登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "identifier", value = "账号", required = true, paramType = "form", dataType = "String"),
            @ApiImplicitParam(name = "credential", value = "凭证", required = true, paramType = "form", dataType = "String"),
            @ApiImplicitParam(name = "loginType", value = "DING_QR_LOGIN 浙政钉扫码登陆,PHONE_VERIFICATION_CODE_LOGIN 手机号验证码登陆"
                    , required = true, paramType = "form", dataType = "String")})
    public void credentialLogin(@RequestParam(value = "identifier", required = false) String identifier,
                                @RequestParam(value = "credential", required = false) String credential,
                                @RequestParam("loginType") String loginType) {
        // 不实现任何内容，只是为了出api文档
    }

    @PostMapping(value = "/logout")
    @ApiOperation(value = "退出登陆")
    public void logout() {
        // 不实现任何内容，具体实现交由Spring Security进行管理
    }

    /**
     * 当需要身份认证时，跳转到这里
     */
    @GetMapping("/auth-require")
    @CrossOrigin(originPatterns = "*", allowCredentials = "true", maxAge = 3600)
    public void requireAuthentication(HttpServletResponse response) throws IOException {
        response.setContentType(StrPool.CONTENT_TYPE);
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED));
    }

    /**
     * 设置session失效
     */
    @GetMapping("/invalid-session")
    @CrossOrigin(originPatterns = "*", allowCredentials = "true", maxAge = 3600)
    public void invalidSession(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType(StrPool.CONTENT_TYPE);
        Cookie cookie = new Cookie(BizConst.COOKIE_KEY, null);
        cookie.setPath(request.getContextPath() + "/");
        cookie.setMaxAge(SessionTimeConst.SESSION_EXPIRED);
        response.addCookie(cookie);
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED));
    }

    @PostMapping(value = "/proxy/authCodeLogin", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperation(value = "代登陆")
    @WebLog("代登录（代理接口）")
    public void proxyAuthCodeLogin(@RequestParam(value = "userId") Long userId,
                                   @RequestParam(value = "userName") String username,
                                   @RequestParam(value = "timestamp") long timestamp,
                                   @RequestParam(value = "sign") String sign,
                                   HttpServletRequest request,
                                   HttpServletResponse response) throws IOException {
        if (LoginUserUtil.getUserId().equals(userId)) {
            throw BizException.wrap("代登录用户无效：%s", username);
        }
        String targetUserId = String.valueOf(userId);
        if (!agentLoginManage.agentLoginProxySignCheck(targetUserId, timestamp, sign)) {
            throw BizException.wrap("签名错误");
        }
        String authCode = authCodeLoginManage.generateAuthCode(targetUserId);
        String urlParam = "?authCode=" + authCode;
        String path = WebProperties.apiHost + request.getContextPath() + AUTH_CODE_LOGIN_PATH;
        response.sendRedirect(path + urlParam);
    }

    @PostMapping(value = "/getAuthCode", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public AuthCodeVO getAuthCode(@RequestParam(value = "userId") String userId,
                                  @RequestParam(value = "timestamp") Long timestamp,
                                  @RequestParam(value = "sign") String sign) {
        String authCode = authCodeLoginManage.generateAuthCode(userId, timestamp, sign);
        return new AuthCodeVO(authCode);
    }

    @GetMapping(value = "/authCodeLogin", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperation(value = "授权码登录")
    public void authCodeLogin(@RequestParam(value = "authCode") String authCode) {
        // 接口文档使用
    }

    @PostMapping(value = "/mh-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperation(value = "代登陆")
    @ApiImplicitParam(name = "code", value = "账号", paramType = "form")
    public void mhLogin(@RequestParam(value = "code") String code) {
        // 不实现任何内容，只是为了出api文档
    }

    @PostMapping(value = "/common-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperation(value = "公共登陆接口，目前适用于省局跳转登陆")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "credential", value = "凭证", required = true, paramType = "form", dataType = "String"),
            @ApiImplicitParam(name = "platform", value = "平台  PROVINCIAL_BUREAU，省局", required = true, paramType = "form", dataType = "String")
    })
    public void commonLogin(@RequestParam(value = "credential") String credential
            , @RequestParam(value = "platform") String platform) {
        // 不实现任何内容，只是为了出api文档
    }
}
