package cn.iocoder.yudao.module.member.service.storegoodsinventoryrecord;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.storegoods.vo.StoreSaleGoodsPageVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoodsinventoryrecord.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.storegoodsinventoryrecord.StoreGoodsInventoryRecordDO;
import cn.iocoder.yudao.module.member.dal.mysql.storegoodsinventoryrecord.StoreGoodsInventoryRecordMapper;
import cn.iocoder.yudao.module.member.enums.InventoryTypeEnum;
import cn.iocoder.yudao.module.member.util.MemberTimeUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

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

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.STORE_GOODS_INVENTORY_RECORD_NOT_EXISTS;

/**
 * 商品出入库记录 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class StoreGoodsInventoryRecordServiceImpl implements StoreGoodsInventoryRecordService {

    @Resource
    private StoreGoodsInventoryRecordMapper storeGoodsInventoryRecordMapper;

    @Override
    public Integer createStoreGoodsInventoryRecord(StoreGoodsInventoryRecordSaveReqVO createReqVO) {
        // 插入
        StoreGoodsInventoryRecordDO storeGoodsInventoryRecord = BeanUtils.toBean(createReqVO, StoreGoodsInventoryRecordDO.class);
        storeGoodsInventoryRecordMapper.insert(storeGoodsInventoryRecord);
        // 返回
        return storeGoodsInventoryRecord.getId();
    }

    @Override
    public void updateStoreGoodsInventoryRecord(StoreGoodsInventoryRecordSaveReqVO updateReqVO) {
        // 校验存在
        validateStoreGoodsInventoryRecordExists(updateReqVO.getId());
        // 更新
        StoreGoodsInventoryRecordDO updateObj = BeanUtils.toBean(updateReqVO, StoreGoodsInventoryRecordDO.class);
        storeGoodsInventoryRecordMapper.updateById(updateObj);
    }

    @Override
    public void deleteStoreGoodsInventoryRecord(Integer id) {
        // 校验存在
        validateStoreGoodsInventoryRecordExists(id);
        // 删除
        storeGoodsInventoryRecordMapper.deleteById(id);
    }

    private void validateStoreGoodsInventoryRecordExists(Integer id) {
        if (storeGoodsInventoryRecordMapper.selectById(id) == null) {
            throw exception(STORE_GOODS_INVENTORY_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public StoreGoodsInventoryRecordDO getStoreGoodsInventoryRecord(Integer id) {
        return storeGoodsInventoryRecordMapper.selectById(id);
    }

    @Override
    public PageResult<StoreGoodsInventoryRecordDO> getStoreGoodsInventoryRecordPage(StoreGoodsInventoryRecordPageReqVO pageReqVO) {
        return storeGoodsInventoryRecordMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<InventoryRecordPageVO> getRecordPage(InventoryRecordPageReqVO pageReqVO) {
        LocalDate now = LocalDate.now();
        LocalDateTime dayStart = now.atStartOfDay();
        LocalDateTime dayEnd = now.atTime(LocalTime.MAX);
        if (StrUtil.isNotBlank(pageReqVO.getStartTime())) {
            dayStart =MemberTimeUtils.getDayStart(pageReqVO.getStartTime());
            dayEnd = MemberTimeUtils.getDayEnd(pageReqVO.getEndTime());
        }
        LambdaQueryWrapper<StoreGoodsInventoryRecordDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(pageReqVO.getGoodsName()),StoreGoodsInventoryRecordDO::getGoodsName, pageReqVO.getGoodsName());
        wrapper.between(StoreGoodsInventoryRecordDO::getCreateTime, dayStart, dayEnd);
        wrapper.eq(pageReqVO.getCarteenId()!=null,StoreGoodsInventoryRecordDO::getCarteenId, pageReqVO.getCarteenId());
        wrapper.orderByDesc(StoreGoodsInventoryRecordDO::getGoodsId);
        List<StoreGoodsInventoryRecordDO> list = storeGoodsInventoryRecordMapper.selectList(wrapper);

        // 分组并合并
        List<InventoryRecordPageVO> summaries = list.stream()
                .collect(Collectors.groupingBy(
                        record -> Arrays.asList(record.getCarteenId(),record.getCreateTime().toLocalDate(),record.getGoodsName(), record.getPrice()), // 按商品名称、价格和日期分组
                        Collectors.toList()
                ))
                .entrySet()
                .stream()
                .map(entry -> {
                    // 获取分组的键和值
                    List<? extends Comparable<? extends Comparable<?>>> key = entry.getKey();
                    Long carteenId = (Long) key.get(0);
                    LocalDate date = (LocalDate) key.get(1);
                    String productName = (String) key.get(2);
                    double price = (Double) key.get(3);
                    List<StoreGoodsInventoryRecordDO> productRecords = entry.getValue();

                    // 计算入库和出库总数
                    int totalInbound = productRecords.stream()
                            .filter(vo->vo.getType().equals(InventoryTypeEnum.IN.getCode()))
                            .mapToInt(StoreGoodsInventoryRecordDO::getNumber)
                            .sum();

                    int totalOutbound = productRecords.stream()
                            .filter(vo->vo.getType().equals(InventoryTypeEnum.OUT.getCode()))
                            .mapToInt(StoreGoodsInventoryRecordDO::getNumber)
                            .sum();
                    InventoryRecordPageVO recordPageVO = new InventoryRecordPageVO();
                    recordPageVO.setGoodsId(productRecords.get(0).getGoodsId());
                    recordPageVO.setGoodsName(productName);
                    recordPageVO.setCarteenId(carteenId);
                    recordPageVO.setPrice(price);
                    recordPageVO.setInNumber(totalInbound);
                    recordPageVO.setInPrice(NumberUtil.round(totalInbound * price,2).doubleValue());
                    recordPageVO.setOutNumber(totalOutbound);
                    recordPageVO.setOutPrice(NumberUtil.round(totalOutbound * price,2).doubleValue());
                    recordPageVO.setCreateTime(date.atStartOfDay());
                    return recordPageVO;
                })
                .collect(Collectors.toList());

        // 按时间和商品名称排序
        List<InventoryRecordPageVO> sortedSummaries = summaries.stream()
                .sorted(Comparator
                        .comparing(InventoryRecordPageVO::getCarteenId)           // 先按门店升序排序
                        .thenComparing(InventoryRecordPageVO::getCreateTime,Comparator.reverseOrder())           // 先按时间降序排序
                        .thenComparing(InventoryRecordPageVO::getGoodsId) // 再按商品Id升序排序
                )
                .collect(Collectors.toList());

        // 分页
        List<InventoryRecordPageVO> paginatedSummaries = paginate(sortedSummaries, pageReqVO.getPageNo(), pageReqVO.getPageSize());

        return new PageResult<>(paginatedSummaries, (long) summaries.size());
    }


    public static List<InventoryRecordPageVO> paginate(List<InventoryRecordPageVO> summaries, int pageNumber, int pageSize) {
        // 计算起始位置
        int skip = (pageNumber - 1) * pageSize;

        // 如果超出范围，返回空列表
        if (skip >= summaries.size()) {
            return Collections.emptyList();
        }

        // 执行分页
        return summaries.stream()
                .skip(skip) // 跳过前面 (pageNumber - 1) * pageSize 条记录
                .limit(pageSize) // 限制返回 pageSize 条记录
                .collect(Collectors.toList());
    }

    @Override
    public InventoryStatisticsVO getRecordCount(InventoryRecordPageReqVO pageReqVO) {
        Double totalInMoney = storeGoodsInventoryRecordMapper.count(InventoryTypeEnum.IN.getCode(), pageReqVO);
        Double totalOutMoney = storeGoodsInventoryRecordMapper.count(InventoryTypeEnum.OUT.getCode(), pageReqVO);
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        pageReqVO.setStartTime(today);
        pageReqVO.setEndTime(today);
        Double todayInMoney = storeGoodsInventoryRecordMapper.count(InventoryTypeEnum.IN.getCode(), pageReqVO);
        Double todayOutMoney = storeGoodsInventoryRecordMapper.count(InventoryTypeEnum.OUT.getCode(), pageReqVO);
        return new InventoryStatisticsVO(totalInMoney, totalOutMoney, todayInMoney, todayOutMoney);
    }
}