package org.dromara.zhishu.service.impl;

import cn.dev33.satoken.annotation.SaIgnore;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.dromara.zhishu.domain.dto.RunningTaskShopGoodsDto;
import org.dromara.zhishu.domain.dto.SuccessDataKfz;
import org.springframework.data.redis.core.StringRedisTemplate;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.zhishu.domain.RunningTask;
import org.dromara.zhishu.domain.dto.ErpGoodsDto;
import org.dromara.zhishu.domain.dto.SuccessDataItemDto;
import org.dromara.zhishu.domain.vo.RunningTaskNumVo;
import org.dromara.zhishu.domain.vo.ZhishuShopGoodsVo;
import org.dromara.zhishu.mapper.RunningTaskByShopMapper;
import org.dromara.zhishu.mapper.ShopMapper;
import org.dromara.zhishu.service.IRunningTaskByShopService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;  // 检查集合是否为空

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 执行的任务Service业务层处理
 *
 * @author yxy
 * @date 2025-08-5
 */
@RequiredArgsConstructor
@Service
public class RunningTaskByShopServiceImpl implements IRunningTaskByShopService {

    private final RunningTaskByShopMapper baseMapper;

    private final ShopMapper shopMapper;
    private final StringRedisTemplate stringRedisTemplate;

    @DS("slave")
    @Override
    public List<Map> selectGetShopGoodsList(String tableName,String isOnsale,String isbn,String priceDown,String priceUp,String startDate,String endDate, Long pageNum, Long pageSize,String goodsName,String stockDown,String stockUp,String trilateralId,String goodsCode,String skuCode) {

        Long priceUpLong = null;
        Long priceDownLong = null;
        if (priceUp != null && StringUtils.isNotEmpty(priceUp)){
            priceUpLong = Long.parseLong(new BigDecimal(priceUp).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        if (priceDown != null && StringUtils.isNotEmpty(priceDown)){
            priceDownLong = Long.parseLong(new BigDecimal(priceDown).multiply(new BigDecimal(100)).toBigInteger().toString());
        }


        return baseMapper.selectGetShopGoodsList(tableName,isOnsale,isbn,priceDownLong,priceUpLong,startDate,endDate, pageNum, pageSize, goodsName, stockDown, stockUp, trilateralId, goodsCode, skuCode);
    }

    @DS("slave")
    @Override
    public int selectGetShopGoodsListCount(String tableName,String isOnsale,String isbn,String priceDown,String priceUp,String startDate,String endDate,String goodsName,String stockDown,String stockUp,String trilateralId,String goodsCode,String skuCode) {

        Long priceUpLong = null;
        Long priceDownLong = null;
        if (priceUp != null && StringUtils.isNotEmpty(priceUp)){
            priceUpLong = Long.parseLong(new BigDecimal(priceUp).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        if (priceDown != null && StringUtils.isNotEmpty(priceDown)){
            priceDownLong = Long.parseLong(new BigDecimal(priceDown).multiply(new BigDecimal(100)).toBigInteger().toString());
        }

        return baseMapper.selectGetShopGoodsListCount(tableName,isOnsale,isbn,priceDownLong,priceUpLong,startDate,endDate, goodsName, stockDown, stockUp, trilateralId, goodsCode, skuCode);
    }

    @DS("slave")
    @Override
    public List<Map> selectGetShopGoodsListByDto(RunningTaskShopGoodsDto runningTaskShopGoodsDto){
        Long priceUpLong = null;
        Long priceDownLong = null;
        if (runningTaskShopGoodsDto.getPriceUp() != null){
            priceUpLong = Long.parseLong(new BigDecimal(runningTaskShopGoodsDto.getPriceUp()).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        if (runningTaskShopGoodsDto.getPriceDown() != null){
            priceDownLong = Long.parseLong(new BigDecimal(runningTaskShopGoodsDto.getPriceDown()).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        runningTaskShopGoodsDto.setPriceUp(priceUpLong);
        runningTaskShopGoodsDto.setPriceDown(priceDownLong);
        return baseMapper.selectGetShopGoodsListByDto(runningTaskShopGoodsDto);
    }

    @DS("slave")
    @Override
    public int selectNumByIsbn(String tableName, String isbn){
        return baseMapper.selectNumByIsbn(tableName,isbn);
    }


    @DS("slave")
    @Override
    public int selectGetShopGoodsNum(String tableName,String isOnSale,String isbn,String priceDown,String priceUp,String startDate,String endDate,String goodsName,String stockDown,String stockUp,String trilateralId,String goodsCode,String skuCode) {
        Long priceUpLong = null;
        Long priceDownLong = null;
        if (priceUp != null && StringUtils.isNotEmpty(priceUp)){
            priceUpLong = Long.parseLong(new BigDecimal(priceUp).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        if (priceDown != null && StringUtils.isNotEmpty(priceDown)){
            priceDownLong = Long.parseLong(new BigDecimal(priceDown).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        return baseMapper.selectGetShopGoodsNum(tableName,isOnSale,isbn,priceDownLong,priceUpLong,startDate,endDate, goodsName, stockDown, stockUp, trilateralId, goodsCode, skuCode);
    }

    @DS("slave")
    @Override
    public int delShopGoods(String tableName,String isOnSale,String isbn,String priceDown,String priceUp,String startDate,String endDate){
        Long priceUpLong = null;
        Long priceDownLong = null;
        if (priceUp != null && StringUtils.isNotEmpty(priceUp)){
            priceUpLong = Long.parseLong(new BigDecimal(priceUp).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        if (priceDown != null && StringUtils.isNotEmpty(priceDown)){
            priceDownLong = Long.parseLong(new BigDecimal(priceDown).multiply(new BigDecimal(100)).toBigInteger().toString());
        }
        return baseMapper.delShopGoods(tableName,isOnSale,isbn,priceDownLong,priceUpLong,startDate,endDate);
    }

    @DS("slave")
    @Override
    public int selectByTrilateralId(String tableName, String trilateralId) {
        return baseMapper.selectByTrilateralId(tableName, trilateralId);
    }

    @DS("slave")
    @Override
    public RunningTask selectVoByTrilateralId(String tableName,String trilateralId){
        return baseMapper.selectVoByTrilateralId(tableName,trilateralId);
    }

    @DS("slave")
    @Override
    public String selectLastFinishTime(String tableName){
        return baseMapper.selectLastFinishTime(tableName);
    }

    @DS("slave")
    @Override
    public List<RunningTask> selectByIsbn(String tableName,String isbn){
        return baseMapper.selectByIsbn(tableName,isbn);
    }

    @DS("slave")
    @Override
    public List<RunningTaskNumVo> selectTaskShopNum(String tableName,Long taskId) {
        return baseMapper.selectTaskShopNum(tableName,taskId);
    }

    @DS("slave")
    @Override
    public int selectGetShopGoodsNumByTasKId(String tableName, String taskId) {
        return baseMapper.selectGetShopGoodsNumByTasKId(tableName, taskId);
    }

    @DS("slave")
    @Override
    public String selectStatus(String tableName) {
        int num = checkTableExists(tableName);
        if (num == 0) {
            return "3";
        }
        String status = baseMapper.selectStatus(tableName);
        if (status == null || StringUtils.isEmpty(status) || status.equals("3")) {
            return "3";
        } else {
            return status;
        }
    }

    @DS("slave")
    @Override
    public List<SuccessDataItemDto> selectRepeatNoPage(String tableName){
        List<SuccessDataItemDto> mapList = baseMapper.selectRepeat(tableName);
        // 按ISBN分组，计算每个ISBN需要保留的记录数
        Map<String, Long> isbnCounts = mapList.stream()
                .collect(Collectors.groupingBy(
                        m -> m.getIsbn().toString(),
                        Collectors.counting()
                ));

        // 收集需要保留的记录
        Map<String, Integer> keptCounts = new HashMap<>();
        List<SuccessDataItemDto> result = new ArrayList<>();

        for (SuccessDataItemDto item : mapList) {
            String isbn = item.getIsbn().toString();
            long total = isbnCounts.get(isbn);
            int kept = keptCounts.getOrDefault(isbn, 0);

            if (kept < total - 1) { // 保留n-1条
                result.add(item);
                keptCounts.put(isbn, kept + 1);
            }
        }
        return result;
    }

    @DS("slave")
    @Override
    public List<SuccessDataItemDto> selectShopGoodsList(ErpGoodsDto erpGoodsDto){
        if (erpGoodsDto.getPriceUp() != null && StringUtils.isNotEmpty(erpGoodsDto.getPriceUp())){
            erpGoodsDto.setPriceUp(new BigDecimal(erpGoodsDto.getPriceUp()).multiply(new BigDecimal(100)).toString());
        }
        if (erpGoodsDto.getPriceDown() != null && StringUtils.isNotEmpty(erpGoodsDto.getPriceDown())){
            erpGoodsDto.setPriceDown(new BigDecimal(erpGoodsDto.getPriceDown()).multiply(new BigDecimal(100)).toString());
        }
        return baseMapper.selectShopGoodsList(erpGoodsDto);
    }

    /**
     * kfz专用导出店铺商品数据
     * @param erpGoodsDto
     * @return
     */
    @DS("slave")
    @Override
    public List<SuccessDataKfz> selectKfzShopGoodsList(ErpGoodsDto erpGoodsDto){
        if (erpGoodsDto.getPriceUp() != null && StringUtils.isNotEmpty(erpGoodsDto.getPriceUp())){
            erpGoodsDto.setPriceUp(new BigDecimal(erpGoodsDto.getPriceUp()).multiply(new BigDecimal(100)).toString());
        }
        if (erpGoodsDto.getPriceDown() != null && StringUtils.isNotEmpty(erpGoodsDto.getPriceDown())){
            erpGoodsDto.setPriceDown(new BigDecimal(erpGoodsDto.getPriceDown()).multiply(new BigDecimal(100)).toString());
        }
        return baseMapper.selectKfzShopGoodsList(erpGoodsDto);
    }

    @DS("slave")
    @Override
    public Page<SuccessDataItemDto> selectRepeat(String tableName,Long pageNum,Long pageSize){
        Page<SuccessDataItemDto> page = new Page<>(pageNum, pageSize);
        List<SuccessDataItemDto> mapList = baseMapper.selectRepeat(tableName);
        if (CollectionUtils.isEmpty(mapList)) {
            return page;
        }

        // 按ISBN分组，计算每个ISBN需要保留的记录数
        Map<String, Long> isbnCounts = mapList.stream()
                .collect(Collectors.groupingBy(
                        m -> m.getIsbn().toString(),
                        Collectors.counting()
                ));

        // 收集需要保留的记录
        Map<String, Integer> keptCounts = new HashMap<>();
        List<SuccessDataItemDto> result = new ArrayList<>();

        for (SuccessDataItemDto item : mapList) {
            String isbn = item.getIsbn().toString();
            long total = isbnCounts.get(isbn);
            int kept = keptCounts.getOrDefault(isbn, 0);

            if (kept < total - 1) { // 保留n-1条
                result.add(item);
                keptCounts.put(isbn, kept + 1);
            }
        }

        // 使用MyBatis-Plus的Page对象
        page.setTotal(result.size());

        int fromIndex = (pageNum.intValue() - 1) * pageSize.intValue();
        int toIndex = Math.min(fromIndex + pageSize.intValue(), result.size());

        if (fromIndex > result.size()) {
            page.setRecords(Collections.emptyList());
        } else {
            page.setRecords(result.subList(fromIndex, toIndex));
        }

        return page;
    }

    @DS("slave")
    @Override
    public int checkTableExists(String tableName) {
        return baseMapper.checkTableExists(tableName);
    }

    @DS("slave")
    @Override
    public void createTable(String tableName) {
        baseMapper.createTable(tableName);
    }

    @DS("slave")
    @Override
    public void insert(String tableName, RunningTask task) {
        baseMapper.insert(tableName, task);
    }

    @DS("slave")
    @Override
    public void update(String tableName, RunningTask task) {
        baseMapper.update(tableName, task);
    }

    @DS("slave")
    @Override
    public void batchInsert(String tableName, List<RunningTask> list) {
        baseMapper.batchInsert(tableName, list);
    }


    @DS("slave")
    @Override
    public void updateStatus(String tableName) {
        baseMapper.updateStatus(tableName);
    }

    @DS("slave")
    @Override
    public void deleteAll(String tableName) {
        baseMapper.deleteAll(tableName);
    }

    @DS("slave")
    @Override
    public void deleteByStatus(String tableName,String status){
        baseMapper.deleteByStatus(tableName,status);
    }

    @DS("slave")
    @Override
    public void deleteByTaskId(String tableName,String taskId){
        baseMapper.deleteByTaskId(tableName,taskId);
    }

    @DS("slave")
    @Override
    public void deleteByGoodsId(String tableName, String goodsId) {
        baseMapper.deleteByGoodsId(tableName, goodsId);
    }

    @DS("slave")
    @Override
    public List<SuccessDataItemDto> selectOnSaleGoodsId(String tableName) {
        return baseMapper.selectOnSaleGoodsId(tableName);
    }

    @DS("slave")
    @Override
    public List<SuccessDataItemDto> selectByGoodsId(String tableName, String trilateralId) {
        return baseMapper.selectByGoodsId(tableName, trilateralId);
    }

    @DS("slave")
    @Override
    public void updateSuccessDataById( String tableName,  String id, String successDataJsonStr) {
        baseMapper.updateSuccessDataById(tableName, id, successDataJsonStr);
    }
    @DS("slave")
    @Override
    public List<Map> getShopGoodsList(String tableName) {
        return baseMapper.getShopGoodsList(tableName);
    }
    @DS("slave")
    @Override
    public Integer getShopGoodsTotalNum(String tableName) {
        return baseMapper.getShopGoodsTotalNum(tableName);
    }

    @DS("slave")
    @Override
    public Integer getShopGoodsTotalNumByTaskId(String tableName,Long taskId){
        return baseMapper.getShopGoodsTotalNumByTaskId(tableName,taskId);
    }

    @DS("slave")
    @Override
    public  Map<String, Boolean>  batchCheckGoodsIdExists(String tableName, List<String> goodsIds) {
        if (goodsIds.isEmpty()) {
            return new HashMap<>();
        }

        // 分批处理，避免IN条件过长
        List<List<String>> batches = Lists.partition(goodsIds, 1000);
        Map<String, Boolean> result = new ConcurrentHashMap<>();

        batches.parallelStream().forEach(batch -> {
            List<Map<String, Object>> existsList = baseMapper.batchCheckExists(tableName, batch);
            existsList.forEach(item -> {
                String goodsId = item.get("goods_id").toString();
                Boolean exists = "1".equals(item.get("exists_flag").toString());
                result.put(goodsId, exists);
            });
        });

        return result;
    }

    @Override
    @DS("slave")
    public List<Map> selectGetShopGoodsListAll(String tableName, String isOnsale, Long pageNum, Long pageSize) {
        return baseMapper.selectGetShopGoodsListAll(tableName,isOnsale, pageNum, pageSize);
    }

    @DS("slave")
    @Override
    public Integer countAll(String tableName) {
        return baseMapper.countAll(tableName);
    }

    /**
     * 批量查询goods_id是否存在，返回存在的goods_id列表
     * @param tableName
     * @param goodsIds
     * @return
     */
    @DS("slave")
    @Override
    public List<Long> batchSelectExistsByGoodsIds(String tableName,List<Long> goodsIds){
        return baseMapper.batchSelectExistsByGoodsIds(tableName,goodsIds);
    }

    @DS("slave")
    @Override
    public Map<String, Object> selectTodayGoods(List<String> shopId) {

        /** 等待修改读取缓存中的数据 */

        Map<String, Object> resMap = new HashMap<>();

        if (CollectionUtils.isEmpty(shopId)) {
            System.out.println("用户无关联店铺，返回空数据");
            resMap.put("todayPublishGoods", 0);
            resMap.put("todayUpdateGoods", 0);
            resMap.put("todayDeleteGoods", 0);
            return resMap;
        }

        String startTime = LocalDate.now().atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String endTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 初始化统计变量
        int todayPublishGoods = 0;
        int todayEditGoodsTotal = 0;
        int todayDelGoodsTotal = 0;

        int processedTables = 0;
        int skippedTables = 0;

        long startTimeMs = System.currentTimeMillis();

        for (String shopIdStr : shopId) {
            String tableName = "t_running_task_" + shopIdStr;

            try {
                int checkMark = baseMapper.checkTableExists(tableName);
                if (checkMark == 0) {
                    skippedTables++;
                    continue;
                }

                Map<String, Object> res = baseMapper.selectTodayGoods(tableName, startTime, endTime);
                processedTables++;

                // 安全转换每个店铺的结果
                if (res != null) {
                    todayPublishGoods += safeConvertToInt(res.get("todayPublishGoods"));
                    todayEditGoodsTotal += safeConvertToInt(res.get("todayEditGoods"));
                    todayDelGoodsTotal += safeConvertToInt(res.get("todayDelGoods"));
                }
            } catch (Exception e) {
                System.out.printf("查询店铺今日商品数据异常，店铺ID: %d, 表名: %s, 异常信息: %s",
                        Long.parseLong(shopIdStr), tableName, e.getMessage());
            }
        }

        long endTimeMs = System.currentTimeMillis();

        // 将统计结果放入返回map
        resMap.put("todayPublishGoods", todayPublishGoods);
        resMap.put("todayUpdateGoods", todayEditGoodsTotal);
        resMap.put("todayDeleteGoods", todayDelGoodsTotal);

        // 添加性能统计信息（可选）
        resMap.put("_stats", Map.of(
                "processedTables", processedTables,
                "skippedTables", skippedTables,
                "queryTimeMs", endTimeMs - startTimeMs
        ));

        System.out.printf("今日商品数据查询完成: 发布=%d, 修改=%d, 删除=%d, 处理表=%d, 跳过表=%d, 耗时=%dms%n",
                todayPublishGoods, todayEditGoodsTotal, todayDelGoodsTotal,
                processedTables, skippedTables, endTimeMs - startTimeMs);

        return resMap;
    }

    // 安全类型转换方法
    private int safeConvertToInt(Object value) {
        if (value == null) return 0;
        if (value instanceof Integer) return (Integer) value;
        if (value instanceof Long) return ((Long) value).intValue();
        if (value instanceof BigDecimal) return ((BigDecimal) value).intValue();
        if (value instanceof BigInteger) return ((BigInteger) value).intValue();
        if (value instanceof Number) return ((Number) value).intValue();
        try {
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    @DS("slave")
    @Override
    public Map<String, Object> selectTodaySales(List<String> shopId) {
        Map<String, Object> resMap = new HashMap<>();

        if (CollectionUtils.isEmpty(shopId)) {
            System.out.println("用户无关联店铺，返回空数据");
            resMap.put("todayOrder", 0);
            resMap.put("turnover", 0);
            return resMap;
        }

        String todayDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        int todayOrderTotal = 0;
        double profitTotal = 0.0;

        for (String shopIdStr : shopId) {
            try {
                String orderCountKey = "order_count_" + todayDate + "_" + shopIdStr;
                String orderAmountKey = "order_amount_" + todayDate + "_" + shopIdStr;

                String orderCountStr = stringRedisTemplate.opsForValue().get(orderCountKey);
                String orderAmountStr = stringRedisTemplate.opsForValue().get(orderAmountKey);

                if (StringUtils.isNotEmpty(orderCountStr)) {
                    todayOrderTotal += Integer.parseInt(orderCountStr);
                }

                // 累加订单金额（利润）
                if (StringUtils.isNotEmpty(orderAmountStr)) {
                    profitTotal += Double.parseDouble(orderAmountStr);
                }

            } catch (Exception e) {
                System.out.printf("读取Redis数据异常，店铺ID: %s, 异常信息: %s%n", shopIdStr, e.getMessage());
            }
        }

        // 将统计结果放入返回map
        resMap.put("todayOrder", todayOrderTotal);
        resMap.put("turnover", profitTotal);

        System.out.printf("今日销售数据查询完成: 订单数=%d, 利润=%.2f%n", todayOrderTotal, profitTotal);

        return resMap;
    }

}
