package com.yiqi.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yiqi.common.enums.ClothOrderStatusType;
import com.yiqi.common.enums.SourceType;
import com.yiqi.common.enums.StatusType;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.core.domain.SettlementStoreClothStatistics;
import com.yiqi.core.service.ISettlementStoreClothStatisticsService;
import com.yiqi.order.domain.OrderCloth;
import com.yiqi.order.domain.dto.SettlementFactoryStatisticsDto;
import com.yiqi.core.service.ISettlementFactoryStatisticsService;
import com.yiqi.order.domain.OrderClothItem;
import com.yiqi.order.service.IOrderClothItemService;
import com.yiqi.order.service.IOrderClothService;
import com.yiqi.settlement.service.ISettlementFactoryRateService;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.IManageFactoryService;
import com.yiqi.system.service.ISysStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 门店每日统计Service业务层处理
 *
 * @author douya
 * @date 2025-03-21
 */
@Slf4j
@Service
public class SettlementFactoryStatisticsServiceImpl implements ISettlementFactoryStatisticsService {

    @Autowired
    private IOrderClothService orderClothService;

    @Autowired
    private IOrderClothItemService orderClothItemService;

    @Autowired
    private IManageFactoryService manageFactoryService;

    @Autowired
    private ISettlementStoreClothStatisticsService settlementStoreClothStatisticsService;

    @Autowired
    private ISysStoreService storeService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateDayStatistics(Date date) {
        // 1. 获取所有有效门店
        List<SysStore> storeList = storeService.list(new QueryWrapper<SysStore>().lambda()
                .eq(SysStore::getDelFlag, StatusType.OK.getCode())
                .eq(SysStore::getStatus, StatusType.OK.getCode())
        );
        if (CollUtil.isEmpty(storeList)) {
            return;
        }
        // 2. 遍历门店生成统计数据
        List<SettlementStoreClothStatistics> statisticsList = new ArrayList<>();
        for (SysStore store : storeList) {
            SettlementFactoryStatisticsDto settlementFactoryStatisticsDto =
                    generateTotalFactoryStatistics(store.getFactoryId(), store.getId(), DateUtils.getStartTime(date), DateUtils.getEndTime(date));
            SettlementStoreClothStatistics statistics = generateTotalClothStatistics(store.getFactoryId(), store.getId(), date);
            BeanUtil.copyProperties(settlementFactoryStatisticsDto, statistics);
            statistics.setId(null);
            statistics.setFactoryId(store.getFactoryId());
            statistics.setStoreId(store.getId());
            statistics.setStoreName(store.getName());
            statistics.setCreateTime(DateUtils.getNowDate());
            statistics.setDay(Integer.valueOf(DateUtil.format(date, "yyyyMMdd")));
            statisticsList.add(statistics);
        }
        // 3. 删除原有统计数据
        settlementStoreClothStatisticsService.remove(new QueryWrapper<SettlementStoreClothStatistics>().lambda()
                .eq(SettlementStoreClothStatistics::getDay, Integer.valueOf(DateUtil.format(date, "yyyyMMdd"))));
        // 3. 批量插入统计数据
        settlementStoreClothStatisticsService.saveBatch(statisticsList);
    }

    @Override
    public List<SettlementFactoryStatisticsDto> generateFactoryStatisticsByDate(Long factoryId, Long storeId, Date start, Date end, Integer pageNum, Integer pageSize) {
        // 1. 获取日期范围内的所有日期
        List<Date> dateList = new ArrayList<>();
        Date currentDate = end;
        while (currentDate.after(start)) {
            dateList.add(currentDate);
            currentDate = DateUtils.addDays(currentDate, -1);
        }
        List<SettlementFactoryStatisticsDto> statisticsList = new ArrayList<>();
        // 3. 为每个日期生成统计数据
        for (Date date : dateList) {
            SettlementFactoryStatisticsDto statistics = settlementStoreClothStatisticsService.totalByConditionByDate(factoryId, null, date);
            statistics.setStatisticsDate(DateUtil.formatDate(date));
            statisticsList.add(statistics);
        }
        return statisticsList;
    }

    @Override
    public List<SettlementFactoryStatisticsDto> generateFactoryStatisticsByStoreId(Long factoryId, Long storeId, Date start, Date end) {
        // 1. 获取所有有效门店
        QueryWrapper<SysStore> storeWrapper = new QueryWrapper<>();
        storeWrapper.eq("del_flag", StatusType.OK.getCode());
        storeWrapper.gt("id", 0);
        if (storeId != null) {
            storeWrapper.eq("id", storeId);
        }
        if (factoryId != null) {
            storeWrapper.eq("factory_id", factoryId);
        }
        List<SysStore> storeList = storeService.list(storeWrapper);
        if (CollUtil.isEmpty(storeList)) {
            return Collections.emptyList();
        }

        List<SettlementFactoryStatisticsDto> statisticsList = new ArrayList<>();

        // 4. 为每个门店生成统计数据
        for (SysStore store : storeList) {
            SettlementFactoryStatisticsDto statistics = settlementStoreClothStatisticsService.totalByCondition(factoryId, store.getId(), start, end);
            statistics.setStoreName(store.getName());
            statisticsList.add(statistics);
        }
        statisticsList.sort(Comparator.comparing(SettlementFactoryStatisticsDto::getReceiveOrderCount, Comparator.reverseOrder()));
        return statisticsList;
    }

    @Override
    public SettlementFactoryStatisticsDto generateTotalFactoryStatistics(Long factoryId, Long storeId, Date start, Date end) {
        // 1. 查询指定日期范围内的所有订单衣服记录
        QueryWrapper<OrderClothItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(factoryId!=null,"factory_id", factoryId)
                .eq(storeId != null, "org_id", storeId)
                .ge("flow_status", 1)
                .ge("in_factory_time", DateUtils.addDays(start, -2))
                .le("in_factory_time", DateUtils.addDays(end, 2))
                .ge("create_time", DateUtils.addDays(start, -5));

        List<OrderClothItem> clothItems = orderClothItemService.list(queryWrapper);
        if (CollUtil.isEmpty(clothItems)) {
            log.info("没有衣服订单 {} between {} and {}", factoryId, start, end);
            return null;
        }

        SettlementFactoryStatisticsDto statistics = new SettlementFactoryStatisticsDto();
        statistics.setFactoryId(factoryId);
        statistics.setStoreId(storeId);
        statistics.setStatisticsDate(DateUtil.formatDate(start) + " 至 " + DateUtil.formatDate(end));

        // 2. 统计总入厂衣服
        List<OrderClothItem> inFactoryItems = clothItems.stream()
                .filter(item -> item.getInFactoryTime() != null &&
                        !item.getInFactoryTime().before(start) &&
                        !item.getInFactoryTime().after(end))
                .collect(Collectors.toList());

        statistics.setDailyInFactoryCount(inFactoryItems.size());
        statistics.setDailyInFactoryAmount(inFactoryItems.stream()
                .map(OrderClothItem::getTotalPrice)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));

        // 3. 统计总检查衣服
        statistics.setDailyCheckedCount((int) clothItems.stream()
                .filter(item -> item.getCheckClothTime() != null &&
                        !item.getCheckClothTime().before(start) &&
                        !item.getCheckClothTime().after(end))
                .count());

        // 4. 统计总出厂衣服
        statistics.setDailyOutFactoryCount((int) clothItems.stream()
                .filter(item -> item.getOutFactoryTime() != null &&
                        !item.getOutFactoryTime().before(start) &&
                        !item.getOutFactoryTime().after(end))
                .count());

        // 5. 统计总退单
        List<OrderClothItem> refundItems = clothItems.stream()
                .filter(item -> item.getRefundTime() != null &&
                        !item.getRefundTime().before(start) &&
                        !item.getRefundTime().after(end))
                .collect(Collectors.toList());

        statistics.setDailyRefundCount(refundItems.size());
        statistics.setDailyRefundAmount(refundItems.stream()
                .map(OrderClothItem::getTotalPrice)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add));

        // 6. 计算总实际结算金额
        statistics.setDailyActualSettlementAmount(
                statistics.getDailyInFactoryAmount().subtract(statistics.getDailyRefundAmount()));

        return statistics;
    }

    /**
     * 生成取收衣统计
     *
     * @param factoryId 工厂ID
     * @param storeId 门店ID
     * @param date 统计日期
     * @return SettlementStoreClothStatistics 统计结果
     */
    public SettlementStoreClothStatistics generateTotalClothStatistics(Long factoryId, Long storeId, Date date) {
        // 统计结果对象
        SettlementStoreClothStatistics statistics = new SettlementStoreClothStatistics();

        // 1. 收衣相关（set_price_time为当日）
        Date startOfDay = DateUtils.getStartTime(date);
        Date endOfDay = DateUtils.getEndTime(date);

        QueryWrapper<OrderCloth> receiveOrderWrapper = new QueryWrapper<>();
        receiveOrderWrapper.eq("factory_id", factoryId)
                .eq("org_id", storeId)
                .eq("del_flag", "0")
                .ge("set_price_time", startOfDay)
                .le("set_price_time", endOfDay)
                .ge("create_time", DateUtils.addDays(startOfDay, -5));

        List<OrderCloth> receiveOrders = orderClothService.list(receiveOrderWrapper);

        // 收衣订单数
        statistics.setReceiveOrderCount(receiveOrders.size());
        // 收衣总件数
        int receiveTotalQuantity = receiveOrders.stream()
                .mapToInt(o -> o.getOrderClothCount() == null ? 0 : o.getOrderClothCount())
                .sum();
        statistics.setReceiveTotalQuantity(receiveTotalQuantity);
        // 收衣订单总金额
        BigDecimal receiveTotalAmount = receiveOrders.stream()
                .map(o -> o.getOrderAmount() == null ? BigDecimal.ZERO : o.getOrderAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setReceiveTotalAmount(receiveTotalAmount);
        // 收衣未支付订单数
        List<OrderCloth> receiveUnpaidOrders = receiveOrders.stream()
                .filter(o -> o.getPayTime() == null)
                .collect(Collectors.toList());
        statistics.setReceiveUnpaidOrderCount(receiveUnpaidOrders.size());
        // 收衣未支付订单金额
        BigDecimal receiveUnpaidAmount = receiveUnpaidOrders.stream()
                .map(o -> o.getOrderAmount() == null ? BigDecimal.ZERO : o.getOrderAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setReceiveUnpaidAmount(receiveUnpaidAmount);

        // 2. 取衣相关（OrderClothItem.take_cloth_time为当日）
        QueryWrapper<OrderClothItem> pickupItemWrapper = new QueryWrapper<>();
        pickupItemWrapper.eq("factory_id", factoryId)
                .eq("org_id", storeId)
                .eq("del_flag", "0")
                .ge("take_cloth_time", startOfDay)
                .le("take_cloth_time", endOfDay)
                .ge("create_time", DateUtils.addDays(startOfDay, -10));

        List<OrderClothItem> pickupItems = orderClothItemService.list(pickupItemWrapper);

        // 取衣总件数
        statistics.setPickupTotalQuantity(pickupItems.size());
        // 取衣订单ID集合
        Set<Long> pickupOrderIds = pickupItems.stream()
                .map(OrderClothItem::getOrderId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        // 取衣订单数
        statistics.setPickupOrderCount(pickupOrderIds.size());

        // 查询这些订单
        List<OrderCloth> pickupOrders = new ArrayList<>();
        if (!pickupOrderIds.isEmpty()) {
            pickupOrders = orderClothService.list(new QueryWrapper<OrderCloth>().in("id", pickupOrderIds));
        }
        // 取衣订单总金额
        BigDecimal pickupTotalAmount = pickupOrders.stream()
                .map(o -> o.getOrderAmount() == null ? BigDecimal.ZERO : o.getOrderAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPickupTotalAmount(pickupTotalAmount);

        // 取衣已支付订单（pay_time_type=1 且 pay_time为当日）
        List<OrderCloth> pickupPaidOrders = pickupOrders.stream()
                .filter(o -> "1".equals(o.getPayTimeType())
                        && o.getPayTime() != null
                        && !o.getPayTime().before(startOfDay)
                        && !o.getPayTime().after(endOfDay))
                .collect(Collectors.toList());
        statistics.setPickupPaidOrderCount(pickupPaidOrders.size());
        BigDecimal pickupPaidAmount = pickupPaidOrders.stream()
                .map(o -> o.getOrderAmount() == null ? BigDecimal.ZERO : o.getOrderAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPickupPaidAmount(pickupPaidAmount);
        return statistics;
    }
}
