package com.sckw.transport.handler;


import com.alibaba.fastjson.JSON;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.contract.api.feign.LogisticsScoreFeignService;
import com.sckw.contract.api.model.dto.req.LogisticsScoreDetailFeignDto;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.model.enums.CarWaybillV1Enum;
import com.sckw.core.model.enums.DispatchWayEnums;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.dto.RUpdateDriverScoreDto;
import com.sckw.fleet.api.model.vo.DriverConductRulesVO;
import com.sckw.fleet.api.model.vo.TruckDispatchCoefficientVO;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.transport.model.*;
import com.sckw.transport.model.param.*;
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;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 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;
    @Autowired
    protected KwtLogisticsOrderCirculateRepository logisticsOrderCirculateRepository;
    @Autowired
    protected KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
    @Autowired
    protected KwtLogisticsOrderGoodsRepository logisticsOrderGoodsRepository;
    @Autowired
    protected KwtGatekeeperWaybillOrderRepository gatekeeperWaybillOrderRepository;
    @Autowired
    protected KwtForkliftWaybillOrderRepository forkliftWaybillOrderRepository;
    @Autowired
    protected KwtWaybillOrderWeighbridgeRepository waybillOrderWeighbridgeRepository;

    @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;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteContractService remoteContractService;

    @Autowired
    LogisticsScoreFeignService logisticsScoreFeignService;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    GoodsInfoService goodsInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    protected RemoteSystemService remoteSystemService;

    /**
     * 模板方法 - 定义处理流程
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderTakingResp 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(waybillOrder);
            // 6. 生成节点轨迹
            createNodeTrace(param, waybillOrder);
            //7.自动派单计算分值
            calculateScore(param, waybillOrder);
            // 8. 后置处理
            OrderTakingResp handlerResult = afterProcess(param, waybillOrder);

            log.info("{}处理完成", getProcessName());
            return handlerResult;
        } catch (Exception e) {
            log.error("运单处理器异常！", e);
            throw new BusinessPlatfromException(ErrorCodeEnum.SYSTEM_ERROR, e.getMessage());
        }  finally {
            // 确保清理线程上下文，防止内存泄漏
            BusinessContext.clear();
        }

    }

    // 1. 参数校验
    protected void validate(T param) {
        if (param == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "参数不能为空");
        }
        if (!(param instanceof WaybillOrderCancelParam || param instanceof WaybillOrderCmeIntoWeighParam
                || param instanceof WaybillOrderUnloadingWeighParam ||  param instanceof WaybillOrderReplenishParam)) {
            if (StringUtils.isBlank(param.getLng()) || StringUtils.isBlank(param.getLat())) {
                throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "未获取到定位，请重启app后再次操作");
            }
        }
        // 非接单流程必须校验运单ID
        if (!(param instanceof OrderCirculateTakingQueryParam) && param.getWaybillOrderId() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "运单ID不能为空");
        }
        // 过磅校验
        if (param instanceof WaybillOrderCmeIntoWeighParam || param instanceof WaybillOrderUnloadingWeighParam) {
            if (param.getWeighbridgeId() == null || param.getWeighbridgeName() == 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 void updateStatus(KwtWaybillOrder waybillOrder) {
        if (waybillOrder == null) {
            //接单已经初始化了，无需额外更新
            return;
        }
        getStatus(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;
    }

    /**
     * 计算自动派车的行为分数
     * @param param
     * @param waybillOrder
     */
    protected void calculateScore(T param, KwtWaybillOrder waybillOrder) {
        if (!(param instanceof OrderCirculateTakingQueryParam) && DispatchWayEnums.AUTO_DISPATCH.getCode().equals(waybillOrder.getDispatchWay())) {
            calculateAutoDispatchScore(param, waybillOrder);
        }

    }

    // //7.自动派单计算分值
    protected abstract void calculateAutoDispatchScore(T param, KwtWaybillOrder waybillOrder);


    // 8. 后置处理
    protected OrderTakingResp afterProcess(T param, KwtWaybillOrder waybillOrder) {
        return new OrderTakingResp();
    }

    protected abstract String getProcessName();

    protected abstract void getStatus(KwtWaybillOrder waybillOrder);

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


    /**
     * 查询物流订单
     */
    protected KwtLogisticsOrder getLogisticsOrder(Long logOrderId) {
        KwtLogisticsOrder logisticsOrder = logisticsOrderRepository.queryByLogisticsOrderId(logOrderId);
        if (logisticsOrder == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.LOGISTICS_ORDER_NOT_FOUND, "物流订单数据不存在！");
        }
        return logisticsOrder;
    }

    /**
     * 查询运单
     */
    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;
    }

    /**
     * 查询运单节点
     */
    protected KwtWaybillOrderNode getNodesByOrderId(Long waybillOrderId, Integer status) {
        KwtWaybillOrderNode orderNode = waybillOrderNodeRepository.queryNodesByOrderId(waybillOrderId, status);
        if (orderNode == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_NODE_NOT_EXIST, "未找到关联的运单节点数据！");
        }
        return orderNode;
    }


    // 查询供应商id
    protected Long getSupplierId(KwtWaybillOrder waybillOrder) {
        if (waybillOrder == null) {
            return 0L;
        }
        //查询订单托运单位
        KwtLogisticsOrderUnit logisticsOrderUnit = logisticsOrderUnitRepository.queryByLOrderIdAndUnitType(waybillOrder.getLOrderId(), 1);
        if (logisticsOrderUnit == null || logisticsOrderUnit.getEntId() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.LOGISTICS_ORDER_NOT_ENT, "未找到关联的物流订单托运企业（供应商）！");
        }
        return logisticsOrderUnit.getEntId();
    }


    /**
     * 查询司机所在企业的供应商派车系数
     */
    protected TruckDispatchCoefficientVO getAutoTruckDispatchByEntId(Long entId) {
        TruckDispatchCoefficientVO truckDispatchVO = remoteFleetService.findAutoTruckDispatchByEntId(entId);
        if (truckDispatchVO == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到自动派车系数！");
        }
        return truckDispatchVO;
    }

    /**
     * 查询司机所在企业的供应商司机行为规则
     */
    protected DriverConductRulesVO getDriverConductRulesByEntId(Long entId) {
        DriverConductRulesVO driverRulesVO = remoteFleetService.findDriverConductRulesByEntId(entId);
        if (driverRulesVO == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "未找到司机行为规则数据！");
        }
        return driverRulesVO;
    }

    /**
     * 查询该司机连续卸货节点数据
     * @param waybillOrder
     * @param continuousOnTimes
     * @return
     */
    protected List<KwtWaybillOrderNode> getWaybillOrderNodesByStatus(KwtWaybillOrder waybillOrder, Integer continuousOnTimes, CarWaybillV1Enum waybillV1Enum) {
        //司机运单数据
        List<KwtWaybillOrder> waybillOrders = waybillOrderRepository.queryByEntId(waybillOrder.getEntId(), waybillOrder.getDriverId());
        if (CollectionUtils.isEmpty(waybillOrders)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_NOT_FOUND, "物流运单不存在！");
        }
        List<Long> wOrderIds = waybillOrders.stream().map(KwtWaybillOrder::getId).collect(Collectors.toList());
        //查询司机的节点数据
        List<KwtWaybillOrderNode> waybillOrderNodeList = waybillOrderNodeRepository
                .queryContinuousNodesByDriverId(wOrderIds, waybillOrder.getDriverId(), waybillV1Enum.getCode());
        if (CollectionUtils.isEmpty(waybillOrderNodeList) || waybillOrderNodeList.size() < continuousOnTimes) {
            log.info("司机{}按时接节点不足{}次，当前记录数：{}", waybillOrder.getDriverId(), continuousOnTimes, waybillOrderNodeList.size());
            return Collections.emptyList();
        }
        return waybillOrderNodeList;
    }

    /**
     * 修改司机评分
     * @param supeEntId
     * @param entId
     * @param driverId
     * @param score
     */
    public void updateDriverScore(Long supeEntId, Long entId, Long driverId, Integer score, String action) {
        RUpdateDriverScoreDto dto = new RUpdateDriverScoreDto();
        dto.setSupEntId(supeEntId);
        dto.setLogEntId(entId);
        dto.setDriverId(driverId);
        dto.setScore(BigDecimal.valueOf(score));
        dto.setAction(action);

        remoteFleetService.updateDriverScoreByEntId(dto);
    }

    /**
     * 更新企业评分
     * @param waybillOrder
     * @param supplierId
     * @param score
     */
    public void updateLogEntScore(KwtWaybillOrder waybillOrder, Long supplierId, Integer score, String remark) {
        LogisticsScoreDetailFeignDto detailDto = new LogisticsScoreDetailFeignDto();
        detailDto.setProviderEntId(supplierId);
        detailDto.setLogisticsEntId(waybillOrder.getEntId());
        detailDto.setPhone(waybillOrder.getDriverPhone());
        detailDto.setAction(remark);
        detailDto.setScoreChange(BigDecimal.valueOf(score));
        logisticsScoreFeignService.updateLogisticsScore(detailDto);
    }
}

