package com.sckw.transport.handler;


import com.alibaba.fastjson.JSON;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.transport.model.KwtWaybillOrder;
import com.sckw.transport.model.KwtWaybillOrderNode;
import com.sckw.transport.model.KwtWaybillOrderSubtask;
import com.sckw.transport.model.param.OrderCirculateTakingQueryParam;
import com.sckw.transport.model.param.WaybillOrderCmeIntoWeighParam;
import com.sckw.transport.model.param.WaybillOrderLeaveMockParam;
import com.sckw.transport.model.param.WaybillOrderProcessParam;
import com.sckw.transport.repository.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * Author: donglang
 * Time: 2025-11-19
 * Des: 运单操作处理器
 * Version: 1.0
 */

@Slf4j
public abstract class AbstractWaybillOrderHandler<T extends WaybillOrderProcessParam> {

    // 依赖的Repository等组件
    @Autowired
    protected KwtWaybillOrderRepository waybillOrderRepository;
    @Autowired
    protected KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
    @Autowired
    protected KwtWaybillOrderNodeRepository waybillOrderNodeRepository;
    @Autowired
    protected KwtWaybillOrderTicketRepository waybillOrderTicketRepository;
    @Autowired
    protected KwtLogisticsOrderRepository logisticsOrderRepository;
    @Autowired
    protected KwtWaybillOrderAddressRepository waybillOrderAddressRepository;
    @Autowired
    protected KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    protected RemoteFleetService remoteFleetService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 80000)
    protected TradeOrderInfoService tradeOrderInfoService;



    /**
     * 模板方法 - 定义处理流程
     */
    @Transactional(rollbackFor = Exception.class)
    public void handler(T param) {
        try {
            log.info("开始处理{}，参数：{}", getProcessName(), JSON.toJSONString(param));

            // 1. 参数校验
            validate(param);
            // 2. 获取运单（接单时返回null）
            KwtWaybillOrder waybillOrder = getWaybillOrder(param);
            // 3. 状态校验
            checkState(param, waybillOrder);
            // 4. 核心业务
            doBusiness(param, waybillOrder);
            // 5. 更新状态
            updateStatus(param, waybillOrder);
            // 6. 生成节点轨迹
            createNodeTrace(param, waybillOrder);
            // 7. 后置处理
            afterProcess(param, waybillOrder);

            log.info("{}处理完成", getProcessName());
        } finally {
            // 确保清理线程上下文，防止内存泄漏
            BusinessContext.clear();
        }

    }

    // 1. 参数校验
    protected void validate(T param) {
        if (param == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "参数不能为空");
        }
        // 非接单流程必须校验运单ID
        if (!(param instanceof OrderCirculateTakingQueryParam) && param.getWaybillOrderId() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "运单ID不能为空");
        }
        // 过磅校验
        if (param instanceof WaybillOrderCmeIntoWeighParam || param instanceof WaybillOrderLeaveMockParam) {
            if (param.getWeighbridgeId() == null || param.getWeighbridgeName() == null || param.getWeighUrl() == null) {
                throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "地磅信息不能为空");
            }
        }
    }

    // 2. 获取运单
    protected abstract KwtWaybillOrder getWaybillOrder(T param);

    // 3. 状态校验
    protected abstract void checkState(T param, KwtWaybillOrder waybillOrder);

    // 4. 核心业务
    protected abstract void doBusiness(T param, KwtWaybillOrder waybillOrder);

    // 5. 更新状态
    protected abstract void updateStatus(T param, KwtWaybillOrder waybillOrder);

    // 6. 生成节点轨迹
    protected void createNodeTrace(T param, KwtWaybillOrder waybillOrder) {
        if (waybillOrder == null) {
            return;
        }
        KwtWaybillOrderNode node = getWaybillOrderNode(param, waybillOrder);
        node.setRemark(getRemark(param, waybillOrder));
        waybillOrderNodeRepository.save(node);
        log.info("记录{}节点轨迹成功，节点ID：{}", getProcessName(), node.getId());
    }


    public KwtWaybillOrderNode getWaybillOrderNode(T param, KwtWaybillOrder waybillOrder) {
        log.info("创建车辆运单-节点轨迹入参参数：{}", JSON.toJSONString(param));
        KwtWaybillOrderSubtask subtask = getWaybillSubtask(waybillOrder.getId());
        KwtWaybillOrderNode node = new KwtWaybillOrderNode();
        node.setWOrderId(waybillOrder.getId());
        node.setWSubtaskId(subtask.getId());
        node.setOrderStatus(waybillOrder.getStatus());
        node.setTruckId(waybillOrder.getTruckId());
        node.setTruckNo(waybillOrder.getTruckNo());
        node.setDriverId(waybillOrder.getDriverId());
        node.setDriverName(waybillOrder.getDriverName());
        node.setWeighbridgeId(param.getWeighbridgeId());
        node.setWeighbridgeName(param.getWeighbridgeName());
        node.setWeighUrl(param.getWeighUrl());
        node.setLng(param.getLng());
        node.setLat(param.getLat());
        return node;
    }

    // 7. 后置处理
    protected void afterProcess(T param, KwtWaybillOrder waybillOrder) {}

    protected abstract String getProcessName();


    protected abstract String getRemark(T param, KwtWaybillOrder waybillOrder);


    /**
     * 查询运单
     */
    protected KwtWaybillOrder getWaybillOrder(Long waybillOrderId) {
        KwtWaybillOrder waybillOrder = waybillOrderRepository.queryByBillOrderId(waybillOrderId);
        if (waybillOrder == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_NOT_FOUND, "物流运单不存在！");
        }
        return waybillOrder;
    }

    /**
     * 查询子运单
     */
    protected KwtWaybillOrderSubtask getWaybillSubtask(Long waybillOrderId) {
        KwtWaybillOrderSubtask subtask = waybillOrderSubtaskRepository.queryByWOrderId(waybillOrderId);
        if (subtask == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_SUB_NOT_FOUND, "未找到关联的子运单！");
        }
        return subtask;
    }




}

