package com.sckw.report.service.impl;

import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.BaseResult;
import com.sckw.order.api.feign.OrderStatisticsFeignService;
import com.sckw.order.api.model.DailySalesStatisticsDto;
import com.sckw.order.api.model.DailyShipmentStatisticsDto;
import com.sckw.order.api.model.GoodsAmountStatisticsDto;
import com.sckw.order.api.model.GoodsVolumeStatisticsDto;
import com.sckw.report.model.vo.*;
import com.sckw.report.service.KwBiReportService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class KwBiReportServiceImpl implements KwBiReportService {

    @Autowired
    private OrderStatisticsFeignService orderStatisticsFeignService;

    @Override
    public DailyShipmentAmountVo getDailyShipmentAmount() {
        Long entId = LoginUserHolder.getEntId();
        BaseResult<List<DailyShipmentStatisticsDto>> result = orderStatisticsFeignService.getDailyShipmentByCategory(entId, 7);
        
        DailyShipmentAmountVo vo = new DailyShipmentAmountVo();
        List<String> dates = generateLast7Days();
        vo.setDates(dates);

        if (result == null || !result.isSuccess() || result.getData() == null) {
            vo.setCategoryDataList(Collections.emptyList());
            return vo;
        }

        Map<String, Map<String, BigDecimal>> dataMap = result.getData().stream()
                .collect(Collectors.groupingBy(
                        DailyShipmentStatisticsDto::getGoodsType,
                        Collectors.toMap(
                                DailyShipmentStatisticsDto::getOrderDate,
                                DailyShipmentStatisticsDto::getActualAmount,
                                BigDecimal::add
                        )
                ));

        List<DailyShipmentAmountVo.ShipmentCategoryData> categoryDataList = new ArrayList<>();
        dataMap.forEach((category, dateAmountMap) -> {
            DailyShipmentAmountVo.ShipmentCategoryData data = new DailyShipmentAmountVo.ShipmentCategoryData();
            data.setCategoryName(category);
            
            List<BigDecimal> amounts = new ArrayList<>();
            for (String date : dates) {
                amounts.add(dateAmountMap.getOrDefault(date, BigDecimal.ZERO));
            }
            data.setAmounts(amounts);
            categoryDataList.add(data);
        });
        vo.setCategoryDataList(categoryDataList);

        return vo;
    }

    @Override
    public DailySalesAmountVo getDailySalesAmount() {
        Long entId = LoginUserHolder.getEntId();
        BaseResult<List<DailySalesStatisticsDto>> result = orderStatisticsFeignService.getDailySalesByCategory(entId, 7);

        DailySalesAmountVo vo = new DailySalesAmountVo();
        List<String> dates = generateLast7Days();
        vo.setDates(dates);

        if (result == null || !result.isSuccess() || result.getData() == null) {
            vo.setCategoryDataList(Collections.emptyList());
            return vo;
        }

        Map<String, Map<String, BigDecimal>> dataMap = result.getData().stream()
                .collect(Collectors.groupingBy(
                        DailySalesStatisticsDto::getGoodsType,
                        Collectors.toMap(
                                DailySalesStatisticsDto::getOrderDate,
                                DailySalesStatisticsDto::getSalesAmount,
                                BigDecimal::add
                        )
                ));

        List<DailySalesAmountVo.SalesCategoryData> categoryDataList = new ArrayList<>();
        dataMap.forEach((category, dateAmountMap) -> {
            DailySalesAmountVo.SalesCategoryData data = new DailySalesAmountVo.SalesCategoryData();
            data.setCategoryName(category);

            List<BigDecimal> amounts = new ArrayList<>();
            for (String date : dates) {
                amounts.add(dateAmountMap.getOrDefault(date, BigDecimal.ZERO));
            }
            data.setAmounts(amounts);
            categoryDataList.add(data);
        });
        vo.setCategoryDataList(categoryDataList);

        return vo;
    }

    @Override
    public GoodsSalesVolumeRatioVo getGoodsSalesVolumeRatio() {
        Long entId = LoginUserHolder.getEntId();
        BaseResult<List<GoodsVolumeStatisticsDto>> result = orderStatisticsFeignService.getGoodsVolumeTop5(entId);

        GoodsSalesVolumeRatioVo vo = new GoodsSalesVolumeRatioVo();

        if (result == null || !result.isSuccess() || result.getData() == null || result.getData().isEmpty()) {
            vo.setRatioList(Collections.emptyList());
            return vo;
        }

        List<GoodsVolumeStatisticsDto> dataList = result.getData();
        BigDecimal totalVolume = dataList.stream()
                .map(dto -> dto.getTotalVolume() != null ? dto.getTotalVolume() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        List<GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem> ratioList = new ArrayList<>();
        for (GoodsVolumeStatisticsDto dto : dataList) {
            GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem item = new GoodsSalesVolumeRatioVo.GoodsVolumeRatioItem();
            item.setGoodsName(dto.getGoodsName());
            item.setVolume(dto.getTotalVolume() != null ? dto.getTotalVolume() : BigDecimal.ZERO);
            
            BigDecimal percentage = BigDecimal.ZERO;
            if (totalVolume.compareTo(BigDecimal.ZERO) > 0) {
                percentage = item.getVolume().multiply(new BigDecimal("100"))
                        .divide(totalVolume, 2, RoundingMode.HALF_UP);
            }
            item.setPercentage(percentage);
            ratioList.add(item);
        }

        vo.setRatioList(ratioList);
        return vo;
    }

    @Override
    public GoodsSalesAmountRatioVo getGoodsSalesAmountRatio() {
        Long entId = LoginUserHolder.getEntId();
        BaseResult<List<GoodsAmountStatisticsDto>> result = orderStatisticsFeignService.getGoodsAmountTop5(entId);

        GoodsSalesAmountRatioVo vo = new GoodsSalesAmountRatioVo();

        if (result == null || !result.isSuccess() || result.getData() == null || result.getData().isEmpty()) {
            vo.setRatioList(Collections.emptyList());
            return vo;
        }

        List<GoodsAmountStatisticsDto> dataList = result.getData();
        BigDecimal totalAmount = dataList.stream()
                .map(dto -> dto.getTotalAmount() != null ? dto.getTotalAmount() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        List<GoodsSalesAmountRatioVo.GoodsAmountRatioItem> ratioList = new ArrayList<>();
        for (GoodsAmountStatisticsDto dto : dataList) {
            GoodsSalesAmountRatioVo.GoodsAmountRatioItem item = new GoodsSalesAmountRatioVo.GoodsAmountRatioItem();
            item.setGoodsName(dto.getGoodsName());
            item.setAmount(dto.getTotalAmount() != null ? dto.getTotalAmount() : BigDecimal.ZERO);

            BigDecimal percentage = BigDecimal.ZERO;
            if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                percentage = item.getAmount().multiply(new BigDecimal("100"))
                        .divide(totalAmount, 2, RoundingMode.HALF_UP);
            }
            item.setPercentage(percentage);
            ratioList.add(item);
        }

        vo.setRatioList(ratioList);
        return vo;
    }

    private List<String> generateLast7Days() {
        List<String> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd");
        LocalDate today = LocalDate.now();
        
        for (int i = 6; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dates.add(date.format(formatter));
        }
        
        return dates;
    }
}