package com.ruoyi.ss.store.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.dashboard.domain.vo.BillCountVo;
import com.ruoyi.ss.device.domain.DeviceCountVO;
import com.ruoyi.ss.device.domain.DeviceQuery;
import com.ruoyi.ss.device.domain.enums.DeviceGroupBy;
import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus;
import com.ruoyi.ss.device.domain.enums.DeviceStatus;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.store.domain.StoreVo;
import com.ruoyi.ss.store.domain.vo.StoreOperatorVO;
import com.ruoyi.ss.store.service.StoreAssembler;
import com.ruoyi.ss.store.service.StoreValidator;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillGroupBy;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wjh
 * 2024/4/29
 */
@Service
public class StoreAssemblerImpl implements StoreAssembler {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private TransactionBillService transactionBillService;

    @Autowired
    private StoreValidator storeValidator;

    /**
     * 拼接设备数量
     *
     * @param list 店铺列表
     */
    @Override
    public void assembleDeviceCount(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        Map<Long, Integer> countMap = deviceService.selectCountMapByStoreIds(list.stream().map(StoreVo::getStoreId).collect(Collectors.toList()));

        for (StoreVo store : list) {
            Integer count = countMap.get(store.getStoreId());
            store.setDeviceCount(count == null ? 0 : count);
        }
    }

    /**
     * 拼接营收数据
     *
     * @param list
     */
    @Override
    public void assembleRevenue(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        // 本日收入
        this.assembleTodayIncome(list);
        // 本月收入
        this.assembleMonthIncome(list);
        // 上月收入
        this.assembleLastMonthIncome(list);
        // 在线设备数量
        this.assembleOnlineCount(list);
        // 离线设备数量
        this.assembleOfflineCount(list);
    }

    /**
     * 拼接本月收入
     *
     * @param list
     */
    @Override
    public void assembleMonthIncome(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        TransactionBillQuery query = new TransactionBillQuery();
        LocalDate now = LocalDate.now();
        query.setGroupBy(TransactionBillGroupBy.store_id.name());
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList()));
        query.setStatus(TransactionBillStatus.SUCCESS.getStatus());
        query.setType(TransactionBillType.RECHARGE.getType());
        query.setMonth(now.getMonthValue());
        query.setYear(now.getYear());
        Map<Long, BillCountVo> map = transactionBillService.selectCountMap(query, BillCountVo::getStoreId);

        for (StoreVo store : list) {
            BillCountVo count = map.get(store.getStoreId());
            if (count != null) {
                store.setMonthIncome(count.getRecharge());
            } else {
                store.setMonthIncome(BigDecimal.ZERO);
            }
        }
    }

    /**
     * 拼接本日收入
     *
     * @param list
     */
    @Override
    public void assembleTodayIncome(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        TransactionBillQuery query = new TransactionBillQuery();
        query.setGroupBy(TransactionBillGroupBy.store_id.name());
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList()));
        query.setStatus(TransactionBillStatus.SUCCESS.getStatus());
        query.setType(TransactionBillType.RECHARGE.getType());
        query.setCreateDate(DateUtils.getNowDate());
        Map<Long, BillCountVo> map = transactionBillService.selectCountMap(query, BillCountVo::getStoreId);

        for (StoreVo store : list) {
            BillCountVo count = map.get(store.getStoreId());
            if (count != null) {
                store.setTodayIncome(count.getRecharge());
            } else {
                store.setTodayIncome(BigDecimal.ZERO);
            }
        }
    }

    /**
     * 拼接上月收入
     *
     * @param list
     */
    @Override
    public void assembleLastMonthIncome(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        TransactionBillQuery query = new TransactionBillQuery();
        LocalDate lastMonth = LocalDate.now().plusMonths(-1);
        query.setGroupBy(TransactionBillGroupBy.store_id.name());
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).filter(Objects::nonNull).distinct().collect(Collectors.toList()));
        query.setStatus(TransactionBillStatus.SUCCESS.getStatus());
        query.setType(TransactionBillType.RECHARGE.getType());
        query.setMonth(lastMonth.getMonthValue());
        query.setYear(lastMonth.getYear());
        Map<Long, BillCountVo> map = transactionBillService.selectCountMap(query, BillCountVo::getStoreId);

        for (StoreVo store : list) {
            BillCountVo count = map.get(store.getStoreId());
            if (count != null) {
                store.setLastMonthIncome(count.getRecharge());
            } else {
                store.setLastMonthIncome(BigDecimal.ZERO);
            }
        }
    }

    /**
     * 拼接在线数量
     *
     * @param list
     */
    @Override
    public void assembleOnlineCount(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        DeviceQuery query = new DeviceQuery();
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).collect(Collectors.toList()));
        query.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus());
        query.setGroupBy(DeviceGroupBy.store_id.name());
        Map<Long, Integer> countMap = deviceService.selectCommonCountMap(query, DeviceCountVO::getStoreId);

        for (StoreVo store : list) {
            Integer count = countMap.get(store.getStoreId());
            store.setOnlineCount(count == null ? 0 :count);
        }
    }

    /**
     * 拼接离线数量
     *
     * @param list
     */
    @Override
    public void assembleOfflineCount(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        DeviceQuery query = new DeviceQuery();
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).collect(Collectors.toList()));
        query.setOnlineStatus(DeviceOnlineStatus.OFFLINE.getStatus());
        query.setGroupBy(DeviceGroupBy.store_id.name());
        Map<Long, Integer> countMap = deviceService.selectCommonCountMap(query, DeviceCountVO::getStoreId);

        for (StoreVo store : list) {
            Integer count = countMap.get(store.getStoreId());
            store.setOfflineCount(count == null ? 0 :count);
        }
    }

    /**
     * 拼接可共享设备数量
     *
     * @param list
     */
    @Override
    public void assembleAvailableDeviceCount(List<StoreVo> list) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }
        DeviceQuery query = new DeviceQuery();
        query.setStoreIds(list.stream().map(StoreVo::getStoreId).collect(Collectors.toList()));
        query.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus());
        query.setStatus(DeviceStatus.NORMAL.getStatus());
        query.setGroupBy(DeviceGroupBy.store_id.name());
        Map<Long, Integer> countMap = deviceService.selectCommonCountMap(query, DeviceCountVO::getStoreId);

        for (StoreVo store : list) {
            Integer count = countMap.get(store.getStoreId());
            store.setAvailableDeviceCount(count == null ? 0 :count);
        }
    }

    @Override
    public void assembleOperator(List<StoreVo> list, Long userId) {
        if (CollectionUtils.isEmptyElement(list)) {
            return;
        }

        for (StoreVo store : list) {
            StoreOperatorVO vo = StoreOperatorVO.defaultInstance();
            // 有操作权限，可修改、配置
            if (storeValidator.canOperaStore(store, userId)) {
                vo.setConfig(true);
                vo.setUpdate(true);
            }
            // 是商户，可删除、查看设备列表
            if (storeValidator.isMch(store, userId)) {
                vo.setDel(true);
                vo.setViewDevice(true);
                vo.setAddStaff(true);
            }
            store.setOperator(vo);
        }
    }
}
