package com.cpop.core.handler;

import com.alibaba.fastjson.JSONObject;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.ip.IpUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginForm;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.CpopAuthenticationException;
import com.cpop.core.service.CoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;

/**
 * @author: DB
 * @date: 2022-09-25 16:24
 * @Description: 登录失败handler
 */
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {

    @Autowired
    private CoreService coreService;

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        String jsonString = httpServletRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        //映射登录表单
        LoginForm loginFormBo = JSONObject.parseObject(jsonString, LoginForm.class);
        //构建用户信息
        LoginUser loginUser = new LoginUser();
        loginUser.setUserName(loginFormBo.getUsername()).setIpAddr(IpUtils.getIpAddr(httpServletRequest));
        String errorMessage = "用户名或密码错误";
        R<String> result;
        //自定义认证异常,可以从这里获取到想要的参数
        if(e instanceof CpopAuthenticationException) {
            loginUser.setUserType((UserType) ((CpopAuthenticationException) e).getParams());
            errorMessage = e.getMessage();
            result = R.ok(errorMessage);
        }else {
            result = R.fail(errorMessage);
        }
        if (loginUser.getUserType() == UserType.OAM_USER || loginUser.getUserType() == UserType.MINI_USER) {
            if (StringUtils.isNotBlank(loginFormBo.getUsername())){
                //添加登录失败日志
                coreService.insertOperationLog(Constants.FAIL, OperationLogEnum.SYSTEM_LOGIN, loginUser, errorMessage);
            }
        }
        outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
        outputStream.close();
    }
}
