package com.cpxt.web.controller.biz;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cpxt.biz.domain.*;
import com.cpxt.biz.mapper.*;
import com.cpxt.common.annotation.Anonymous;
import com.cpxt.common.core.controller.BaseController;
import com.cpxt.common.core.domain.AjaxResult;
import com.cpxt.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.util.*;
import java.util.stream.Collectors;

/**
 * 大屏Controller
 *
 * @author Luo.J
 * @date 2024-12-16
 */
@RestController
@RequestMapping("/biz/largeScreen")
@Anonymous
public class LargeScreenController extends BaseController {

    @Autowired
    private BizDriverMapper bizDriverMapper;

    @Autowired
    private BizOrderMapper bizOrderMapper;

    @Autowired
    private BizCarMapper bizCarMapper;

    @Autowired
    private BizCustomerMapper bizCustomerMapper;

    @Autowired
    private BizCustomerShopMapper bizCustomerShopMapper;

    @Autowired
    private BizCustomerRouteShopMapper bizCustomerRouteShopMapper;

    @Autowired
    private BizCustomerShopStateMapper bizCustomerShopStateMapper;

    @Autowired
    private BizCustomerRouteMapper bizCustomerRouteMapper;

    @Autowired
    private BizCustomerRouteStateMapper bizCustomerRouteStateMapper;

    @Autowired
    private StatCarMapper statCarMapper;

    @Autowired
    private StatDriverMapper statDriverMapper;

    @Autowired
    private BizCustomerWarehouseMapper bizCustomerWarehouseMapper;

    private final String today = DateUtil.format(new Date(), "yyyy-MM-dd");

    private final LargeScreenEntity largeScreenEntity = new LargeScreenEntity();

    /**
     * 司机概览
     */
    @GetMapping("/driver/overview")
    public AjaxResult driverOverview()
    {
        long onlineDrive = getDriveCount(1);
        long offlineDrive = getDriveCount(0);
        double onlineRate = commonComputeRatio(onlineDrive, onlineDrive + offlineDrive);
        double deliveryMileage = getDeliveryMileage();
        largeScreenEntity.setOnlineDrive(onlineDrive);
        largeScreenEntity.setOfflineDrive(offlineDrive);
        largeScreenEntity.setOnlineRate(onlineRate);
        largeScreenEntity.setDeliveryMileage(deliveryMileage);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 今日订单概览
     */
    @GetMapping("/order/overview")
    public AjaxResult orderOverview()
    {
        long completedOrder = getCompletedOrder(today);
        long incompleteOrder = getIncompleteOrder(today);
        double completedRate = commonComputeRatio(completedOrder,completedOrder + incompleteOrder);
        double incompleteRate = commonComputeRatio(incompleteOrder,completedOrder + incompleteOrder);
        largeScreenEntity.setCompletedOrder(completedOrder);
        largeScreenEntity.setIncompleteOrder(incompleteOrder);
        largeScreenEntity.setCompletedRate(completedRate);
        largeScreenEntity.setIncompleteRate(incompleteRate);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 总体概览
     */
    @GetMapping("/overall/overview")
    public AjaxResult overallOverview()
    {
        long onDutyDriver = getOnDutyDriver();
        long onDutyCar = getOnDutyCar();
        long customer = getCustomer();
        long shop = getShop();
        long order = getOrder();
        long route = getRoute();
        long warehouse = getWarehouse();
        largeScreenEntity.setOnDutyDriver(onDutyDriver);
        largeScreenEntity.setOnDutyCar(onDutyCar);
        largeScreenEntity.setCustomer(customer);
        largeScreenEntity.setShop(shop);
        largeScreenEntity.setOrder(order);
        largeScreenEntity.setRoute(route);
        largeScreenEntity.setWarehouse(warehouse);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 门店配送情况
     */
    @GetMapping("/customer/deliverySituation")
    public AjaxResult customerDeliverySituation()
    {
        DateTime offset = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -15);
        Map<String,Object> result = new HashMap<>();
        List<String> keys = new ArrayList<>();
        List<Map<String,Long>> values = new ArrayList<>();
        List<String> customerNameList = bizCustomerMapper.getCustomerName();
        for (int i = 0; i <= 15; i++) {
            DateTime time = DateUtil.offset(offset, DateField.DAY_OF_MONTH, i);
            String thatDay = DateUtil.format(time, "yyyy-MM-dd");
            String day = DateUtil.format(time, "MM-dd");
            keys.add(day);
            Map<String,Long> map = new HashMap<>();
            for (String customerName : customerNameList) {
                LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(BizOrder::getStatus,1);
                queryWrapper.ne(BizOrder::getOrderStatus,"4");
                queryWrapper.eq(BizOrder::getCustomerName,customerName);
                queryWrapper.like(BizOrder::getCreateTime,thatDay);
                Long aLong = bizOrderMapper.selectCount(queryWrapper);
                map.put(customerName,aLong);
            }
            values.add(map);
        }
        result.put("keys",keys);
        result.put("values",values);
        result.put("customerNameList",customerNameList);
        largeScreenEntity.setCustomerDeliverySituation(result);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 近30天配送订单top5
     */
    @GetMapping("/driver/deliveryOrderTop5")
    public AjaxResult deliveryOrderTop5()
    {
        DateTime offset = DateUtil.offset(new Date(), DateField.MONTH, -1);
        DateTime dateTime = DateUtil.beginOfDay(offset);
        String startTime = DateUtil.format(dateTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
        String endTime = DateUtil.format(new Date(),DateUtils.YYYY_MM_DD_HH_MM_SS);
        Map<String,Object> result = new HashMap<>();
        List<String> driverNameList = bizDriverMapper.selectDriverName();
        Map<String,Long> map = new HashMap<>();
        for (String driverName : driverNameList) {
            LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizOrder::getStatus,1);
            queryWrapper.ne(BizOrder::getOrderStatus,"4");
            queryWrapper.and(wq -> wq.eq(BizOrder::getDriverName,driverName).or().eq(BizOrder::getCopilotName,driverName));
            queryWrapper.ge(BizOrder::getCreateTime,startTime);
            queryWrapper.le(BizOrder::getCreateTime,endTime);
            Long aLong = bizOrderMapper.selectCount(queryWrapper);
            map.put(driverName,aLong);
        }
        // 倒序
        List<Map.Entry<String, Long>> entries = new ArrayList<>(map.entrySet());
        entries.sort(Map.Entry.<String, Long>comparingByValue().reversed());
        // 取前5个
        List<Map.Entry<String, Long>> deliveryOrderTop5 = entries.stream().limit(5).collect(Collectors.toList());

        // 使用Stream API提取所有的键和值
        List<String> keyList = deliveryOrderTop5.stream().map(Map.Entry::getKey).collect(Collectors.toList());
        List<Long> valueList = deliveryOrderTop5.stream().map(Map.Entry::getValue).collect(Collectors.toList());
        result.put("keys",keyList);
        result.put("values",valueList);

        largeScreenEntity.setDeliveryOrderTop5(result);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 近30天配送里程top5（人）
     */
    @GetMapping("/driver/deliveryDistanceTop5")
    public AjaxResult deliveryDistanceTop5Driver()
    {
        Map<String,Object> result = new HashMap<>();
        DateTime offset = DateUtil.offset(new Date(), DateField.MONTH, -1);
        DateTime dateTime = DateUtil.beginOfDay(offset);
        String startTime = DateUtil.format(dateTime, DateUtils.YYYY_MM_DD);
        String endTime = DateUtil.format(new Date(),DateUtils.YYYY_MM_DD);

        List<String> keyList = statDriverMapper.selectOdometerTop5CarNo(startTime,endTime);
        List<Double> valueList = statDriverMapper.selectOdometerTop5Odometer(startTime,endTime);
        result.put("keys",keyList);
        result.put("values",valueList);
        largeScreenEntity.setDeliveryDistanceTop5Driver(result);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 近30天配送里程top5（车辆）
     */
    @GetMapping("/car/deliveryDistanceTop5")
    public AjaxResult deliveryDistanceTop5Car()
    {
        Map<String,Object> result = new HashMap<>();
        DateTime offset = DateUtil.offset(new Date(), DateField.MONTH, -1);
        DateTime dateTime = DateUtil.beginOfDay(offset);
        String startTime = DateUtil.format(dateTime, DateUtils.YYYY_MM_DD);
        String endTime = DateUtil.format(new Date(),DateUtils.YYYY_MM_DD);

        List<String> keyList = statCarMapper.selectOdometerTop5CarNo(startTime,endTime);
        List<Double> valueList = statCarMapper.selectOdometerTop5Odometer(startTime,endTime);
        result.put("keys",keyList);
        result.put("values",valueList);
        largeScreenEntity.setDeliveryDistanceTop5Car(result);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 查询所有路线信息
     */
    @GetMapping("/route/list")
    public AjaxResult routeList()
    {
        LambdaQueryWrapper<BizCustomerRoute> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomerRoute::getStatus,1);
        List<BizCustomerRoute> bizCustomerRoutes = bizCustomerRouteMapper.selectList(queryWrapper);
        for (BizCustomerRoute bizCustomerRoute : bizCustomerRoutes) {
            LambdaQueryWrapper<BizCustomerRouteState> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(BizCustomerRouteState::getRouteId,bizCustomerRoute.getId());
            BizCustomerRouteState bizCustomerRouteState = bizCustomerRouteStateMapper.selectOne(queryWrapper1);
            bizCustomerRouteState.setFinishRate(commonComputeRatio(bizCustomerRouteState.getFinishOrders(),bizCustomerRouteState.getTodayOrders()));
            bizCustomerRoute.setBizCustomerRouteState(bizCustomerRouteState);
        }
        largeScreenEntity.setRouteList(bizCustomerRoutes);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 查询路线下的店铺信息以及店铺状态
     */
    @GetMapping("/route/shop/list")
    public AjaxResult routeShopList(@RequestParam Integer routeId)
    {
        LambdaQueryWrapper<BizCustomerRoute> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomerRoute::getId,routeId);
        queryWrapper.eq(BizCustomerRoute::getStatus,1);
        BizCustomerRoute bizCustomerRoute = bizCustomerRouteMapper.selectOne(queryWrapper);
        LambdaQueryWrapper<BizCustomerRouteShop> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(BizCustomerRouteShop::getRouteId,bizCustomerRoute.getId());
        List<BizCustomerRouteShop> bizCustomerRouteShops = bizCustomerRouteShopMapper.selectList(queryWrapper1);
        if (bizCustomerRouteShops.size() != 0){
            List<Long> shopIdList = bizCustomerRouteShops.stream().map(BizCustomerRouteShop::getShopId).collect(Collectors.toList());
            LambdaQueryWrapper<BizCustomerShop> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.in(BizCustomerShop::getId,shopIdList);
            List<BizCustomerShop> bizCustomerShops = bizCustomerShopMapper.selectList(queryWrapper2);
            for (BizCustomerShop bizCustomerShop : bizCustomerShops) {
                LambdaQueryWrapper<BizCustomerShopState> queryWrapper3 = new LambdaQueryWrapper<>();
                queryWrapper3.eq(BizCustomerShopState::getShopId,bizCustomerShop.getId());
                BizCustomerShopState bizCustomerShopState = bizCustomerShopStateMapper.selectOne(queryWrapper3);
                if (bizCustomerShopState != null){
                    bizCustomerShop.setIsFinish(bizCustomerShopState.getIsFinish());
                    LambdaQueryWrapper<BizOrder> queryWrapper4 = new LambdaQueryWrapper<>();
                    queryWrapper4.eq(BizOrder::getOrderSn,bizCustomerShopState.getCurrentOrder());
                    BizOrder bizOrder = bizOrderMapper.selectOne(queryWrapper4);
                    if (bizOrder != null){
                        bizCustomerShop.setCurrentOrder(bizOrder.getOrderSn());
                        bizCustomerShop.setCarNo(bizOrder.getCarNo());
                        bizCustomerShop.setDriveName(bizOrder.getDriverName());
                        bizCustomerShop.setCopilotName(bizOrder.getCopilotName());
                        bizCustomerShop.setStartTime(bizOrder.getStartTime());
                        bizCustomerShop.setArriveImg(bizOrder.getArriveImg());
                    }
                }
            }
            bizCustomerRoute.setShopList(bizCustomerShops);
        }
        largeScreenEntity.setBizCustomerRoute(bizCustomerRoute);
        return AjaxResult.success(largeScreenEntity);
    }

    /**
     * 地区分布情况
     */
    @GetMapping("/area/overview")
    public AjaxResult areaOverview()
    {
        Map<String,Object> result = new HashMap<>();
        List<String> keyList = bizOrderMapper.selectAreaNameOverview();
        List<Long> valueList = bizOrderMapper.selectAreaCountOverview();
        result.put("keys",keyList);
        result.put("values",valueList);
        largeScreenEntity.setAreaOverview(result);
        return AjaxResult.success(largeScreenEntity);
    }

    private long getOrder() {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(BizOrder::getOrderStatus,"4");
        queryWrapper.eq(BizOrder::getStatus,1);
        return bizOrderMapper.selectCount(queryWrapper);
    }

    private long getShop() {
        LambdaQueryWrapper<BizCustomerShop> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomerShop::getStatus,1);
        return bizCustomerShopMapper.selectCount(queryWrapper);
    }

    private long getCustomer() {
        LambdaQueryWrapper<BizCustomer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomer::getStatus,1);
        return bizCustomerMapper.selectCount(queryWrapper);
    }

    private long getRoute(){
        LambdaQueryWrapper<BizCustomerRoute> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomerRoute::getStatus, 1);
        return bizCustomerRouteMapper.selectCount(queryWrapper);
    }

    private long getWarehouse(){
        LambdaQueryWrapper<BizCustomerWarehouse> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCustomerWarehouse::getStatus, 1);
        return bizCustomerWarehouseMapper.selectCount(queryWrapper);
    }

    private long getOnDutyCar() {
        LambdaQueryWrapper<BizCar> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCar::getStatus,1);
        return bizCarMapper.selectCount(queryWrapper);
    }

    private long getOnDutyDriver() {
        LambdaQueryWrapper<BizDriver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizDriver::getStatus,1);
        return bizDriverMapper.selectCount(queryWrapper);
    }

    private long getIncompleteOrder(String today) {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(BizOrder::getCreateTime, today);
        queryWrapper.in(BizOrder::getOrderStatus,"1","2");
        queryWrapper.eq(BizOrder::getStatus,1);
        return bizOrderMapper.selectCount(queryWrapper);
    }

    private long getCompletedOrder(String today) {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(BizOrder::getCreateTime,today);
        queryWrapper.eq(BizOrder::getOrderStatus,"3");
        queryWrapper.eq(BizOrder::getStatus,1);
        return bizOrderMapper.selectCount(queryWrapper);
    }

    private double getDeliveryMileage() {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizOrder::getOrderStatus,"3");
        queryWrapper.eq(BizOrder::getStatus,1);
        List<BizOrder> bizOrders = bizOrderMapper.selectList(queryWrapper);
        double deliveryMileage = 0;
        for (BizOrder bizOrder : bizOrders) {
            if (ObjectUtil.isNotEmpty(bizOrder.getLineDistance())) deliveryMileage += bizOrder.getLineDistance();
        }
        return deliveryMileage;
    }

    private long getDriveCount(Integer onlineStatus) {
        LambdaQueryWrapper<BizDriver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizDriver::getOnlineStatus,onlineStatus);
        queryWrapper.eq(BizDriver::getStatus,1);
        return bizDriverMapper.selectCount(queryWrapper);
    }

    /**
     * 公共方法-计算比率
     * @param divisor 除数
     * @param dividend 被除数
     * @return
     */
    private double commonComputeRatio(long divisor, long dividend) {
        double ratio = 0d;
        if (divisor == 0) return ratio;
        if (dividend !=0 ){
            // 比率 = 某条件下的项目数 / 总项目数
            ratio = (double) divisor / dividend * 100;
            ratio = this.keepTwoDecimals(ratio);//保留两位小数
        }
        return ratio;
    }

    /**
     * 公共方法-保留两位小数
     */
    private double keepTwoDecimals(double nums){
        if (nums != 0){
            return new BigDecimal(nums).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//保留两位小数
        }
        return 0d;
    }

}
