package com.kym.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kym.common.utils.CommUtil;
import com.kym.entity.SplitRecord;
import com.kym.entity.WashDevice;
import com.kym.entity.WashOrder;
import com.kym.entity.queryParams.StatQueryParam;
import com.kym.entity.vo.DashboardVo;
import com.kym.entity.vo.StationTrendVo;
import com.kym.service.*;
import com.kym.service.cache.KymCache;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 统计
 */
@Service
public class StatServiceImpl implements StatService {
    private final UserService userService;
    private final WashOrderService washOrderService;
    private final WashDeviceService washDeviceService;
    private final SplitRecordService splitRecordService;

    public StatServiceImpl(UserService userService, WashOrderService washOrderService, WashDeviceService washDeviceService, SplitRecordService splitRecordService) {
        this.userService = userService;
        this.washOrderService = washOrderService;
        this.washDeviceService = washDeviceService;
        this.splitRecordService = splitRecordService;
    }

    @Override
    public Map<String, Integer> getTodayConsumption() {
        return washOrderService.sumAmountByDate(LocalDate.now());
    }

    @Override
    public Map<String, Integer> getMonthConsumption() {
        return washOrderService.sumMonthAmount(LocalDate.now());
    }

    @Override
    public Integer getTotalConsumption() {
        return null;
    }

    @Override
    public Integer getTotalRegistrations() {
        return (int) userService.count();
    }

    /**
     * 当月订单平均消费金额
     *
     * @return
     */
    @Override
    public Integer getAvgPrice() {
//        int totalAmountMap = washOrderService.sumMonthAmount(LocalDate.now());
//        int totalOrdersMap = washOrderService.countMonthOrdersCount(LocalDate.now());
//        // todo 按照站点 分组统计
//        return totalOrders == 0 ? 0 : totalAmount / totalOrders;
        return null;
    }

    /**
     * 平均洗车时长
     *
     * @return
     */
    @Override
    public Integer getAvgDuration() {
        var startTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
        var endTime = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
        LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(WashOrder::getStartTime, startTime);
        wrapper.gt(WashOrder::getStartTime, endTime);
        var list = washOrderService.list(wrapper);
        if (!list.isEmpty()) {
            var totalSeconds = list.stream().mapToInt(WashOrder::getTotalSeconds).sum();
            return totalSeconds / list.size();
        }
        return null;
    }


    /**
     * 当月用户平均洗车频率
     *
     * @return
     */
    @Override
    public Double getAvgFrequency() {
        var startTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
        var endTime = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
        LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(WashOrder::getStartTime, startTime);
        wrapper.gt(WashOrder::getStartTime, endTime);
        var list = washOrderService.list(wrapper);
        // 洗车人数
        var users = list.stream().distinct().map(WashOrder::getUserId).count();
        return users == 0 ? 0 : (double) Math.round((double) list.size() / users * 100) / 100;
    }

    /**
     * 今日概要
     *
     * @return
     */
    @Override
    public DashboardVo dashboard(String stationId) {
        // 站点今日注册人数
        var todayRegistrations = userService.countDailyRegister(LocalDate.now(), stationId);

        // 站点分账-入账数据
        var todayIncome = (Integer) splitRecordService.lambdaQuery()
                .eq(SplitRecord::getToStationId, stationId)
                .ge(SplitRecord::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN))
                .lt(SplitRecord::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MAX))
                .list().stream().mapToInt(SplitRecord::getAmount).sum();

        // 截止到现在今日的所有洗车订单
        var todayOrders = washOrderService.lambdaQuery()
                .eq(WashOrder::getStationId, stationId)
                .ge(WashOrder::getStartTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN))
                .list();

        // 今日概要
        DashboardVo dashboardVo = new DashboardVo();
        dashboardVo.setTodayIncome(todayIncome);
        dashboardVo.setTodayConsumptionAmount(todayOrders.stream().mapToInt(WashOrder::getAmount).sum());
        dashboardVo.setTodayWashOrders(todayOrders.size());
        dashboardVo.setTotalConsumptionAmount(todayOrders.stream().mapToInt(WashOrder::getAmount).sum());
        dashboardVo.setTodayRegisteredMembers(CommUtil.isEmptyOrNull(todayRegistrations) ? 0 : todayRegistrations.get(stationId));

        // 月度或者总数据 todo
        dashboardVo.setMonthIncome(0); // todo
        dashboardVo.setMonthConsumptionAmount(0); // todo
        dashboardVo.setMonthRegisteredMembers(0); //todo
        dashboardVo.setMonthWashOrders(0); // todo

        dashboardVo.setAvgOrderPrice(0); // todo
        dashboardVo.setAvgOrderDuration(0); // todo
        dashboardVo.setAvgWashFrequency(0.0); // todo

        dashboardVo.setTotalIncome(0); // todo
        dashboardVo.setTotalWashOrders(0); // todo


        return dashboardVo;
    }


    /**
     * 统计站点的设备状态情况
     *
     * @param stationId
     * @return
     */
    @Override
    public Map<String, Long> washDeviceStatus(String stationId) {
        return washDeviceService.lambdaQuery().eq(WashDevice::getStationId, stationId).list()
                .stream().collect((Collectors.groupingBy(WashDevice::getState, Collectors.counting())));
    }

    @Override
    public List<StationTrendVo> trend(StatQueryParam params) {
        // 判断数据权限
        var adminStationIds = KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong());
        if (CommUtil.isEmptyOrNull(params.getStationId()) && CommUtil.isNotEmptyAndNull(adminStationIds)) {
            params.setStationId(adminStationIds.get(0));
        }
        if (CommUtil.isNotEmptyAndNull(params.getStationId()) && CommUtil.isNotEmptyAndNull(adminStationIds) && !adminStationIds.contains(params.getStationId())) {
            params.setStationId(adminStationIds.get(0));
        }


        return washOrderService.stationTrend(params);
    }
}
