package com.ruoyi.dashboard.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.bst.area.service.AreaDashboard;
import com.ruoyi.bst.areaJoin.service.AreaJoinDashboard;
import com.ruoyi.bst.bonus.constants.BonusDailyKeys;
import com.ruoyi.bst.bonus.domain.vo.BonusDailyStatVO;
import com.ruoyi.bst.bonus.service.BonusDashboard;
import com.ruoyi.bst.bonusRefund.constants.BonusRefundDailyKeys;
import com.ruoyi.bst.bonusRefund.domain.vo.BonusRefundDailyStatVO;
import com.ruoyi.bst.bonusRefund.service.BonusRefundDashboard;
import com.ruoyi.bst.device.service.DeviceDashboard;
import com.ruoyi.bst.fault.service.FaultDashboard;
import com.ruoyi.bst.mchApply.service.MchApplyDashboard;
import com.ruoyi.bst.model.service.ModelDashboard;
import com.ruoyi.bst.order.constants.OrderDailyKeys;
import com.ruoyi.bst.order.domain.vo.OrderDailyRefundStatVO;
import com.ruoyi.bst.order.domain.vo.OrderDailyStatVO;
import com.ruoyi.bst.order.service.OrderDashboard;
import com.ruoyi.bst.refund.constants.RefundDailyKeys;
import com.ruoyi.bst.refund.domain.RefundQuery;
import com.ruoyi.bst.refund.domain.enums.RefundType;
import com.ruoyi.bst.refund.domain.vo.RefundDailyStatVO;
import com.ruoyi.bst.refund.service.RefundDashboard;
import com.ruoyi.bst.withdraw.constants.WithdrawDailyKeys;
import com.ruoyi.bst.withdraw.domain.vo.WithdrawDailyStatVO;
import com.ruoyi.bst.withdraw.service.WithdrawDashboard;
import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.dashboard.constants.StatKeys;
import com.ruoyi.dashboard.domain.dailySettleStat.DailySettleStatQuery;
import com.ruoyi.dashboard.domain.dailySettleStat.DailySettleStatVO;
import com.ruoyi.dashboard.domain.dailyStat.DailyStatQuery;
import com.ruoyi.dashboard.domain.dailyStat.DailyStatVO;
import com.ruoyi.dashboard.domain.platformIncomeDaily.PlatformDailyIncomeQuery;
import com.ruoyi.dashboard.domain.platformIncomeDaily.PlatformDailyIncomeVO;
import com.ruoyi.dashboard.domain.revenueStat.RevenueStatQuery;
import com.ruoyi.dashboard.domain.revenueStat.RevenueStatVO;
import com.ruoyi.dashboard.domain.stat.StatQuery;
import com.ruoyi.dashboard.domain.stat.StatVO;
import com.ruoyi.dashboard.utils.DashboardUtil;
import com.ruoyi.system.user.service.UserDashboard;

@Service
public class DashboardService {

    @Autowired
    private OrderDashboard orderDashboard;

    @Autowired
    private BonusDashboard bonusDashboard;

    @Autowired
    private UserDashboard userDashboard;

    @Autowired
    private DeviceDashboard deviceDashboard;

    @Autowired
    private AreaDashboard areaDashboard;

    @Autowired
    private ModelDashboard modelDashboard;

    @Autowired
    private BonusRefundDashboard bonusRefundDashboard;

    @Autowired
    private AreaJoinDashboard areaJoinDashboard;

    @Autowired
    private WithdrawDashboard withdrawDashboard;

    @Autowired
    private MchApplyDashboard mchApplyDashboard;

    @Autowired
    private FaultDashboard faultDashboard;

    @Autowired
    private RefundDashboard refundDashboard;

    public StatVO selectStat(StatQuery query) {
        StatVO vo = new StatVO();
        vo.setOrder(orderDashboard.selectStat(DashboardUtil.toOrderQuery(query), query.getKeys()));
        vo.setOrderRefund(orderDashboard.selectRefundStat(DashboardUtil.toOrderRefundQuery(query), query.getKeys()));
        vo.setBonus(bonusDashboard.selectStat(DashboardUtil.toBonusQuery(query), query.getKeys()));
        vo.setBonusRefund(bonusRefundDashboard.selectStat(DashboardUtil.toBonusRefundQuery(query), query.getKeys()));
        vo.setUser(userDashboard.selectStat(DashboardUtil.toUserQuery(query), query.getKeys()));
        vo.setUserAgent(userDashboard.selectAgentStat(DashboardUtil.toUserAgentQuery(query), query.getKeys()));
        vo.setDevice(deviceDashboard.selectStat(DashboardUtil.toDeviceQuery(query), query.getKeys()));
        vo.setArea(areaDashboard.selectStat(DashboardUtil.toAreaQuery(query), query.getKeys()));
        vo.setModel(modelDashboard.selectStat(DashboardUtil.toModelQuery(query), query.getKeys()));
        vo.setAreaJoin(areaJoinDashboard.selectStat(DashboardUtil.toAreaJoinQuery(query), query.getKeys()));
        vo.setWithdraw(withdrawDashboard.selectStat(DashboardUtil.toWithdrawQuery(query), query.getKeys()));
        vo.setMchApply(mchApplyDashboard.selectStat(DashboardUtil.toMchApplyQuery(query), query.getKeys()));
        vo.setFault(faultDashboard.selectStat(DashboardUtil.toFaultQuery(query), query.getKeys()));
        return vo;
    }

    public List<DailyStatVO> selectDailyStat(DailyStatQuery query) {
        List<OrderDailyStatVO> orderList = orderDashboard.selectDailyStat(DashboardUtil.toOrderQuery(query),
                query.getOrderKeys());
        List<OrderDailyRefundStatVO> orderRefundList = orderDashboard
                .selectDailyRefundStat(DashboardUtil.toOrderRefundQuery(query), query.getOrderRefundKeys());
        List<BonusDailyStatVO> bonusList = bonusDashboard.selectDailyStat(DashboardUtil.toBonusQuery(query),
                query.getBonusKeys());
        List<BonusRefundDailyStatVO> bonusRefundList = bonusRefundDashboard
                .selectDailyStat(DashboardUtil.toBonusRefundQuery(query), query.getBonusRefundKeys());

        List<DailyStatVO> result = new ArrayList<>();
        if (query.getDateRange() != null && query.getDateRange().size() >= 2) {
            result = CollectionUtils.fillVoids(result, DailyStatVO::getDate, (date) -> {
                DailyStatVO vo = new DailyStatVO();
                vo.setDate(date);
                // 订单
                OrderDailyStatVO order = orderList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new OrderDailyStatVO());
                vo.setOrder(order);
                // 订单退款
                OrderDailyRefundStatVO orderRefund = orderRefundList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new OrderDailyRefundStatVO());
                vo.setOrderRefund(orderRefund);
                // 分成
                BonusDailyStatVO bonus = bonusList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusDailyStatVO());
                vo.setBonus(bonus);
                // 分成退款
                BonusRefundDailyStatVO bonusRefund = bonusRefundList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusRefundDailyStatVO());
                vo.setBonusRefund(bonusRefund);

                return vo;
            }, query.getDateRange().get(0), query.getDateRange().get(1));
        }

        return result;
    }

    public RevenueStatVO selectRevenueStat(RevenueStatQuery query) {
        RevenueStatVO vo = new RevenueStatVO();
        List<String> keys = query.getKeys();
        // 订单用户数量
        if (keys.contains(StatKeys.ORDER_USER_COUNT)) {
            vo.setOrderUserCount(orderDashboard.selectUserCount(query.toOrderQuery()));
        }
        // 订单实收金额
        if (keys.contains(StatKeys.ORDER_ACTUAL_AMOUNT)) {
            vo.setOrderActualAmount(orderDashboard.selectSumOfActualAmount(query.toOrderQueryForEnd()));
        }
        // 订单骑行费
        if (keys.contains(StatKeys.ORDER_RIDDING_FEE)) {
            vo.setOrderRiddingFee(orderDashboard.selectSumOfActualRiddingFee(query.toOrderQueryForEnd()));
        }
        // 订单车损费
        if (keys.contains(StatKeys.ORDER_DEDUCTION_FEE)) {
            vo.setOrderDeductionFee(orderDashboard.selectSumOfActualDeductionFee(query.toOrderQueryForEnd()));
        }
        // 订单调度费
        if (keys.contains(StatKeys.ORDER_DISPATCH_FEE)) {
            vo.setOrderDispatchFee(orderDashboard.selectSumOfActualDispatchFee(query.toOrderQueryForEnd()));
        }
        // 订单管理费
        if (keys.contains(StatKeys.ORDER_MANAGE_FEE)) {
            vo.setOrderManageFee(orderDashboard.selectSumOfActualManageFee(query.toOrderQueryForEnd()));
        }
        // 订单数量
        if (keys.contains(StatKeys.ORDER_COUNT)) {
            vo.setOrderCount(orderDashboard.selectCount(query.toOrderQuery()));
        }
        // 订单退款金额
        if (keys.contains(StatKeys.ORDER_REFUND_AMOUNT) || keys.contains(StatKeys.ORDER_ACTUAL_AMOUNT)) {
            RefundQuery refundQuery = query.toOrderRefundQuery();
            refundQuery.setType(RefundType.AUTO.getCode());
            vo.setOrderAutoRefundAmount(refundDashboard.selectSumOfAmount(refundQuery));

            refundQuery.setType(RefundType.ADMIN.getCode());
            vo.setOrderAdminRefundAmount(refundDashboard.selectSumOfAmount(refundQuery));
        }
        // 订单状态数量
        if (keys.contains(StatKeys.ORDER_STATUS_COUNT)) {
            vo.setOrderStatusMap(orderDashboard.selectStatusCount(query.toOrderQuery()));
        }
        // 订单完成状态数量
        if (keys.contains(StatKeys.ORDER_END_STATUS_COUNT)) {
            vo.setOrderEndStatusMap(orderDashboard.selectStatusCount(query.toOrderQueryForEnd()));
        }

        // 分成总金额
        if (keys.contains(StatKeys.BONUS_AMOUNT) || keys.contains(StatKeys.BONUS_ACTUAL_AMOUNT)) {
            vo.setBonusAmount(bonusDashboard.selectSumOfAmount(query.toBonusQuery()));
        }
        // 分成退款金额
        if (keys.contains(StatKeys.BONUS_REFUND_AMOUNT) || keys.contains(StatKeys.BONUS_ACTUAL_AMOUNT)) {
            vo.setBonusRefundAmount(bonusRefundDashboard.selectSumOfUserBonusRefund(query.toBonusRefundQuery()));
        }
        // 分成待分金额
        if (keys.contains(StatKeys.BONUS_WAIT_DIVIDE_AMOUNT)) {
            vo.setBonusWaitDivideAmount(bonusDashboard.selectSumOfWaitAmount(query.toBonusQuery()));
        }
        // 分成数量
        if (keys.contains(StatKeys.BONUS_COUNT)) {
            vo.setBonusCount(bonusDashboard.selectCount(query.toBonusQuery()));
        }

        // 平台分成金额
        if (keys.contains(StatKeys.PLATFORM_BONUS_AMOUNT) || keys.contains(StatKeys.PLATFORM_BONUS_ACTUAL_AMOUNT)) {
            vo.setPlatformBonusAmount(bonusDashboard.selectSumOfAmount(query.toPlatformBonusQuery()));
        }
        // 平台分成退款金额
        if (keys.contains(StatKeys.PLATFORM_BONUS_REFUND_AMOUNT) || keys.contains(StatKeys.PLATFORM_BONUS_ACTUAL_AMOUNT)) {
            vo.setPlatformBonusRefundAmount(bonusRefundDashboard.selectSumOfPlatformBonusRefund(query.toPlatformBonusRefundQuery()));
        }

        // 运营区数量
        if (keys.contains(StatKeys.AREA_COUNT)) {
            vo.setAreaCount(areaDashboard.selectCount(query.toAreaQuery()));
        }

        // 运营区加盟商数量
        if (keys.contains(StatKeys.AREA_JOIN_COUNT)) {
            vo.setAreaJoinCount(areaJoinDashboard.selectJoinCount(query.toAreaJoinQuery()));
        }
        // 运营区合伙人数量
        if (keys.contains(StatKeys.AREA_JOIN_PARTNER_COUNT)) {
            vo.setAreaPartnerCount(areaJoinDashboard.selectPartnerCount(query.toAreaJoinQuery()));
        }
        // 运营区运维数量
        if (keys.contains(StatKeys.AREA_JOIN_OPERATION_COUNT)) {
            vo.setAreaOperationCount(areaJoinDashboard.selectOperationCount(query.toAreaJoinQuery()));
        }

        // 设备数量
        if (keys.contains(StatKeys.DEVICE_COUNT)) {
            vo.setDeviceCount(deviceDashboard.selectCount(query.toDeviceQuery()));
        }
        // 设备状态数量
        if (keys.contains(StatKeys.DEVICE_STATUS_COUNT)) {
            vo.setDeviceStatusMap(deviceDashboard.selectStatusCount(query.toDeviceQuery()));
        }
        // 设备在线状态数量
        if (keys.contains(StatKeys.DEVICE_ONLINE_STATUS_COUNT)) {
            vo.setDeviceOnlineStatusMap(deviceDashboard.selectOnlineStatusCount(query.toDeviceQuery()));
        }

        // 成功提现金额
        if (keys.contains(StatKeys.WITHDRAW_SUCCESS_AMOUNT)) {
            vo.setWithdrawSuccessAmount(withdrawDashboard.selectSuccessAmount(query.toWithdrawQuery()));
        }
        // 待审核的提现数量
        if (keys.contains(StatKeys.WITHDRAW_WAIT_VERIFY_COUNT)) {
            vo.setWithdrawWaitVerifyCount(withdrawDashboard.selectWaitVerifyCount(query.toWithdrawQuery()));
        }
        // 提现手续费
        if (keys.contains(StatKeys.WITHDRAW_SERVICE_CHARGE)) {
            vo.setWithdrawServiceCharge(withdrawDashboard.selectSuccessServiceCharge(query.toWithdrawQuery()));
        }

        // 待审核的加盟商申请数量
        if (keys.contains(StatKeys.MCH_APPLY_APPROVING_COUNT)) {
            vo.setMchApplyApprovingCount(mchApplyDashboard.selectApprovingCount(query.toMchApplyQuery()));
        }

        // 待处理的故障数量
        if (keys.contains(StatKeys.FAULT_PENDING_COUNT)) {
            vo.setFaultPendingCount(faultDashboard.selectPendingCount(query.toFaultQuery()));
        }

        // 用户余额
        if (keys.contains(StatKeys.USER_BALANCE)) {
            vo.setUserBalance(userDashboard.selectSumOfBalance(query.toUserQuery()));
        }
        // 用户数量
        if (keys.contains(StatKeys.USER_COUNT)) {
            vo.setUserCount(userDashboard.selectCount(query.toUserQuery()));
        }
        // 运营商数量
        if (keys.contains(StatKeys.USER_MCH_COUNT)) {
            vo.setUserMchCount(userDashboard.selectMchCount(query.toUserQuery()));
        }

        // 车型数量
        if (keys.contains(StatKeys.MODEL_COUNT)) {
            vo.setModelCount(modelDashboard.selectCount(query.toModelQuery()));
        }

        return vo;
    }

    /**
     * 查询平台每日收益
     */
    public List<PlatformDailyIncomeVO> selectPlatformDailyIncome(PlatformDailyIncomeQuery query) {
        List<PlatformDailyIncomeVO> result = new ArrayList<>();

        // 查询分成金额
        List<BonusDailyStatVO> bonusList = bonusDashboard.selectDailyStat(
            query.toBonusQuery(),
            Arrays.asList(BonusDailyKeys.WAIT_DATE, BonusDailyKeys.BONUS_AMOUNT)
        );

        // 查询分成退款金额
        List<BonusRefundDailyStatVO> bonusRefundList = bonusRefundDashboard.selectDailyStat(
            query.toBonusRefundQuery(),
            Arrays.asList(BonusRefundDailyKeys.CREATE_DATE, BonusRefundDailyKeys.BONUS_REFUND_AMOUNT)
        );

        // 查询每日提现金额
        List<WithdrawDailyStatVO> withdrawList = withdrawDashboard.selectDailyStat(
            query.toWithdrawQuery(),
            Arrays.asList(WithdrawDailyKeys.CREATE_DATE, WithdrawDailyKeys.WITHDRAW_SERVICE_CHARGE)
        );

        if (query.getDateRange() != null && query.getDateRange().size() >= 2) {
            result = CollectionUtils.fillVoids(result, PlatformDailyIncomeVO::getDate, (date) -> {
                PlatformDailyIncomeVO vo = new PlatformDailyIncomeVO();
                vo.setDate(date);

                // 分成金额
                BonusDailyStatVO bonus = bonusList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusDailyStatVO());
                vo.setBonusAmount(MathUtils.dv(bonus.getAmount()));

                // 分成退款金额
                BonusRefundDailyStatVO bonusRefund = bonusRefundList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusRefundDailyStatVO());
                vo.setBonusRefundAmount(MathUtils.dv(bonusRefund.getAmount()));

                // 提现手续费
                WithdrawDailyStatVO withdraw = withdrawList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new WithdrawDailyStatVO());
                vo.setWithdrawServiceCharge(MathUtils.dv(withdraw.getServiceCharge()));

                return vo;
            }, query.getDateRange().get(0), query.getDateRange().get(1));
        }

        return result;
    }

    /**
     * 查询每日结算金额
     */
    public List<DailySettleStatVO> selectDailySettleStat(DailySettleStatQuery query) {
        List<OrderDailyStatVO> orderList = orderDashboard.selectDailyStat(
            query.toOrderQuery(),
            Arrays.asList(OrderDailyKeys.END_DATE, OrderDailyKeys.ACTUAL_AMOUNT)
        );
        List<RefundDailyStatVO> refundList = refundDashboard.selectDailyRefundStat(
            query.toRefundQuery(),
            Arrays.asList(RefundDailyKeys.CREATE_DATE, RefundDailyKeys.AMOUNT)
        );
        List<BonusDailyStatVO> bonusList = bonusDashboard.selectDailyStat(
            query.toBonusQuery(),
            Arrays.asList(BonusDailyKeys.WAIT_DATE, BonusDailyKeys.BONUS_AMOUNT)
        );
        List<BonusRefundDailyStatVO> bonusRefundList = bonusRefundDashboard.selectDailyStat(
            query.toBonusRefundQuery(),
            Arrays.asList(BonusRefundDailyKeys.CREATE_DATE, BonusRefundDailyKeys.BONUS_REFUND_AMOUNT)
        );

        List<DailySettleStatVO> result = new ArrayList<>();
        if (query.getDateRange() != null && query.getDateRange().size() >= 2) {
            result = CollectionUtils.fillVoids(result, DailySettleStatVO::getDate, (date) -> {
                DailySettleStatVO vo = new DailySettleStatVO();
                vo.setDate(date);
                // 订单
                OrderDailyStatVO order = orderList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new OrderDailyStatVO());
                vo.setOrderSettleAmount(order.getActualAmount());
                // 订单退款
                RefundDailyStatVO refund = refundList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new RefundDailyStatVO());
                vo.setRefundAmount(refund.getAmount());
                // 分成
                BonusDailyStatVO bonus = bonusList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusDailyStatVO());
                vo.setBonusSettleAmount(bonus.getAmount());
                // 分成退款
                BonusRefundDailyStatVO bonusRefund = bonusRefundList.stream()
                        .filter(item -> item.getDate() != null && item.getDate().isEqual(date))
                        .findFirst().orElse(new BonusRefundDailyStatVO());
                vo.setBonusRefundAmount(bonusRefund.getAmount());

                return vo;
            }, query.getDateRange().get(0), query.getDateRange().get(1));
        }

        return result;
    }
}
