package com.ghy.quartz.service.impl;

import com.ghy.common.enums.FinancialDetailType;
import com.ghy.common.enums.OrderStatus;
import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.FinancialDetailService;
import com.ghy.quartz.service.OrderService;
import com.ghy.system.domain.SysDeptConfig;
import com.ghy.system.service.ISysDeptConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    /**
     * 需要超时扣款的订单状态
     */
    @Value("${order.timeout.status:-4,-3,-2,1,2,3}")
    private List<Integer> timeoutOrderStatus;

    @Resource
    private ThreadPoolTaskExecutor executor;
    @Resource
    private OrderMasterService orderMasterService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OrderFineRecordMapper orderFineRecordMapper;
    @Resource
    private FinancialDetailService financialDetailService;
    @Resource
    private ISysDeptConfigService sysDeptConfigService;

    @Override
    public void overTimeOrder(String orderStatus) {
        // 这是半小时前的时间
        Date halfHour = new Date(System.currentTimeMillis() - 30 * 60 * 1000);
        // 这是4小时前的时间
        Date fourHour = new Date(System.currentTimeMillis() - 4 * 60 * 60 * 1000);

        // 查询符合超时的单
        List<OrderDetail> orders = orderDetailService.selectByStatus(timeoutOrderStatus);
        for (OrderDetail order : orders) {
            if (order.getOrderStatus().equals(OrderStatus.SERVER.code())) {
                // 服务中状态要按预计上门时间计算超时 4h超时并且扣款
                if (order.getExpectTimeStart().before(fourHour)) {
                    executor.execute(() -> orderTimeout(order, true));
                }
            } else if (timeoutOrderStatus.contains(order.getOrderStatus())) {
                // 其它状态用update_time判断超时 30min超时 4h扣款
                if (fourHour.after(order.getUpdateTime())) {
                    executor.execute(() -> orderTimeout(order, true));
                } else if (order.getUpdateTime().before(halfHour)) {
                    executor.execute(() -> orderTimeout(order, false));
                }
            }
        }

    }

    /**
     * 处理订单超时与扣款
     *
     * @param order 子订单信息
     * @param fine  是否需要扣款
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderTimeout(OrderDetail order, boolean fine) {
        OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getOrderStatus());
        List<OrderTimeoutRecord> records = orderFineRecordMapper.selectList(record);
        if (CollectionUtils.isEmpty(records)) {
            // 如果没有扣款记录 则保存一条扣款记录
            record.setFineStatus(0);
            orderFineRecordMapper.insert(record);
        } else {
            record = records.get(0);
        }

        if (!fine) {
            // 不需要扣款
            return;
        }
        if (record.getFineStatus() == 1) {
            // 如果已经扣款 就不需要往下走了
            return;
        }

        // 把超时记录的扣款状态改为1
        record.setFineStatus(1);
        orderFineRecordMapper.update(record);

        FinancialDetail orderFinancial = financialDetailService.selectByOrderDetailId(order.getId());
        SysDeptConfig deptConfig = sysDeptConfigService.selectByDeptId(order.getDeptId());
        BigDecimal timeoutMoney = deptConfig.getGoingOutTime();
        // 如果扣款额为null或<0
        if (timeoutMoney == null || BigDecimal.ZERO.compareTo(timeoutMoney) > 0) {
            timeoutMoney = BigDecimal.ZERO;
        }
        BigDecimal timeoutRate = deptConfig.getGoingOutTimeRate();
        // 如果扣款比例 为null 或 <0 或 >1.00
        if (timeoutRate == null || BigDecimal.ZERO.compareTo(timeoutRate) > 0 || BigDecimal.ONE.compareTo(timeoutRate) < 0) {
            timeoutRate = BigDecimal.ZERO;
        }
        timeoutMoney = orderFinancial.getPayMoney().multiply(timeoutRate).add(timeoutMoney);
        if (BigDecimal.ZERO.compareTo(timeoutMoney) == 0) {
            // 如果罚金=0时 无需扣款
            logger.info("订单[ID={}]超时无需扣款 GoingOutTime={}, GoingOutTimeRate={}", order.getId(),
                    deptConfig.getGoingOutTime(), deptConfig.getGoingOutTimeRate());
            return;
        }
        if (timeoutMoney.compareTo(orderFinancial.getPayMoney()) > 0) {
            // 如果罚金大于本单金额的情况
            logger.warn("订单[ID={}]超时罚金[{}]大于订单金额[{}]!!! GoingOutTime={}, GoingOutTimeRate={}", order.getId(),
                    timeoutMoney, orderFinancial.getPayMoney(), deptConfig.getGoingOutTime(), deptConfig.getGoingOutTimeRate());
            timeoutMoney = orderFinancial.getPayMoney();
        }

        //下面是扣款逻辑
        // 从子订单对应的财务单里扣除2元
        orderFinancial.setPayMoney(orderFinancial.getPayMoney().subtract(timeoutMoney));
        financialDetailService.updateFinancialDetail(orderFinancial);

        // 生成对应的扣款明细
        FinancialDetail fineFinancial = new FinancialDetail();
        fineFinancial.setDeptId(orderFinancial.getDeptId());
        fineFinancial.setCode(financialDetailService.createCode());
        fineFinancial.setFinancialMasterId(orderFinancial.getFinancialMasterId());
        fineFinancial.setFinancialMasterCode(orderFinancial.getFinancialMasterCode());
        fineFinancial.setPayMoney(timeoutMoney);
        fineFinancial.setFinancialDetailType(FinancialDetailType.FINE_FEE.getCode());
        financialDetailService.insertFinancialDetail(fineFinancial);
    }


    @Override
    public void autoFinishOrder() {
        // 子订单自动完单
        // 查询出"待确认"状态的子订单
        List<OrderDetail> orderDetails = orderDetailService.selectByStatus(Collections.singletonList(OrderStatus.FINISH_CHECK.code()));
        long now = System.currentTimeMillis();
        long day14ago = now - (60 * 60 * 1000L);
//        long day14ago = now - 10000L;
        for (OrderDetail orderDetail : orderDetails) {
            // 筛选符合自动确认的订单
            if (day14ago > orderDetail.getWorkFinishTime().getTime()) {
                logger.info("子订单自动完成[id={}, code={}]", orderDetail.getId(), orderDetail.getCode());
                try {
                    // 子订单完单流程(分账与提现)
                    orderDetailService.finish(orderDetail.getId());
                } catch (Exception e) {
                    logger.error("子订单自动完成[id={}, code={}]出错", orderDetail.getId(), orderDetail.getCode(), e);
                }
            }
        }

        // 主订单自动完单
        List<OrderMaster> orderMasters = orderMasterService.selectUnfinished();
        for (OrderMaster om : orderMasters) {
            try {
                boolean allAssign = orderMasterService.isAllAssign(om.getId());
                // 如果存在未派单的子订单 就不刷新主单状态
                if (!allAssign) {
                    continue;
                }
                List<OrderDetail> ods = orderDetailService.selectByOrderMasterId(om.getId());
                Set<Integer> statusSet = ods.stream().map(OrderDetail::getOrderStatus).collect(Collectors.toSet());
                // 没有子单,未派单的情况不刷新主单状态
                if (CollectionUtils.isEmpty(statusSet)) {
                    continue;
                }
                boolean allFinish = true;
                for (Integer integer : statusSet) {
                    if (integer < 5) {
                        allFinish = false;
                        break;
                    }
                }
                // 如果已经不存在"已完成"和"已取消"以外的子订单 就把主订单也改为完成
                if (allFinish) {
                    logger.info("主订单自动完成[id={} code={}]", om.getId(), om.getCode());
                    orderMasterService.finish(om.getId());
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    @Override
    public void autoChangeDrawCashStatus() {
//        LocalDate now = LocalDate.now();
//        DayOfWeek dayOfWeek = now.getDayOfWeek();
//        if (dayOfWeek.getValue() > 5) {
//            return;
//        }
//        OrderDetail orderDetail = new OrderDetail();
//        orderDetail.setDrawCashStatus(1);
//        List<OrderDetail> orderDetails = orderDetailService.selectOrderDetailList(orderDetail);
//        long before24h = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
//        for (OrderDetail od : orderDetails) {
//            if (od.getDrawCashDate().getTime() < before24h) {
//                OrderDetail update = new OrderDetail();
//                update.setId(od.getId());
//                update.setOrderStatus(2);
//                orderDetailService.updateOrderDetail(update);
//                logger.info("订单[{}]自动提现成功", od.getCode());
//            }
//        }
    }

}
