package com.ruoyi.web.controller.ss;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.ValidGroup;
import com.ruoyi.common.domain.vo.LocalDateDecimalVO;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.dashboard.domain.dto.BillDailyAmountQuery;
import com.ruoyi.dashboard.service.DashboardService;
import com.ruoyi.ss.balancePeriod.domain.SmBalancePeriodQuery;
import com.ruoyi.ss.balancePeriod.service.ISmBalancePeriodService;
import com.ruoyi.ss.bonus.domain.BonusQuery;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.businessRecord.service.ISmBusinessRecordService;
import com.ruoyi.dashboard.domain.dto.ServiceIncomeQuery;
import com.ruoyi.ss.payBill.domain.PayBillQuery;
import com.ruoyi.ss.payBill.domain.enums.PayBillStatus;
import com.ruoyi.ss.payBill.domain.vo.PayDailyAmountVO;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.refund.domain.RefundQuery;
import com.ruoyi.ss.refund.domain.enums.RefundStatus;
import com.ruoyi.ss.refund.service.RefundService;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionDailyAmountVO;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillGroupBy;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.businessRecord.domain.SmBusinessRecordVo;
import com.ruoyi.dashboard.domain.vo.BriefVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 报表Controller
 * @author 辉
 * 2024/3/6
 */
@RestController
@RequestMapping("/system/dashboard")
public class SmDashboardController extends BaseController {

    @Autowired
    private TransactionBillService transactionBillService;

    @Autowired
    private ISmBalancePeriodService balancePeriodService;

    @Autowired
    private ISmBusinessRecordService businessRecordService;

    @Autowired
    private DashboardService dashboardService;

    @Autowired
    private BonusService bonusService;

    @Autowired
    private PayBillService payBillService;

    @Autowired
    private RefundService refundService;

    /**
     * 舆情分析数据
     */
    @GetMapping("/brief")
    public AjaxResult brief() {
        BriefVo brief = businessRecordService.selectBrief();

        Date today = new Date();
        Date startDate = DateUtils.plusDate(today, -12);
        Date endDate = DateUtils.plusDate(today, -1);
        List<SmBusinessRecordVo> history = businessRecordService.selectDailyLatest(startDate, endDate);

        brief.setHistory(history);

        return AjaxResult.success(brief);
    }

    /**
     * 获取账单分时统计数据
     * @param dto 查询条件
     * @return 统计数据
     */
    @GetMapping("/hourBillCount")
    public AjaxResult hourBillCount(@Validated(ValidGroup.Query.class) TransactionBillQuery dto) {
        dto.setGroupBy(TransactionBillGroupBy.create_hour.name());
        dto.setStatusList(TransactionBillStatus.serviceIncome());
        return AjaxResult.success(transactionBillService.selectCount(dto));
    }

    /**
     * 获取余额时段分析
     */
    @ApiOperation("获取余额时段分析")
    @GetMapping("/balancePeriod")
    public AjaxResult balancePeriod(SmBalancePeriodQuery dto) {
        return AjaxResult.success(balancePeriodService.selectSmBalancePeriodList(dto));
    }

    /**
     * 获取待办事项
     */
    @GetMapping("/todoList")
    public AjaxResult getTodoList() {
        return success(dashboardService.getTodoList());
    }

    /**
     * 获取服务费、收入及成本
     */
    @GetMapping("/serviceIncome")
    public AjaxResult getServiceIncome(ServiceIncomeQuery query) {
        return success(dashboardService.getServiceIncome(query));
    }

    /**
     * 按月统计分成
     */
    @GetMapping("/bonusMonthAmount")
    public AjaxResult getBonusMonthAmount(BonusQuery query) {
        return success(bonusService.selectMonthPayedAmount(query));
    }

    /**
     * 按天统计分成
     */
    @GetMapping("/bonusDailyAmount")
    public AjaxResult getBonusDailyAmount(BonusQuery query) {
        List<LocalDateDecimalVO> list = bonusService.selectDailyPayedAmount(query);
        // 若开始和结束日期不为空，则补全缺失的日期
        if (query.getPayDateStart() != null && query.getPayDateEnd() != null) {
            list = CollectionUtils.fillVoids(list, LocalDateDecimalVO::getKey, (date) -> {
                LocalDateDecimalVO vo = new LocalDateDecimalVO();
                vo.setKey(date);
                vo.setValue(BigDecimal.ZERO);
                return vo;
            }, query.getPayDateStart(), query.getPayDateEnd());
        }
        return success(list);
    }

    /**
     * 按天统计支付订单金额数据
     */
    @GetMapping("/billDailyAmount")
    public AjaxResult getBillDailyAmount(BillDailyAmountQuery query) {
        PayBillQuery payQuery = new PayBillQuery();
        payQuery.setPayDateStart(query.getDateStart());
        payQuery.setPayDateEnd(query.getDateEnd());
        payQuery.setStatusList(PayBillStatus.payedList());
        payQuery.setChannelId(query.getChannelId());
        List<LocalDateDecimalVO> payList = payBillService.selectDailyAmount(payQuery);

        RefundQuery refundQuery = new RefundQuery();
        refundQuery.setCreateDateStart(query.getDateStart());
        refundQuery.setCreateDateEnd(query.getDateEnd());
        refundQuery.setStatusList(RefundStatus.successList());
        refundQuery.setChannelId(query.getChannelId());
        List<LocalDateDecimalVO> refundList = refundService.selectDailyAmount(refundQuery);

        List<PayDailyAmountVO> list = new ArrayList<>();
        if (query.getDateStart() != null && query.getDateEnd() != null) {
            list = CollectionUtils.fillVoids(list, PayDailyAmountVO::getDate, (date) -> {
                PayDailyAmountVO vo = new PayDailyAmountVO();
                vo.setDate(date);

                LocalDateDecimalVO pay = payList.stream().filter(item -> date.isEqual(item.getKey())).findFirst().orElse(null);
                if (pay == null) {
                    vo.setTotal(BigDecimal.ZERO);
                } else {
                    vo.setTotal(pay.getValue());
                }

                LocalDateDecimalVO refund = refundList.stream().filter(item -> date.isEqual(item.getKey())).findFirst().orElse(null);
                if (refund == null) {
                    vo.setRefund(BigDecimal.ZERO);
                } else {
                    vo.setRefund(refund.getValue());
                }

                vo.setReceived(vo.getTotal().subtract(vo.getRefund()));

                return vo;
            }, query.getDateStart(), query.getDateEnd());
        }
        return success(list);
    }
}
