package ink.wgink.login.base.service.user;

import com.alibaba.fastjson.JSONObject;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.user.IUserDetailCheckService;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.manager.ConfigManager;
import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @ClassName: UserDetailServiceImpl
 * @Description: User Detail
 * @Author: WangGeng
 * @Date: 2019/2/18 3:06 PM
 * @Version: 1.0
 **/
@Service
public class UserDetailServiceImpl implements UserDetailsService, IUserDetailCheckService {

    @Autowired
    private IUserService userService;

    public UserDetailServiceImpl() {
        super();
    }

    @Override
    public UserDetails loadUserByUsername(String userInfo) throws UsernameNotFoundException {
        String username;
        try {
            JSONObject userInfoObject = JSONObject.parseObject(userInfo);
            username = userInfoObject.getString("userUsername");
        } catch (Exception e) {
            username = userInfo;
        }

        UserPO userPO = userService.getPOByUsername(username.toLowerCase());
        if (null == userPO) {
            throw new UserAuthenticationException("账号不存在");
        }
        if (userPO.getUserState() == 1) {
            throw new UserAuthenticationException("账号已冻结");
        }
        if (isAccountExpired(userPO)) {
            throw new UserAuthenticationException("账号已经过期");
        }
        return createUserBO(userPO);
    }

    /**
     * 创建UserBO
     *
     * @param userPO
     * @return
     */
    private LoginUser createUserBO(UserPO userPO) {
        LoginUser loginUser = new LoginUser(userPO.getUserUsername(), userPO.getUserPassword(),
                userPO.getUserType() == 1 ? true : false,
                isAccountNonExpired(userPO),
                isCredentialsNonExpired(userPO),
                userPO.getUserState() == 0 ? true : false);
        loginUser.setUserId(userPO.getUserId());
        loginUser.setUserName(userPO.getUserName());
        loginUser.setUserPhone(userPO.getUserPhone());
        loginUser.setUserUKey(userPO.getUserUKey());
        loginUser.setLoginType(userPO.getLoginType());
        loginUser.setUserEmail(userPO.getUserEmail());
        loginUser.setUserAvatar(userPO.getUserAvatar());
        return loginUser;
    }

    /**
     * 账号是否没有过期
     *
     * @param userPO
     * @return
     */
    private boolean isAccountNonExpired(UserPO userPO) {
        if (StringUtils.equals(userPO.getUserUsername(), ISystemConstant.ADMIN)) {
            return true;
        }
        if (!StringUtils.isBlank(userPO.getUserExpiredDate())) {
            // 判断用户是否超时失效
            DateTime expiredDateTime = DateTime.parse(userPO.getUserExpiredDate(), DateTimeFormat.forPattern(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
            DateTime nowDateTime = DateTime.now();
            if (expiredDateTime.isBefore(nowDateTime)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 密码是否没有过期
     *
     * @param userPO
     * @return
     */
    private boolean isCredentialsNonExpired(UserPO userPO) {
        if (StringUtils.equals(userPO.getUserUsername(), ISystemConstant.ADMIN)) {
            return true;
        }
        Map<String, String> config = ConfigManager.getInstance().getConfig();
        String passwordValidity = config.get("passwordValidity");
        // 自定义密码有效期
        if (StringUtils.equals(passwordValidity, "custom")) {
            Object passwordValidityDays = config.get("passwordValidityDays");
            int validityDays = passwordValidityDays == null ? 0 : (Integer) passwordValidityDays;
            if (validityDays <= 0) {
                return true;
            }
            DateTime passwordModifiedDateTime = DateTime.parse(userPO.getGmtPasswordModified(), DateTimeFormat.forPattern(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
            DateTime passwordExpiredDateTime = passwordModifiedDateTime.plusDays(validityDays);
            DateTime nowDateTime = DateTime.now();
            if (passwordExpiredDateTime.isBefore(nowDateTime)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 账号是否过期
     *
     * @param userPO
     * @return
     */
    private boolean isAccountExpired(UserPO userPO) {
        if (StringUtils.isBlank(userPO.getUserExpiredDate())) {
            return false;
        }
        DateTime now = DateTime.now();
        DateTime expiredDateTime = DateTime.parse(userPO.getUserExpiredDate(), DateTimeFormat.forPattern(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
        if (expiredDateTime.isAfter(now)) {
            return false;
        }
        return true;
    }

}
