package ink.wgink.login.app.service.appsign.impl;

import ink.wgink.exceptions.AppDeviceException;
import ink.wgink.exceptions.AppVersionException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.interfaces.expand.login.ILoginAppHandlerService;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginDefaultVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginPhoneVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginVO;
import ink.wgink.login.app.service.appdeviceuser.IAppDeviceUserService;
import ink.wgink.login.app.service.appsign.IAppSignService;
import ink.wgink.login.app.service.appversion.IAppVersionService;
import ink.wgink.login.base.service.BaseAppSignService;
import ink.wgink.pojo.bos.LoginAppUser;
import ink.wgink.service.user.enums.UserStateEnum;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.request.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: AppSignServiceImpl
 * @Description: 登录
 * @Author: wanggeng
 * @Date: 2021/4/7 3:59 下午
 * @Version: 1.0
 */
@Service
public class AppSignServiceImpl extends BaseAppSignService implements IAppSignService {

    @Autowired
    private IAppDeviceUserService appDeviceUserService;
    @Autowired
    private IAppVersionService appVersionService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IUserService userService;
    @Autowired(required = false)
    private ILoginAppHandlerService loginAppHandlerService;


    @Override
    public String defaultSign(AppLoginDefaultVO appLoginDefaultVO) throws Exception {
        String userPassword = appLoginDefaultVO.getPassword();
        checkApiLock(appLoginDefaultVO);
        UserPO userPO = userService.getPOByUsername(appLoginDefaultVO.getUsername());
        if (userPO == null) {
            throw new SearchException("用户不存在");
        }
        if (!passwordEncoder.matches(userPassword, userPO.getUserPassword())) {
            throw new SearchException("用户名或密码错误");
        }
        userLogin(appLoginDefaultVO, userPO);
        return getToken(userPO);
    }

    @Override
    public String phoneSign(AppLoginPhoneVO appLoginPhoneVO) throws Exception {
        UserPO userPO = userService.getPOByPhone(appLoginPhoneVO.getUsername());
        if (userPO == null) {
            throw new SearchException("用户不存在");
        }
        userLogin(appLoginPhoneVO, userPO);
        return getToken(userPO);
    }

    /**
     * 用户登陆，如果设备编号存在，则通过设备编号判断是否可以登录
     *
     * @param appLoginVO
     * @param userPO
     */
    private void userLogin(AppLoginVO appLoginVO, UserPO userPO) throws Exception {
        if (userPO.getUserState() == UserStateEnum.UN_EXAMINE.getValue()) {
            throw new SearchException("用户未审核");
        }
        if (userPO.getUserState() == UserStateEnum.UN_PASS.getValue()) {
            throw new SearchException("用户审核未通过");
        }
        if (userPO.getUserState() == UserStateEnum.LOCK.getValue()) {
            throw new SearchException("用户已锁定");
        }
        if (DateUtil.isDateExpired(userPO.getUserExpiredDate())) {
            throw new SearchException("账号已经过期");
        }
        LOG.debug("校验设备");
        if (!StringUtils.isBlank(appLoginVO.getDeviceNo()) && !appDeviceUserService.canSign(userPO.getUserId(), appLoginVO.getDeviceNo())) {
            throw new AppDeviceException("非法登录设备");
        }
        if (loginAppHandlerService != null) {
            LOG.debug("自定义登录处理");
            LoginAppUser loginAppUser = new LoginAppUser();
            BeanUtils.copyProperties(userPO, loginAppUser);
            loginAppHandlerService.handle(loginAppUser);
        }
        LOG.debug("更新登录信息");
        updateLoginInfo(userPO, appLoginVO.getLongitude(), appLoginVO.getLatitude());
    }

    /**
     * 更新登录信息
     *
     * @param userPO
     * @param userLongitude
     * @param userLatitude
     * @throws UpdateException
     */
    private void updateLoginInfo(UserPO userPO, Object userLongitude, Object userLatitude) throws UpdateException {
        String currentTime = DateUtil.getTime();
        Map<String, Object> params = new HashMap<>(0);
        params.put("userId", userPO.getUserId());
        params.put("lastLoginAddress", RequestUtil.getRequestIp());
        params.put("lastLoginTime", currentTime);
        params.put("userLongitude", userLongitude);
        params.put("userLatitude", userLatitude);
        params.put("gmtModified", currentTime);
        params.put("modifier", userPO.getUserId());
        userService.updateLoginInfo(params);
    }

    /**
     * 校验是否版本锁定，锁定后，如果有升级，提示下载
     */
    private void checkApiLock(AppLoginVO appLoginVO) {
        if (!StringUtils.isBlank(appLoginVO.getAppId()) &&
                appVersionService.canApiLock(appLoginVO.getAppId(), appLoginVO.getAppVersion() == null ? null : appLoginVO.getAppVersion().toString())) {
            throw new AppVersionException("app版本过低，请重新下载");
        }
    }

    @Override
    public String userIdSign(String userId) throws UnsupportedEncodingException {
        UserPO userPO = userService.getPO(userId);
        return getToken(userPO);
    }

}
