package com.cool.store.service.login;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.constants.RedisConstant;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.dao.EnterpriseUserDAO;
import com.cool.store.dto.login.UserLoginDTO;
import com.cool.store.dto.login.UserRefreshLoginDTO;
import com.cool.store.entity.EnterpriseUserDO;
import com.cool.store.entity.login.UserLoginDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.EnterpriseService;
import com.cool.store.userholder.CurrentUser;
import com.cool.store.userholder.RefreshUser;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.poi.constant.Constants;
import com.cool.store.vo.login.UserBaseInfoVO;
import com.cool.store.vo.login.UserLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.util.Objects;

/**
 * <p>
 * 登录基础服务类
 * </p>
 *
 * @author wangff
 * @since 2025/9/3
 */
@Slf4j
@Service
public abstract class LoginBaseService implements LoginStrategy {
    @Resource
    private RedisUtilPool redisUtilPool;
    @Resource
    private EnterpriseUserDAO enterpriseUserDAO;
    @Resource
    private EnterpriseService enterpriseService;

    /**
     * 策略登录实现方法
     */
    public abstract ResponseResult userLogin(UserLoginDTO param, UserLoginDO userLoginDO);

    @Override
    public ResponseResult login(UserLoginDTO param) {
        log.info("login:{}", JSONObject.toJSONString(param));
        String errorPasswordCountKey = MessageFormat.format(RedisConstant.ERROR_PASSWORD_COUNT_KEY, LocalDate.now(), param.getMobile());
        String errorCount = redisUtilPool.getString(errorPasswordCountKey);
        //判断密码错误次数
        if (StringUtils.isNotBlank(errorCount)) {
            if (Integer.parseInt(errorCount) >= CommonConstants.MAX_ERROR_PASSWORD_COUNT) {
                return ResponseResult.fail(ErrorCodeEnum.PASSWORD_ERROR_MAX_COUNT, errorCount);
            }
        }
        EnterpriseUserDO enterpriseUserDO = enterpriseUserDAO.selectByMobile(param.getMobile());
        if (Objects.isNull(enterpriseUserDO)) {
            throw new ServiceException(ErrorCodeEnum.PARTNER_MOBILE_INCORRECT);
        }
        UserLoginDO userLoginDO = enterpriseUserDAO.getUserLoginByUnionid(enterpriseUserDO.getUnionid());
        return userLogin(param, userLoginDO);
    }

    @Override
    public ResponseResult refreshLogin(UserRefreshLoginDTO param) {
        String refreshTokenKey = RedisConstant.REFRESH_TOKEN_PREFIX + param.getRefreshToken();
        String refreshUserStr = redisUtilPool.getString(refreshTokenKey);
        if (StringUtils.isBlank(refreshUserStr)) {
            return ResponseResult.fail(ErrorCodeEnum.REFRESH_TOKEN_INVALID);
        }
        RefreshUser refreshUser = JSONObject.parseObject(refreshUserStr, RefreshUser.class);
        if (StringUtils.isBlank(refreshUser.getMobile())) {
            return ResponseResult.fail(ErrorCodeEnum.REFRESH_TOKEN_INVALID);
        }
        UserLoginDO userLoginDO = new UserLoginDO(refreshUser.getUserId(), refreshUser.getMobile(), null);
        return ResponseResult.success(getUserLoginInfo(userLoginDO));
    }

    @Override
    public ResponseResult logout() {
        LoginUserInfo currentUser = CurrentUserHolder.getUser();
        String accessToken = currentUser.getAccessToken();
        String key = RedisConstant.ACCESS_TOKEN_PREFIX + accessToken;
        redisUtilPool.delKey(key);
        return ResponseResult.success();
    }

    /**
     * 获取登录accessToken
     *
     * @param userLoginDO 用户登录信息
     * @return accessToken
     */
    public UserLoginVO getUserLoginInfo(UserLoginDO userLoginDO) {
        CurrentUser currentUser = enterpriseService.getLoginInfo(userLoginDO.getMobile());
        UserBaseInfoVO userBAseInfoVO = BeanUtil.toBean(currentUser, UserBaseInfoVO.class);
        RefreshUser refreshUser = enterpriseService.getRefreshUser(userLoginDO.getUserId(), userLoginDO.getMobile());
        return new UserLoginVO(currentUser.getAccessToken(), refreshUser.getRefreshToken(), CommonConstants.ACTION_TOKEN_EXPIRE, userBAseInfoVO);
    }
}
