package com.user.service.service.impl;

import com.base.orbit.constant.Constants;
import com.base.orbit.domain.AjaxResult;
import com.base.orbit.domain.enity.SysUser;
import com.user.service.token.LoginUser;
import com.user.service.redis.RedisCache;
import com.user.service.token.TokenService;
import com.user.service.service.ILoginServcie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.security.core.Authentication;
import java.util.HashMap;
import java.util.Objects;

@Service
@Slf4j
public class LoginServiceImpl implements ILoginServcie {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TokenService tokenService;

    @Override
    public AjaxResult login(SysUser user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassWord());
        /**
         * // 调用链
         * AuthenticationManager.authenticate()  --> ProviderManager.authenticate()
         * --> DaoAuthenticationProvider(AbstractUserDetailsAuthenticationProvider).authenticate()
         * // 处理
         * 在最后的 authenticate() 方法中，调用了 UserDetailsService.loadUserByUsername()
         * 并进行了密码校验，校验成功就构造一个认证过的 UsernamePasswordAuthenticationToken 对象放入 SecurityContext.
         */
        Authentication authenticate = null;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authenticate = authenticationManager.authenticate(authenticationToken);
        } catch (Exception e) {
            log.error("用户认证失败，错误信息:", e.getMessage());
            return AjaxResult.error("用户认证失败，错误信息:" + e.getMessage());
        }
        //  抛出参数不合法异常
        if (Objects.isNull(authenticate)) {
            log.error("登录失败，用户名【" + user.getUserName() + "】密码【" + user.getPassWord() + "】");
            return AjaxResult.error("登录失败，用户名【" + user.getUserName() + "】密码【" + user.getPassWord() + "】");
        }
        //  使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        //  把token响应给前端
        String token = tokenService.createToken(loginUser);
        HashMap<String, Object> map = new HashMap<>();
        map.put(Constants.TOKEN, token);
        map.put(Constants.USER_TYPE, loginUser.getUser().getUserType());
        map.put(Constants.USER_ID, loginUser.getUser().getUserId());
        return AjaxResult.success("登陆成功", map);
    }

    @Override
    public AjaxResult logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String token = loginUser.getToken();
        redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + token);
        return AjaxResult.success("退出成功");
    }
}
