package com.kym.admin.jobs;

import com.alibaba.fastjson2.JSON;
import com.kym.entity.WashDevice;
import com.kym.entity.WashOrder;
import com.kym.entity.awoara.OrderInfo;
import com.kym.service.OrderSettlementService;
import com.kym.service.WashDeviceService;
import com.kym.service.WashOrderService;
import com.kym.service.awoara.AwoaraService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 僵死订单对账定时任务
 * 扫描长时间未结算的订单，主动查询设备状态进行兜底结算
 *
 * @author skyline
 */
@Slf4j
@Component
public class StaleOrderReconciliationJob {

    private final WashOrderService washOrderService;
    private final WashDeviceService washDeviceService;
    private final AwoaraService awoaraService;
    private final OrderSettlementService orderSettlementService;

    /**
     * 僵死订单阈值（秒），默认30分钟
     */
    @Value("${kym.stale-order-threshold-seconds:1800}")
    private int staleOrderThresholdSeconds;

    public StaleOrderReconciliationJob(WashOrderService washOrderService,
                                       WashDeviceService washDeviceService,
                                       AwoaraService awoaraService,
                                       OrderSettlementService orderSettlementService) {
        this.washOrderService = washOrderService;
        this.washDeviceService = washDeviceService;
        this.awoaraService = awoaraService;
        this.orderSettlementService = orderSettlementService;
    }

    /**
     * 每5分钟扫描一次僵死订单
     */
    @Async("AsyncExecutor")
    @Scheduled(cron = "0 */5 * * * ?")
    public void reconcileStaleOrders() {
        log.info("僵死订单对账-开始");
        var threshold = LocalDateTime.now().minusSeconds(staleOrderThresholdSeconds);

        List<WashOrder> staleOrders = washOrderService.lambdaQuery()
                .eq(WashOrder::getOrderStatus, WashOrder.ORDER_STATUS_开机)
                .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付)
                .le(WashOrder::getStartTime, threshold)
                .list();

        if (staleOrders.isEmpty()) {
            log.info("僵死订单对账-无僵死订单");
            return;
        }

        log.info("僵死订单对账-发现 {} 个僵死订单", staleOrders.size());

        for (WashOrder order : staleOrders) {
            try {
                reconcileOrder(order);
            } catch (Exception e) {
                log.error("僵死订单对账-订单 {} 处理异常", order.getOrderId(), e);
            }
        }

        log.info("僵死订单对账-结束");
    }

    private void reconcileOrder(WashOrder order) {
        log.info("僵死订单对账-处理订单：{}，设备：{}/{}", order.getOrderId(), order.getProductKey(), order.getDeviceName());

        // 策略1：主动查询设备上的订单状态
        try {
            OrderInfo orderInfo = awoaraService.queryOrder(order.getProductKey(), order.getDeviceName(), order.getOrderId());
            if (orderInfo != null && orderInfo.getClose_type() != null && !orderInfo.getClose_type().isEmpty()) {
                log.info("僵死订单对账-订单 {} 设备已关闭，执行结算", order.getOrderId());
                orderSettlementService.settleOrder(order, orderInfo);
                return;
            }
            if (orderInfo != null && (orderInfo.getClose_type() == null || orderInfo.getClose_type().isEmpty())) {
                log.info("僵死订单对账-订单 {} 设备仍在进行中，跳过", order.getOrderId());
                return;
            }
        } catch (Exception e) {
            log.warn("僵死订单对账-订单 {} 查询设备失败：{}，尝试兜底策略", order.getOrderId(), e.getMessage());
        }

        // 策略2：设备不可达，检查设备在DB中的状态
        var device = washDeviceService.lambdaQuery()
                .eq(WashDevice::getProductKey, order.getProductKey())
                .eq(WashDevice::getDeviceName, order.getDeviceName())
                .one();

        if (device != null && WashDevice.STATE_空闲.equals(device.getState())) {
            log.info("僵死订单对账-订单 {} 设备已空闲，使用最后已知数据兜底结算", order.getOrderId());
            settleWithLastKnownData(order);
            return;
        }

        // 策略3：设备不可达且状态未知，标记异常等待人工处理
        log.warn("僵死订单对账-订单 {} 无法自动处理，设备状态：{}，标记异常",
                order.getOrderId(), device != null ? device.getState() : "unknown");
        washOrderService.lambdaUpdate()
                .set(WashOrder::getStopReason, "僵死订单-无法自动结算，设备状态：" + (device != null ? device.getState() : "unknown"))
                .eq(WashOrder::getId, order.getId())
                .update();
    }

    /**
     * 使用最后一次 order_update 保存的数据进行兜底结算
     */
    private void settleWithLastKnownData(WashOrder order) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrder_id(order.getOrderId());
        orderInfo.setOrder_id_local(order.getOrderIdLocal());
        orderInfo.setOpen_type(order.getOpenType());
        orderInfo.setClose_type("reconcile");
        orderInfo.setAmount(order.getAmount() != null ? order.getAmount() : 0);
        orderInfo.setAmount_receivable(order.getAmountReceivable() != null ? order.getAmountReceivable() : 0);
        orderInfo.setAmount_received(order.getAmountReceived() != null ? order.getAmountReceived() : 0);
        orderInfo.setDiscount_money(order.getDiscountMoney() != null ? order.getDiscountMoney() : 0);
        orderInfo.setMember_discount(order.getMemberDiscount() != null ? order.getMemberDiscount() : 100);
        orderInfo.setPrepay_money(order.getPrepayMoney() != null ? order.getPrepayMoney() : 0);
        orderInfo.setOperation_remain_time(order.getOperationRemainTime() != null ? order.getOperationRemainTime() : 0);
        orderInfo.setIdle_remain_time(order.getIdleRemainTime() != null ? order.getIdleRemainTime() : 0);
        if (order.getDetail() != null) {
            orderInfo.setDetail(order.getDetail());
        }

        log.info("僵死订单对账-订单 {} 兜底结算数据：amount={}, amount_received={}",
                order.getOrderId(), orderInfo.getAmount(), orderInfo.getAmount_received());

        order.setStopReason("僵死订单-设备已空闲，使用最后更新数据结算");
        washOrderService.updateById(order);

        orderSettlementService.settleOrder(order, orderInfo);
    }
}
