package shop.alien.gateway.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.second.LifeUserLog;
import shop.alien.entity.second.SecondRiskControlRecord;
import shop.alien.entity.second.SecondUserCredit;
import shop.alien.entity.second.SecondUserCreditRecord;
import shop.alien.entity.second.enums.SecondUserCreditScoreEnum;
import shop.alien.entity.store.LifeUser;
import shop.alien.entity.store.vo.LifeUserVo;
import shop.alien.gateway.config.BaseRedisService;
import shop.alien.gateway.config.RiskControlProperties;
import shop.alien.gateway.feign.SecondServiceFeign;
import shop.alien.gateway.mapper.LifeUserGatewayMapper;
import shop.alien.gateway.mapper.LifeUserLogGatewayMapper;
import shop.alien.mapper.second.SecondRiskControlRecordMapper;
import shop.alien.mapper.second.SecondUserCreditMapper;
import shop.alien.mapper.second.SecondUserCreditRecordMapper;
import shop.alien.util.common.JwtUtil;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户
 */
@Service
@RequiredArgsConstructor
public class LifeUserService extends ServiceImpl<LifeUserGatewayMapper, LifeUser> {

    private final LifeUserGatewayMapper lifeUserMapper;

    private final LifeUserLogGatewayMapper lifeUserLogMapper;

    private final BaseRedisService baseRedisService;

    private final SecondServiceFeign alienSecondFeign;

    private final ActivityInviteConfigService activityInviteConfigService;

    private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;

    private final LifeUserLogTransactionService lifeUserLogTransactionService;

    @Autowired
    private final SecondUserCreditMapper secondUserCreditMapper;

    @Autowired
    private final SecondUserCreditRecordMapper secondUserCreditRecordMapper;

    @Autowired
    private RiskControlProperties riskControlProperties;

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

    public LifeUserVo userLogin(String phoneNum, String inviteCode, String macIp) {
        LifeUser user = getUserByPhone(phoneNum);
        if (user == null) {
            LifeUser lifeUser = new LifeUser();
            lifeUser.setUserPhone(phoneNum);
            lifeUser.setUserName(phoneNum);
            lifeUser.setRealName(phoneNum);
            lifeUser.setCreatedTime(new Date());
            int ret = lifeUserMapper.insert(lifeUser);
            if (ret == 1) {
                LifeUser user2 = getUserByPhone(phoneNum);
                LifeUserVo userVo = new LifeUserVo();
                BeanUtils.copyProperties(user2, userVo);
                Map<String, String> tokenMap = new HashMap<>();
                tokenMap.put("phone", phoneNum);
                tokenMap.put("userName", lifeUser.getUserName());
                tokenMap.put("userId", lifeUser.getId().toString());
                tokenMap.put("userType", "user");
//                userVo.setToken(JWTUtils1.createToken(tokenMap));
                String token = getToken(phoneNum, userVo.getUserName(), tokenMap);
                userVo.setToken(token);
                baseRedisService.setString("user_" + phoneNum, token);
                // 二手平台登录log，同一个macip登录多账号记录
                addLifeUserLogInfo(user2, macIp);

                return userVo;
            } else {
                return null;
            }
        } else {
            LifeUserVo userVo = new LifeUserVo();
            BeanUtils.copyProperties(user, userVo);
            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 = getToken(phoneNum, user.getUserName(), tokenMap);
            userVo.setToken(token);
            baseRedisService.setString("user_" + phoneNum, token);
            // 二手平台登录log，同一个macip登录多账号记录
            addLifeUserLogInfo(user, macIp);

            return userVo;
        }
    }

    private String getToken(String phoneNum, String userVo, 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;
            }
        }
        String token = JwtUtil.createJWT("user_" + phoneNum, userVo, JSONObject.toJSONString(tokenMap), effectiveTimeIntLong);
        return token;
    }

    public LifeUser getUserByPhone(String phoneNum) {
        LambdaQueryWrapper<LifeUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LifeUser::getUserPhone, phoneNum);
        return this.getOne(lambdaQueryWrapper);
    }


    /**
     * 用户登录log存放（加入mac地址）
     * 记录用户登录信息并进行风控检查
     */
    @Transactional
    public void addLifeUserLogInfo(LifeUser user, String macIp) {
        try {
            LifeUserLog lifeUserLog = new LifeUserLog();
            lifeUserLog.setUserId(user.getId());
            lifeUserLog.setUserName(user.getUserName());
            lifeUserLog.setMacIp(macIp);
            lifeUserLog.setCreatedTime(new Date());
            // 通过独立服务类调用，确保事务代理生效，插入操作立即提交
            int count = lifeUserLogTransactionService.insertLifeUserLog(lifeUserLog);
            if (count > 0) {
                String startDate = LocalDateTime.now().minusHours(24L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                // 通过独立服务类查询，确保能看到刚才插入并提交的数据
                List<LifeUserLog> lsit = lifeUserLogTransactionService.getLifeUserLogByDate(startDate, endDate, macIp);

                if (lsit.size() > riskControlProperties.getAccountAbnormal().getRegCount24h() && !isViolation(startDate, endDate, macIp, user.getId())) {

                    for (LifeUserLog row: lsit) {
                        List<SecondUserCreditRecord> num = secondUserCreditRecordMapper.selectList(new LambdaQueryWrapper<SecondUserCreditRecord>()
                                .eq(SecondUserCreditRecord::getUserId, row.getUserId())
                                .eq(SecondUserCreditRecord::getPointsType, SecondUserCreditScoreEnum.ABNORMAL_ACCOUNTV.getCode())
                                .ge(SecondUserCreditRecord::getCreatedTime, startDate)
                                .le(SecondUserCreditRecord::getCreatedTime, endDate));

                        if (num.size() <= 0) {
                            LambdaQueryWrapper<SecondUserCredit> queryWrapper = new LambdaQueryWrapper<>();
                            queryWrapper.eq(SecondUserCredit::getUserId, row.getUserId())
                                    .orderByDesc(SecondUserCredit::getCreatedTime).last("LIMIT 1");
                            SecondUserCredit secondUserCredit = secondUserCreditMapper.selectOne(queryWrapper);
                            int score = secondUserCredit.getUserPoints() + SecondUserCreditScoreEnum.ABNORMAL_ACCOUNTV.getScore();
                            secondUserCredit.setUserPoints(score);
                            secondUserCreditMapper.updateById(secondUserCredit);

                            SecondUserCreditRecord record = new SecondUserCreditRecord();
                            record.setUserId(row.getUserId());
                            record.setPointsType(SecondUserCreditScoreEnum.ABNORMAL_ACCOUNTV.getCode());
                            record.setPoints(SecondUserCreditScoreEnum.ABNORMAL_ACCOUNTV.getScore());
                            record.setCurrentScoreCount(score);
                            record.setCreatedTime(new Date());
                            secondUserCreditRecordMapper.insert(record);

                            // 小于100分封禁用户
                            if (score < 100) {
                                LifeUser user1 = new LifeUser();
                                user1.setId(row.getUserId());
                                user1.setIsBanned(1);
                                lifeUserMapper.updateById(user1);
                            }
                        }
                    }

//                    String detailInfo = lsit.stream()
//                            .map(row -> row.getUserId().toString())
//                            .collect(Collectors.joining(","));
//                    alienSecondFeign.recordRiskControlData(user.getId(), 2, "账号异常", macIp, detailInfo);
                }
            }
            // 第一次登录，添加用户基础积分
            alienSecondFeign.createPointsRecord(user.getId(), 500, 1);
        } catch (Exception e) {
            log.error("用户登录log存放异常：{}", e);
        }

    }

    /**
     * 判断是否已存在违规记录
     * 检查指定时间段内是否已经记录过该用户的风控信息
     *
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param macIp MAC地址/IP
     * @param userId 用户ID
     * @return boolean true-已存在违规记录，false-不存在
     */
    public boolean isViolation(String startDate, String endDate, String macIp, Integer userId) {
        List<SecondRiskControlRecord> list = secondRiskControlRecordMapper.selectByBusinessId(startDate, endDate, macIp);
        for (SecondRiskControlRecord record : list) {
            // 将数组转换为包含整数的列表
            List<Integer> userIdList = Arrays.stream(record.getDetailInfo().split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            if (userIdList.contains(userId)) {
                return true;
            }
        }
        return false;
    }
}
