package com.hzs.member.statis.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.enums.ETop30Type;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.DataMaskingUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.member.statis.DirectStatisticsTop30VO;
import com.hzs.member.statis.mapper.MemberStatisticsMapper;
import com.hzs.member.statis.param.DirectStatisticsTop30QueryParam;
import com.hzs.member.statis.service.IMemberStatisticsService;
import com.hzs.member.statis.util.DataGeneratorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.*;
import java.util.*;

@Service
@Slf4j
public class MemberStatisticsServiceImpl implements IMemberStatisticsService {

    @Resource
    private MemberStatisticsMapper memberStatisticsMapper;

    @Resource
    private RedisService redisService;
    @Override
    public List<DirectStatisticsTop30VO> getDirectStatisticsNumberOfPeople(DirectStatisticsTop30QueryParam param) {
        String show = redisService.getCacheObject(CacheConstants.TOP_30_ACTIVITY + ETop30Type.PEOPLE.getKey());
        if(ObjectUtil.isEmpty(show) || "false".equals(show)){
            return null;
        }
        if(DateUtils.isYearMonthExceedCurrent(param.getYear() + "/" + param.getMonth())) {
            return null;
        }
        setStartAndEndDate(param);
        List<DirectStatisticsTop30VO> list = memberStatisticsMapper.getDirectStatisticsNumberOfPeople(param);
        return desensitizationAndFaker(list, param, 1);
    }

    @Override
    public List<DirectStatisticsTop30VO> getDirectStatisticsNumberOfAmount(DirectStatisticsTop30QueryParam param) {
        String show = redisService.getCacheObject(CacheConstants.TOP_30_ACTIVITY + ETop30Type.AMOUNT.getKey());
        if(ObjectUtil.isEmpty(show) || "false".equals(show)){
            return null;
        }
        if(DateUtils.isYearMonthExceedCurrent(param.getYear() + "/" + param.getMonth())) {
            return null;
        }
        setStartAndEndDate(param);
        List<DirectStatisticsTop30VO> list = memberStatisticsMapper.getDirectStatisticsNumberOfAmount(param);
        return desensitizationAndFaker(list, param, 2);
    }

    /**
     * 数据脱敏&格式化数字&假数据
     * @param list
     * @param param
     * @param type
     */
    private List<DirectStatisticsTop30VO> desensitizationAndFaker(List<DirectStatisticsTop30VO> list, DirectStatisticsTop30QueryParam param, Integer type){
        List<DirectStatisticsTop30VO> fakerList = DataGeneratorUtils.generateFakeData(
                new ArrayList<>(), 30, 1, DataGeneratorUtils.TimeGranularity.DAY);
        List<DirectStatisticsTop30VO> result = list;
        if(param.getFaker()){
            result = generateFakeData(list, 30, fakerList, type);
        }
        for (DirectStatisticsTop30VO directStatisticsTop30VO : result) {
            if(param.getFaker()){
                directStatisticsTop30VO.setMemberCode(DataMaskingUtil.mask(directStatisticsTop30VO.getMemberCode(), 2, 2));
                directStatisticsTop30VO.setMemberName(DataMaskingUtil.maskFirstLast(directStatisticsTop30VO.getMemberName()));
            }
//            directStatisticsTop30VO.setNumberOfAmount(directStatisticsTop30VO.getNumberOfAmount().divide(new BigDecimal(10000)));
        }
        return result;
    }
    private void setStartAndEndDate(DirectStatisticsTop30QueryParam param) {
        // 参数验证
        if (ObjectUtil.isEmpty(param.getYear()) || ObjectUtil.isEmpty(param.getMonth())) {
            throw new IllegalArgumentException("年份和月份不能为空");
        }
        try {
            int year = Integer.parseInt(param.getYear());
            int month = Integer.parseInt(param.getMonth());
            YearMonth yearMonth = YearMonth.of(year, month);
            LocalDateTime firstDay = yearMonth.atDay(1).atStartOfDay();
            LocalDateTime lastDay = yearMonth.atEndOfMonth().atTime(23, 59, 59);
            // 获取系统默认时区
            ZoneId zoneId = ZoneId.systemDefault();
            // 转换为Date
            param.setStartDate(Date.from(firstDay.atZone(zoneId).toInstant()));
            param.setEndDate(Date.from(lastDay.atZone(zoneId).toInstant()));
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("年份或月份格式不正确", e);
        } catch (Exception e) {
            throw new RuntimeException("获取时间范围失败", e);
        }
    }
    /**
     * 生成假数据并填充到列表
     *
     * @param list 原始数据列表
     * @param totalCount 总数
     * @param fakerList 假数据列表
     * @param type 类型：1为设置numberOfPeople, 2为设置numberOfAmount
     * @return 填充后的列表
     */
    public static List<DirectStatisticsTop30VO> generateFakeData(
            List<DirectStatisticsTop30VO> list,
            int totalCount,
            List<DirectStatisticsTop30VO> fakerList,
            int type) {
        if (list == null) {
            list = new ArrayList<>();
        }

        if (fakerList == null || fakerList.isEmpty()) {
            throw new IllegalArgumentException("假数据列表不能为空");
        }

        if (totalCount < list.size()) {
            throw new IllegalArgumentException("总数不能小于原始列表大小");
        }

        // 计算需要生成的假数据数量
        int needGenerateCount = totalCount - list.size();

        // 检查假数据列表是否有足够的数据
        if (needGenerateCount > fakerList.size()) {
            throw new IllegalArgumentException("假数据列表数据不足");
        }

        // 从假数据列表中移除并获取需要的假数据
        List<DirectStatisticsTop30VO> selectedFakerData = new ArrayList<>();
        for (int i = 0; i < needGenerateCount; i++) {
            // 随机选择一个假数据
            int randomIndex = new Random().nextInt(fakerList.size());
            DirectStatisticsTop30VO fakerData = fakerList.remove(randomIndex);
            selectedFakerData.add(fakerData);
        }

        // 根据类型设置数据
        if (type == 1) {
            setNumberOfPeople(selectedFakerData, list);
        } else if (type == 2) {
            setNumberOfAmount(selectedFakerData, list);
        } else {
            throw new IllegalArgumentException("类型参数无效，只能是1或2");
        }

        // 将生成的假数据添加到原始列表
        list.addAll(selectedFakerData);

        // 按照对应类型降序排序
        if (type == 1) {
            list.sort(Comparator.comparing(DirectStatisticsTop30VO::getNumberOfPeople).reversed());
        } else {
            list.sort(Comparator.comparing(DirectStatisticsTop30VO::getNumberOfAmount).reversed());
        }

        return list;
    }

    /**
     * 设置numberOfPeople
     */
    private static void setNumberOfPeople(List<DirectStatisticsTop30VO> selectedFakerData, List<DirectStatisticsTop30VO> originalList) {
        // 找出原始列表中最小的numberOfPeople
        int minPeopleCount = Integer.MAX_VALUE;
        for (DirectStatisticsTop30VO data : originalList) {
            if (data.getNumberOfPeople() != null && data.getNumberOfPeople() < minPeopleCount) {
                minPeopleCount = data.getNumberOfPeople();
            }
        }
        if (minPeopleCount == Integer.MAX_VALUE) {
            minPeopleCount = 10; // 默认值，可以根据需要调整
        }
        Random random = new Random();
        for (DirectStatisticsTop30VO fakerData : selectedFakerData) {
            if (minPeopleCount == 1) {
                fakerData.setNumberOfPeople(1);
            } else {
                int value = random.nextInt(minPeopleCount - 1) + 1;
                fakerData.setNumberOfPeople(value);
            }
        }
    }

    /**
     * 设置numberOfAmount
     */
    private static void setNumberOfAmount(List<DirectStatisticsTop30VO> selectedFakerData, List<DirectStatisticsTop30VO> originalList) {
        // 找出原始列表中最小的numberOfAmount
        BigDecimal minAmount = null;
        for (DirectStatisticsTop30VO data : originalList) {
            if (data.getNumberOfAmount() != null) {
                if (minAmount == null || data.getNumberOfAmount().compareTo(minAmount) < 0) {
                    minAmount = data.getNumberOfAmount();
                }
            }
        }
        if (minAmount == null) {
            minAmount = new BigDecimal(188); // 默认值，可以根据需要调整
        }
        Random random = new Random();
        for (DirectStatisticsTop30VO fakerData : selectedFakerData) {
            if (minAmount.compareTo(new BigDecimal(188)) == 0) {
                BigDecimal value = new BigDecimal(188);
                fakerData.setNumberOfAmount(value);
            } else {
                BigDecimal range = minAmount.subtract(BigDecimal.ONE);
                BigDecimal randomValue = new BigDecimal(random.nextDouble() * range.doubleValue()).setScale(4, BigDecimal.ROUND_HALF_UP);
                if (randomValue.compareTo(BigDecimal.ZERO) <= 0) {
                    randomValue = BigDecimal.ONE;
                }
                fakerData.setNumberOfAmount(randomValue);
            }
        }
    }

}
