package shop.alien.gateway.service;

import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LifeUser;
import shop.alien.entity.store.dto.LifeUserPasswordDto;
import shop.alien.entity.store.vo.LifeUserVo;
import shop.alien.gateway.config.BaseRedisService;
import shop.alien.gateway.mapper.LifeUserGatewayMapper;
import shop.alien.util.common.JwtUtil;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 用户端密码登录服务（独立实现，不修改原有验证码登录逻辑）
 */
@Service
@RequiredArgsConstructor
public class LifeUserPasswordService {

    private final LifeUserGatewayMapper lifeUserMapper;

    private final BaseRedisService baseRedisService;

    private final LifeUserService lifeUserService;

    @Value("${jwt.expiration-time}")
    private String effectiveTime;

    public R<LifeUserVo> passwordLogin(LifeUserPasswordDto dto) {
        if (dto == null || StringUtils.isBlank(dto.getPhoneNum()) || StringUtils.isBlank(dto.getPassword())) {
            return R.fail("手机号和密码不能为空");
        }
        LifeUser user = lifeUserService.getUserByPhone(dto.getPhoneNum());
        if (user == null) {
            return R.fail("当前账号不存在，请先去注册账号");
        }
        if (StringUtils.isBlank(user.getPassword())) {
            return R.fail("尚未设置登录密码，请使用验证码登录或设置密码");
        }
        if (!Objects.equals(dto.getPassword(), user.getPassword())) {
            return R.fail("密码错误");
        }
        if (user.getIsBanned() != null && user.getIsBanned() == 1) {
            return R.fail("您的账户因严重违规导致被封禁");
        }
        if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
            return R.fail("你的账号已注销");
        }
        return R.data(createLoginVo(user, dto.getPhoneNum(), dto.getMacIp()));
    }

    public R<String> forgetPassword(LifeUserPasswordDto dto) {
        if (dto == null || StringUtils.isBlank(dto.getPhoneNum()) || StringUtils.isBlank(dto.getCode())) {
            return R.fail("手机号和验证码不能为空");
        }
        if (StringUtils.isBlank(dto.getPassword())) {
            return R.fail("密码不能为空");
        }
        if (!Objects.equals(dto.getPassword(), dto.getConfirmPassword())) {
            return R.fail("两次密码输入不一致");
        }
        String cacheCode = baseRedisService.getString("verification_user_forget_password_" + dto.getPhoneNum());
        if (cacheCode == null) {
            return R.fail("验证码过期或未发送");
        }
        if (!cacheCode.trim().equals(dto.getCode().trim())) {
            return R.fail("验证码错误，请重新输入");
        }
        LifeUser user = lifeUserService.getUserByPhone(dto.getPhoneNum());
        if (user == null) {
            return R.fail("当前账号不存在，请先去注册账号");
        }
        LifeUser update = new LifeUser();
        update.setId(user.getId());
        update.setPassword(dto.getPassword());
        if (lifeUserMapper.updateById(update) <= 0) {
            return R.fail("重置密码失败");
        }
        baseRedisService.delete("verification_user_forget_password_" + dto.getPhoneNum());
        invalidateUserSessions(dto.getPhoneNum());
        return R.success("密码重置成功");
    }

    private LifeUserVo createLoginVo(LifeUser user, String phoneNum, String macIp) {
        LifeUserVo userVo = new LifeUserVo();
        BeanUtils.copyProperties(user, userVo);
        userVo.setPassword(null);
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("phone", phoneNum);
        tokenMap.put("userName", user.getUserName());
        tokenMap.put("userId", user.getId().toString());
        tokenMap.put("userType", "user");
        String token = createToken(phoneNum, user.getUserName(), tokenMap);
        userVo.setToken(token);
        addSessionToken(phoneNum, token);
        lifeUserService.addLifeUserLogInfo(user, macIp);
        userVo.setHasLoginPassword(StringUtils.isNotBlank(user.getPassword()));
        lifeUserService.fillLogoutEndTime(userVo, user);
        return userVo;
    }

    private String createToken(String phoneNum, String userName, Map<String, String> tokenMap) {
        int effectiveTimeInt = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
        String effectiveTimeUnit = effectiveTime.substring(effectiveTime.length() - 1);
        long effectiveTimeIntLong = 0L;
        switch (effectiveTimeUnit) {
            case "s":
                effectiveTimeIntLong = effectiveTimeInt * 1000L;
                break;
            case "m":
                effectiveTimeIntLong = effectiveTimeInt * 60L * 1000L;
                break;
            case "h":
                effectiveTimeIntLong = effectiveTimeInt * 60L * 60L * 1000L;
                break;
            case "d":
                effectiveTimeIntLong = effectiveTimeInt * 24L * 60L * 60L * 1000L;
                break;
            default:
                break;
        }
        return JwtUtil.createJWT("user_" + phoneNum, userName, JSONObject.toJSONString(tokenMap), effectiveTimeIntLong);
    }

    private void addSessionToken(String phone, String token) {
        String legacyKey = "user_" + phone;
        String sessionSetKey = "user_sessions:" + phone;
        String oldSingle = baseRedisService.getString(legacyKey);
        if (oldSingle != null && !oldSingle.isEmpty()) {
            baseRedisService.setSetList(sessionSetKey, oldSingle);
        }
        baseRedisService.delete(legacyKey);
        baseRedisService.setSetList(sessionSetKey, token);
    }

    private void invalidateUserSessions(String phone) {
        baseRedisService.delete("user_" + phone);
        baseRedisService.delete("user_sessions:" + phone);
    }
}
