package com.njzscloud.dispose.cst.order.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.utils.GroupUtil;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.security.util.SecurityUtil;
import com.njzscloud.common.sn.support.SnUtil;
import com.njzscloud.dispose.common.pojo.entity.BaseEntity;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import com.njzscloud.dispose.cst.customer.mapper.CustomerMapper;
import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity;
import com.njzscloud.dispose.cst.driver.mapper.DriverMapper;
import com.njzscloud.dispose.cst.driver.pojo.entity.DriverEntity;
import com.njzscloud.dispose.cst.order.constant.*;
import com.njzscloud.dispose.cst.order.helper.PaymentRecordHelper;
import com.njzscloud.dispose.cst.order.mapper.OrderMapper;
import com.njzscloud.dispose.cst.order.mapper.OrderTransMapper;
import com.njzscloud.dispose.cst.order.pojo.entity.*;
import com.njzscloud.dispose.cst.order.pojo.param.*;
import com.njzscloud.dispose.cst.order.pojo.result.*;
import com.njzscloud.dispose.cst.project.pojo.entity.ProjectEntity;
import com.njzscloud.dispose.cst.project.service.ProjectService;
import com.njzscloud.dispose.cst.station.mapper.StationMapper;
import com.njzscloud.dispose.cst.station.pojo.entity.StationEntity;
import com.njzscloud.dispose.cst.truck.mapper.TruckMapper;
import com.njzscloud.dispose.cst.truck.pojo.entity.TruckEntity;
import com.njzscloud.dispose.finance.constant.ExpenseItemCategory;
import com.njzscloud.dispose.finance.mapper.MoneyAccountMapper;
import com.njzscloud.dispose.finance.pojo.entity.ExpenseItemEntity;
import com.njzscloud.dispose.finance.pojo.entity.MoneyAccountEntity;
import com.njzscloud.dispose.finance.pojo.result.MoneyAccountResult;
import com.njzscloud.dispose.finance.service.ExpenseItemService;
import com.njzscloud.dispose.sys.auth.pojo.result.MyResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.njzscloud.dispose.event.SysMittEvent.PURCHASE_ORDER;
import static com.njzscloud.dispose.event.SysMittEvent.SALES_ORDER;

/**
 * 收/销订单
 *
 * @author ljw
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService extends ServiceImpl<OrderMapper, OrderEntity> {

    private final OrderCargoPlaceService orderCargoPlaceService;
    private final OrderTransMapper orderTransMapper;
    private final ExpenseItemService expenseItemService;
    private final DriverMapper driverMapper;
    private final TruckMapper truckMapper;
    private final CustomerMapper customerMapper;
    private final OrderExpenseItemsService orderExpenseItemsService;
    private final OrderPaymentRecordService orderPaymentRecordService;
    private final MoneyAccountMapper moneyAccountMapper;
    private final StationMapper stationMapper;
    private final PaymentRecordHelper paymentRecordHelper;
    private final ProjectService projectService;

    @Transactional(rollbackFor = Exception.class)
    public void add(CreateOrderParam param) {
        // 订单信息
        param.setOrderStatus(OrderStatus.YiYuYue);
        Long transOrgId = param.getTransOrgId();
        OrderStatus orderStatus = transOrgId == null ? OrderStatus.YiYuYue : OrderStatus.JinXingZhong;
        MyResult userDetail = SecurityUtil.loginUser();
        OrderEntity orderEntity = BeanUtil.copyProperties(param, OrderEntity.class)
            .setSn(this.generateSn())
            .setUserId(SecurityUtil.currentUserId())
            .setCustomerId(userDetail.getCurrentCustomerId())
            .setOrderTime(LocalDateTime.now())
            .setOrderStatus(orderStatus)
            .setAssignmentTransTime(transOrgId == null ? null : LocalDateTime.now());
        this.save(orderEntity);

        // 装卸货信息
        CreateOrderCargoPlaceParam cargoPlace = param.getCargoPlaceParam();
        OrderCargoPlaceEntity placeEntity = BeanUtil.copyProperties(cargoPlace, OrderCargoPlaceEntity.class)
            .setOrderId(orderEntity.getId());
        if (OrderCategory.HuiShouYuYue.equals(param.getOrderCategory())) {
            placeEntity.setZx(Zx.ZhuangHuo.getVal());
        } else if (OrderCategory.XiaoShouYuYue.equals(param.getOrderCategory())) {
            placeEntity.setZx(Zx.XieHuo.getVal());
        }
        orderCargoPlaceService.add(placeEntity);

        // 运输信息
        int transNum = orderEntity.getEstimatedTrainNum();
        OrderTransEntity transEntity;
        for (int i = 1; i <= transNum; i++) {
            transEntity = new OrderTransEntity();
            transEntity.setOrderId(orderEntity.getId());
            transEntity.setTrainNum(i);
            transEntity.setTransStatus(transOrgId == null ? null : TransStatus.DaiPaiDan);
            transEntity.setTransTime(transOrgId == null ? null : LocalDateTime.now());
            transEntity.setCheckStatus(CheckStatus.WeiKanLiao);
            transEntity.setTransDistance(param.getTransDistance());
            orderTransMapper.insert(transEntity);
        }
        // 付费项
        if (transOrgId != null) {
            this.createOrderExpenseItems(orderEntity);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void modify(OrderEntity orderEntity) {
        this.updateById(orderEntity);
    }

    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        this.removeBatchByIds(ids);
    }

    public OrderResult miniDetail(Long id) {
        OrderResult result = baseMapper.miniDetail(id);
        // 1.通过订单ID查询付费记录
        List<OrderPaymentRecordResult> recordResults = baseMapper.getPaymentRecordByOrderId(id);
        result.setOrderPaymentRecordList(recordResults);
        // 合计金额 = 付费记录中 totalSettleMoney 的和
        BigDecimal totalSettleMoney = recordResults.stream()
            .map(OrderPaymentRecordResult::getTotalSettleMoney)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        result.setSettleMoney(totalSettleMoney);

        // 2.通过订单ID查询运输信息
        List<TransResult> transResults = orderTransMapper.getTransResultByOrderId(id);
        result.setTransResultList(transResults);
        // 总毛重 = 运输信息中毛重的和
        Integer totalRoughWeight = transResults.stream()
            .map(TransResult::getRoughWeight)
            .filter(Objects::nonNull)
            .reduce(0, Integer::sum);
        result.setTotalRoughWeight(totalRoughWeight);
        // 总皮重 = 运输信息中皮重的和
        Integer totalTareWeight = transResults.stream()
            .map(TransResult::getTareWeight)
            .filter(Objects::nonNull)
            .reduce(0, Integer::sum);
        result.setTotalTareWeight(totalTareWeight);
        // 总净重 = 运输信息中净重的和
        Integer totalSettleWeight = transResults.stream()
            .map(TransResult::getSettleWeight)
            .filter(Objects::nonNull)
            .reduce(0, Integer::sum);
        result.setTotalSettleWeight(totalSettleWeight);

        return result;
    }

    public SearchOrderResult detail(Long id, String orderType) {
        SearchOrderResult detail = baseMapper.detail(id);
        if (detail == null) return null;
        Long orderId = detail.getId();
        Long projectId = detail.getProjectId();
        List<SearchOrderResult.TransRecode> transRecodeList = orderTransMapper.listTransRecode(Wrappers.query()
                .eq("a.order_id", orderId)
                .in("YuYue".equals(orderType), "a.trans_status", TransStatus.DaiPaiDan, TransStatus.DaiJieDan)
                .in("ShiShi".equals(orderType), "a.trans_status", TransStatus.YiJieDan, TransStatus.YunShuZhong, TransStatus.YiJinChang, TransStatus.YiChuChang)
                .eq("LiShi".equals(orderType), "a.trans_status", TransStatus.YiWanCheng)
                .eq("QuXiao".equals(orderType), "a.trans_status", TransStatus.YiQuXiao)
            )
            .stream()
            .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.TransRecode.class))
            .toList();

        OrderCargoPlaceEntity cargoPlaceEntity = orderCargoPlaceService.getOne(Wrappers.lambdaQuery(OrderCargoPlaceEntity.class).eq(OrderCargoPlaceEntity::getOrderId, orderId));
        SearchOrderResult.CargoPlace cargoPlace = BeanUtil.copyProperties(cargoPlaceEntity, SearchOrderResult.CargoPlace.class);

        SearchOrderResult.ProjectInfo projectInfo = null;
        if (projectId != null) {
            ProjectEntity projectEntity = projectService.getById(projectId);
            projectInfo = BeanUtil.copyProperties(projectEntity, SearchOrderResult.ProjectInfo.class);
        }

        List<SearchOrderResult.PaymentRecord> paymentRecordResultList = orderPaymentRecordService.listPaymentRecord(Wrappers.query().eq("a.order_id", orderId))
            .stream()
            .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.PaymentRecord.class))
            .toList();
        Map<Long, List<SearchOrderResult.PaymentRecord>> transId_paymentRecord_map = GroupUtil.k_a(paymentRecordResultList, SearchOrderResult.PaymentRecord::getTransId);

        for (SearchOrderResult.TransRecode transRecode : transRecodeList) {
            Long transRecodeId = transRecode.getId();
            transRecode.setPaymentRecord(transId_paymentRecord_map.get(transRecodeId));
        }
        detail.setTransRecodes(transRecodeList);
        detail.setCargoPlace(cargoPlace);
        detail.setProjectInfo(projectInfo);
        return detail;
    }

    public PageResult<SearchOrderResult> paging(PageParam pageParam, SearchOrderParam searchOrderParam) {
        String orderType = searchOrderParam.getOrderType();
        String bizType = searchOrderParam.getBizType();
        String sn = searchOrderParam.getSn();
        String stationName = searchOrderParam.getStationName();
        String contacts = searchOrderParam.getContacts();
        String phone = searchOrderParam.getPhone();
        String transOrgName = searchOrderParam.getTransOrgName();
        String projectName = searchOrderParam.getProjectName();
        String goodsName = searchOrderParam.getGoodsName();
        String keywords = searchOrderParam.getKeywords();
        LocalDateTime orderTimeStart = searchOrderParam.getOrderTimeStart();
        LocalDateTime orderTimeEnd = searchOrderParam.getOrderTimeEnd();

        QueryWrapper<Object> ew = Wrappers.query()
            .exists("YuYue".equals(orderType), "SELECT 1 FROM cst_order_trans b WHERE b.order_id = a.id AND b.trans_status IN ('DaiPaiDan','DaiJieDan')")
            .exists("ShiShi".equals(orderType), "SELECT 1 FROM cst_order_trans b WHERE b.order_id = a.id AND b.trans_status IN ('YiJieDan','YunShuZhong','YiJinChang','YiChuChang')")
            .exists("LiShi".equals(orderType), "SELECT 1 FROM cst_order_trans b WHERE b.order_id = a.id AND b.trans_status = 'YiWanCheng'")
            .exists("QuXiao".equals(orderType), "SELECT 1 FROM cst_order_trans b WHERE b.order_id = a.id AND b.trans_status = 'YiQuXiao'")
            .in("DuanBo".equals(bizType), "a.order_category", OrderCategory.DuanBoChu, OrderCategory.DuanBoRu)
            .eq("HuiShou".equals(bizType), "a.order_category", OrderCategory.HuiShouYuYue)
            .eq("XiaoShou".equals(bizType), "a.order_category", OrderCategory.XiaoShouYuYue)
            .like(StrUtil.isNotBlank(sn), "a.sn", sn)
            .like(StrUtil.isNotBlank(stationName), "a.station_name", stationName)
            .like(StrUtil.isNotBlank(contacts), "a.contacts", contacts)
            .like(StrUtil.isNotBlank(phone), "a.phone", phone)
            .like(StrUtil.isNotBlank(transOrgName), "j.org_name", transOrgName)
            .like(StrUtil.isNotBlank(projectName), "f.project_name", projectName)
            .like(StrUtil.isNotBlank(goodsName), "a.goods_name", goodsName)
            .ge(orderTimeStart != null, "a.order_time", orderTimeStart)
            .le(orderTimeEnd != null, "a.order_time", orderTimeEnd)
            .and(StrUtil.isNotBlank(keywords), it -> it
                .like("a.goods_name", keywords)
                .or().like("a.sn", keywords)
                .or().like("a.contacts", keywords)
                .or().like("a.phone", keywords)
                .or().like("j.org_name", keywords)
                .or().like("f.project_name", keywords)
            );
        Page<SearchOrderResult> page = pageParam.toPage();
        page.addOrder(OrderItem.desc("a.create_time"));
        IPage<SearchOrderResult> resultPage = baseMapper.paging(page, ew);
        List<SearchOrderResult> results = resultPage.getRecords();
        if (results.isEmpty()) return PageResult.of(resultPage);
        List<Long> orderIdList = results.stream().map(SearchOrderResult::getId).toList();
        List<Long> projectIdList = results.stream().map(SearchOrderResult::getProjectId).filter(Objects::nonNull).toList();
        List<SearchOrderResult.TransRecode> transRecodes = orderTransMapper.listTransRecode(Wrappers.query()
                .in("a.order_id", orderIdList)
                .in("YuYue".equals(orderType), "a.trans_status", TransStatus.DaiPaiDan, TransStatus.DaiJieDan)
                .in("ShiShi".equals(orderType), "a.trans_status", TransStatus.YiJieDan, TransStatus.YunShuZhong, TransStatus.YiJinChang, TransStatus.YiChuChang)
                .eq("LiShi".equals(orderType), "a.trans_status", TransStatus.YiWanCheng)
                .eq("QuXiao".equals(orderType), "a.trans_status", TransStatus.YiQuXiao)
            )
            .stream()
            .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.TransRecode.class))
            .toList();
        Map<Long, List<SearchOrderResult.TransRecode>> orderId_transRecode_map = GroupUtil.k_a(transRecodes, SearchOrderResult.TransRecode::getOrderId);

        List<SearchOrderResult.CargoPlace> cargoPlaceList = orderCargoPlaceService.list(Wrappers.lambdaQuery(OrderCargoPlaceEntity.class).in(OrderCargoPlaceEntity::getOrderId, orderIdList))
            .stream()
            .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.CargoPlace.class))
            .toList();
        Map<Long, SearchOrderResult.CargoPlace> orderId_cargoPlace_map = GroupUtil.k_o(cargoPlaceList, SearchOrderResult.CargoPlace::getOrderId);

        Map<Long, SearchOrderResult.ProjectInfo> projectId_project_map;
        if (!projectIdList.isEmpty()) {
            List<SearchOrderResult.ProjectInfo> projectInfoList = projectService.list(Wrappers.lambdaQuery(ProjectEntity.class).in(BaseEntity::getId, projectIdList))
                .stream()
                .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.ProjectInfo.class))
                .toList();
            projectId_project_map = GroupUtil.k_o(projectInfoList, SearchOrderResult.ProjectInfo::getId);
        } else {
            projectId_project_map = MapUtil.empty();
        }

        List<SearchOrderResult.PaymentRecord> paymentRecordResultList = orderPaymentRecordService.listPaymentRecord(Wrappers.query().in("a.order_id", orderIdList))
            .stream()
            .map(it -> BeanUtil.copyProperties(it, SearchOrderResult.PaymentRecord.class))
            .toList();
        Map<Long, List<SearchOrderResult.PaymentRecord>> transId_paymentRecord_map = GroupUtil.k_a(paymentRecordResultList, SearchOrderResult.PaymentRecord::getTransId);


        for (SearchOrderResult result : results) {
            Long orderId = result.getId();
            Long projectId = result.getProjectId();
            List<SearchOrderResult.TransRecode> transRecodeList = orderId_transRecode_map.get(orderId);
            for (SearchOrderResult.TransRecode transRecode : transRecodeList) {
                Long transRecodeId = transRecode.getId();
                transRecode.setPaymentRecord(transId_paymentRecord_map.get(transRecodeId));
            }
            result.setTransRecodes(transRecodeList);
            result.setCargoPlace(orderId_cargoPlace_map.get(orderId));
            result.setProjectInfo(projectId_project_map.get(projectId));
        }

        return PageResult.of(resultPage);
    }

    @Transactional(rollbackFor = Exception.class)
    public void assignmentOrg(AssignmentOrgParam orgParam) {
        Assert.notNull(orgParam, () -> Exceptions.clierr("请填写参数"));
        Assert.notNull(orgParam.getOrderId(), () -> Exceptions.clierr("订单ID不可为空"));
        Assert.notNull(orgParam.getTransOrgId(), () -> Exceptions.clierr("清运公司ID不可为空"));

        OrderEntity result = this.getById(orgParam.getOrderId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));
        Assert.isNull(result.getTransOrgId(), () -> Exceptions.clierr("当前订单已分配清运公司，无需重复分配"));
        Assert.isTrue(OrderStatus.YiYuYue.equals(result.getOrderStatus()), () -> Exceptions.clierr("当前订单状态，无法分配清运公司"));

        CustomerEntity customer = customerMapper.selectOne(Wrappers.<CustomerEntity>lambdaQuery()
            .eq(CustomerEntity::getOrgId, orgParam.getTransOrgId())
            .eq(CustomerEntity::getManager, Boolean.TRUE));
        Assert.notNull(customer, () -> Exceptions.clierr("该企业管理员不存在"));

        // 更新订单表 cst_order 的运输公司与状态信息
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setTransOrgId(orgParam.getTransOrgId())
            .setTransCustomerId(customer.getId())
            .setAssignmentTransTime(LocalDateTime.now())
            .setOrderStatus(OrderStatus.JinXingZhong)
            .setId(result.getId());
        this.updateById(orderEntity);

        // 更新运输信息表 cst_trans_order 的运输状态信息
        orderTransMapper.update(Wrappers.<OrderTransEntity>lambdaUpdate()
            .set(OrderTransEntity::getTransStatus, TransStatus.DaiPaiDan)
            .eq(OrderTransEntity::getOrderId, result.getId()));

        // 创建订单付费项
        OrderEntity newOrderInfo = this.getById(orgParam.getOrderId());
        this.createOrderExpenseItems(newOrderInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    public void assignmentDriver(AssignmentDriverParam driverParam) {
        Assert.notNull(driverParam, () -> Exceptions.clierr("请填写参数"));
        Assert.notNull(driverParam.getDriverId(), () -> Exceptions.clierr("司机Id不可为空"));

        // orderId 与 orderTransId 只能有一个有值
        Long orderId = driverParam.getOrderId();
        List<Long> orderTransIdList = driverParam.getOrderTransId();
        boolean hasOrderId = orderId != null;
        boolean hasOrderTransIds = orderTransIdList != null && !orderTransIdList.isEmpty();
        Assert.isTrue(hasOrderId ^ hasOrderTransIds, () -> Exceptions.clierr("orderId与orderTransId只能有一个有值"));

        // 根据参数获取运输信息列表
        List<OrderTransEntity> transEntityList;
        if (hasOrderId) {
            // 如果orderId不为空，查询该订单下所有待派单的运输信息
            transEntityList = orderTransMapper.selectList(Wrappers.<OrderTransEntity>lambdaQuery()
                .eq(OrderTransEntity::getOrderId, orderId)
                .eq(OrderTransEntity::getTransStatus, TransStatus.DaiPaiDan));
            Assert.notEmpty(transEntityList, () -> Exceptions.clierr("该订单下没有待派单的运输信息"));
        } else {
            // 如果orderTransId不为空，查询指定的运输信息
            transEntityList = orderTransMapper.selectList(Wrappers.<OrderTransEntity>lambdaQuery()
                .in(OrderTransEntity::getId, orderTransIdList)
                .eq(OrderTransEntity::getTransStatus, TransStatus.DaiPaiDan));
            Assert.notEmpty(transEntityList, () -> Exceptions.clierr("没有找到待派单的运输信息"));
        }

        // 校验司机信息
        DriverEntity driver = driverMapper.selectById(driverParam.getDriverId());
        Assert.notNull(driver, () -> Exceptions.clierr("司机不存在"));

        // 遍历每个运输信息进行校验和更新
        for (OrderTransEntity transEntity : transEntityList) {
            // 获取当前运输信息的所有付费记录
            List<OrderPaymentRecordEntity> recordList = orderPaymentRecordService.list(Wrappers.<OrderPaymentRecordEntity>lambdaQuery()
                .eq(OrderPaymentRecordEntity::getTransId, transEntity.getId()));
            for (OrderPaymentRecordEntity record : recordList) {
                if (SettlementWay.YuE.equals(record.getSettlementWay())) {
                    MoneyAccountResult accountResult = moneyAccountMapper.detail(record.getPayerMoneyAccountId());
                    // 如果该笔订单支付方式为余额支付，需在分配之前查询当前付款账户余额是否充足，
                    // 不足则提示余额不足，不允许在派司机
                    if (accountResult.getRecharge().compareTo(BigDecimal.ZERO) < 0) {
                        // 已经是负数，禁止再次支付
                        throw Exceptions.clierr(accountResult.getAccountName() + "账户余额不足");
                    }
                }
            }

            // 更新运输信息表 cst_trans_order 的运输状态等信息
            OrderTransEntity updateTrans = new OrderTransEntity();
            updateTrans.setId(transEntity.getId());
            updateTrans.setTransStatus(TransStatus.DaiJieDan);
            updateTrans.setAssignmentDriverTime(LocalDateTime.now());
            updateTrans.setDriverId(driverParam.getDriverId());
            updateTrans.setDriverCustomerId(driver.getCustomerId());
            updateTrans.setDriverUserId(driver.getUserId());
            orderTransMapper.updateById(updateTrans);
        }

        // 更新司机状态（批量更新只需要一次）
        DriverEntity driverEntity = new DriverEntity();
        driverEntity.setId(driverParam.getDriverId());
        driverEntity.setBusy(Boolean.TRUE);
        driverMapper.updateById(driverEntity);

    }

    @Transactional(rollbackFor = Exception.class)
    public void driverAcceptOrder(DriverAcceptOrderParam acceptOrderParam) {
        Assert.notNull(acceptOrderParam, () -> Exceptions.clierr("请填写参数"));
        Assert.notNull(acceptOrderParam.getOrderTransId(), () -> Exceptions.clierr("订单运输ID不可为空"));
        Assert.notNull(acceptOrderParam.getTruckId(), () -> Exceptions.clierr("车辆Id不可为空"));

        OrderTransResult result = orderTransMapper.getById(acceptOrderParam.getOrderTransId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));
        Assert.isTrue(TransStatus.DaiJieDan.equals(result.getTransStatus()), () -> Exceptions.clierr("当前订单状态，无法确认接单"));

        long userId = SecurityUtil.currentUserId();
        DriverEntity driver = driverMapper.selectOne(Wrappers.<DriverEntity>lambdaQuery()
            .eq(DriverEntity::getUserId, userId));
        Assert.notNull(driver, () -> Exceptions.clierr("当前登录人非司机用户"));
        Assert.isTrue(Objects.equals(driver.getId(), result.getDriverId()), () -> Exceptions.clierr("您没有权限接受此单"));

        TruckEntity truckEntity = truckMapper.selectById(acceptOrderParam.getTruckId());
        Assert.notNull(truckEntity, () -> Exceptions.clierr("车辆不存在"));

        // 更新运输信息
        OrderTransEntity transEntity = new OrderTransEntity();
        transEntity.setId(acceptOrderParam.getOrderTransId());
        transEntity.setTransStatus(TransStatus.YiJieDan);
        transEntity.setDriverConfirmTime(LocalDateTime.now());
        transEntity.setTruckCustomerId(truckEntity.getCustomerId());
        transEntity.setTruckOrgId(truckEntity.getOrgId());
        transEntity.setTruckId(acceptOrderParam.getTruckId());
        transEntity.setTruckLicensePlate(truckEntity.getLicensePlate());
        transEntity.setHistoryTareWeight(truckEntity.getTareWeight());
        orderTransMapper.updateById(transEntity);

        // 更新车辆状态
        TruckEntity truck = new TruckEntity();
        truck.setId(acceptOrderParam.getTruckId());
        truck.setBusy(Boolean.TRUE);
        truckMapper.updateById(truck);

    }

    @Transactional(rollbackFor = Exception.class)
    public void startTrans(StartTransParam transParam) {
        Assert.notNull(transParam, () -> Exceptions.clierr("请填写参数"));
        Assert.notNull(transParam.getOrderTransId(), () -> Exceptions.clierr("订单运输ID不可为空"));

        OrderTransResult result = orderTransMapper.getById(transParam.getOrderTransId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));
        Assert.isTrue(TransStatus.YiJieDan.equals(result.getTransStatus()), () -> Exceptions.clierr("当前订单状态，无法开始运输"));

        // 更新运输信息
        OrderTransEntity transEntity = new OrderTransEntity();
        transEntity.setId(transParam.getOrderTransId());
        transEntity.setTransStatus(TransStatus.YunShuZhong);
        transEntity.setTransTime(LocalDateTime.now());
        orderTransMapper.updateById(transEntity);

    }

    /**
     * 车辆进场
     */
    @Transactional(rollbackFor = Exception.class)
    public void truckComing(TruckComingParam comingParam) {
        Integer weight = comingParam.getWeight();
        Assert.notNull(comingParam.getOrderTransId(), () -> Exceptions.clierr("订单运输ID不可为空"));
        Assert.notNull(weight, () -> Exceptions.clierr("磅重不可为空"));

        OrderTransResult result = orderTransMapper.getById(comingParam.getOrderTransId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));

        OrderStatus orderStatus = result.getOrderStatus();
        TransStatus transStatus = result.getTransStatus();
        Assert.isTrue(Objects.equals(orderStatus, OrderStatus.JinXingZhong) &&
            Objects.equals(transStatus, TransStatus.YunShuZhong), () -> Exceptions.clierr("当前订单状态，无法进场"));
        Assert.isTrue(weight != null && weight > 0, () -> Exceptions.clierr("磅重错误"));

        // 更新运输信息
        OrderTransEntity transEntity = new OrderTransEntity();
        transEntity.setId(comingParam.getOrderTransId());
        transEntity.setTransStatus(TransStatus.YiJinChang);
        // 根据订单类型区分毛重皮重
        if (OrderCategory.HuiShouYuYue.equals(result.getOrderCategory())) {
            transEntity.setRoughWeight(weight);
        } else if (OrderCategory.XiaoShouYuYue.equals(result.getOrderCategory())) {
            transEntity.setTareWeight(weight);
            // 更新车辆皮重
            this.updateTruckHisTareWeight(result.getTruckId(), weight);
        }
        transEntity.setInFrontPhoto(comingParam.getFrontPhoto());
        transEntity.setInBodyPhoto(comingParam.getBodyPhoto());
        transEntity.setInTime(LocalDateTime.now());
        orderTransMapper.updateById(transEntity);

    }

    @Transactional(rollbackFor = Exception.class)
    public void check(CheckGoodsParam checkGoodsParam) {
        Assert.notNull(checkGoodsParam.getOrderTransId(), () -> Exceptions.clierr("订单运输ID不可为空"));

        OrderTransResult result = orderTransMapper.getById(checkGoodsParam.getOrderTransId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));

        Assert.isTrue(OrderStatus.JinXingZhong.equals(result.getOrderStatus())
                && TransStatus.YiJinChang.equals(result.getTransStatus()) && CheckStatus.WeiKanLiao.equals(result.getCheckStatus()),
            () -> Exceptions.clierr("当前订单状态，无法看料"));

        // 更新运输信息
        OrderTransEntity transEntity = new OrderTransEntity();
        transEntity.setId(result.getId());
        transEntity.setCheckerId(SecurityUtil.currentUserId());
        transEntity.setCheckStatus(CheckStatus.YiKanLiao);
        transEntity.setCheckTime(LocalDateTime.now());
        transEntity.setCheckPhoto(checkGoodsParam.getCheckPhoto());
        transEntity.setCheckerMemo(checkGoodsParam.getCheckerMemo());
        orderTransMapper.updateById(transEntity);
    }

    /**
     * 车辆出场
     */
    @Transactional(rollbackFor = Exception.class)
    public void truckLeaving(TruckLeavingParam leavingParam) {
        Integer weight = leavingParam.getWeight();
        Assert.notNull(leavingParam.getOrderTransId(), () -> Exceptions.clierr("订单运输ID不可为空"));
        Assert.isTrue(weight != null && weight > 0, () -> Exceptions.clierr("磅重错误"));

        OrderTransResult result = orderTransMapper.getById(leavingParam.getOrderTransId());
        Assert.notNull(result, () -> Exceptions.clierr("订单不存在"));

        Assert.isTrue(OrderStatus.JinXingZhong.equals(result.getOrderStatus())
                && TransStatus.YiJinChang.equals(result.getTransStatus()) && CheckStatus.YiKanLiao.equals(result.getCheckStatus()),
            () -> Exceptions.clierr("当前订单状态，无法出厂"));

        // 更新运输信息
        OrderTransEntity transEntity = new OrderTransEntity();
        transEntity.setId(result.getId());
        transEntity.setTransStatus(TransStatus.YiChuChang);
        // 根据订单类型区分毛重皮重
        if (OrderCategory.HuiShouYuYue.equals(result.getOrderCategory())) {
            transEntity.setTareWeight(weight);
            transEntity.setSettleWeight(result.getRoughWeight() - transEntity.getTareWeight());
            // 更新车辆皮重
            this.updateTruckHisTareWeight(result.getTruckId(), weight);
        } else if (OrderCategory.XiaoShouYuYue.equals(result.getOrderCategory())) {
            transEntity.setRoughWeight(weight);
            transEntity.setSettleWeight(transEntity.getRoughWeight() - result.getTareWeight());
        }
        transEntity.setOutFrontPhoto(leavingParam.getFrontPhoto());
        transEntity.setOutBodyPhoto(leavingParam.getBodyPhoto());
        transEntity.setOutTime(LocalDateTime.now());
        orderTransMapper.updateById(transEntity);

        // 更新付费记录的量,计算结算金额并支付
        boolean allCompleted = paymentRecordHelper.updatePaymentRecordQuantity(
            transEntity.getId(), transEntity.getSettleWeight(), transEntity.getTransDistance(),
            result.getSn(), result.getTrainNum());

        // 如果该运输记录下所有付费记录都已完成，更新运输状态为已完成
        if (allCompleted) {
            OrderTransEntity updateTrans = new OrderTransEntity();
            updateTrans.setId(transEntity.getId());
            updateTrans.setTransStatus(TransStatus.YiWanCheng);
            updateTrans.setFinishTime(LocalDateTime.now());
            orderTransMapper.updateById(updateTrans);
            // 添加采购单或销售单
            if (OrderCategory.HuiShouYuYue.equals(result.getOrderCategory())) {
                PURCHASE_ORDER.emit(updateTrans.getId());
            } else if (OrderCategory.XiaoShouYuYue.equals(result.getOrderCategory())) {
                SALES_ORDER.emit(updateTrans.getId());
            }

            // 检查订单下所有运输记录是否都完成
            this.checkAndUpdateOrderStatus(result.getId());
        }
    }

    public void updateTruckHisTareWeight(Long truckId, Integer weight) {
        TruckEntity truckEntity = truckMapper.selectById(truckId);
        Assert.notNull(truckEntity, () -> Exceptions.clierr("车辆不存在"));

        TruckEntity truck = new TruckEntity();
        truck.setId(truckEntity.getId());
        truck.setTareWeight(weight);
        truckMapper.updateById(truck);
    }

    /**
     * 检查订单下所有运输记录是否都完成，如果都完成则更新订单状态
     *
     * @param orderId 订单ID
     */
    private void checkAndUpdateOrderStatus(Long orderId) {
        List<OrderTransEntity> transList = orderTransMapper.selectList(
            Wrappers.<OrderTransEntity>lambdaQuery()
                .eq(OrderTransEntity::getOrderId, orderId)
                .ne(OrderTransEntity::getTransStatus, TransStatus.YiQuXiao));

        boolean allCompleted = transList.stream()
            .allMatch(t -> TransStatus.YiWanCheng.equals(t.getTransStatus()));

        if (allCompleted) {
            OrderEntity updateOrder = new OrderEntity();
            updateOrder.setId(orderId);
            updateOrder.setOrderStatus(OrderStatus.YiWanCheng);
            updateOrder.setFinishTime(LocalDateTime.now());
            this.updateById(updateOrder);
            log.info("订单 {} 所有运输记录已完成，更新订单状态为已完成", orderId);
        }
    }

    /**
     * 生成订单号
     *
     * @return sn 订单号
     */
    public String generateSn() {
        String sn = SnUtil.next("Booking-Order-SN");
        if (this.exists(Wrappers.<OrderEntity>lambdaQuery().eq(OrderEntity::getSn, sn).eq(OrderEntity::getDeleted, Boolean.FALSE))) {
            this.generateSn();
        }
        return sn;
    }

    /**
     * 创建订单付费项
     *
     * @param orderEntity 订单信息
     */
    public void createOrderExpenseItems(OrderEntity orderEntity) {
        // 组织ids集合
        List<Long> orgIds = Lists.newArrayList();
        Long transOrgId = orderEntity.getTransOrgId();
        orgIds.add(transOrgId);
        CustomerEntity customerEntity = customerMapper.selectOne(Wrappers.<CustomerEntity>lambdaQuery()
            .eq(CustomerEntity::getIdentityCategory, IdentityCategory.PingTai)
            .eq(CustomerEntity::getManager, Boolean.TRUE)
            .eq(CustomerEntity::getDeleted, Boolean.FALSE));
        orgIds.add(customerEntity.getOrgId());
        StationEntity station = stationMapper.selectById(orderEntity.getStationId());
        orgIds.add(station.getOrgId());

        // 读取启用的付费项配置，并按过滤
        List<ExpenseItemEntity> itemEntityList = expenseItemService.list(Wrappers.<ExpenseItemEntity>lambdaQuery()
            .in(ExpenseItemEntity::getOrgId, orgIds)
            .eq(ExpenseItemEntity::getCanuse, Boolean.TRUE)
            .eq(ExpenseItemEntity::getDeleted, Boolean.FALSE));
        Long goodsId = orderEntity.getGoodsId();
        // 1. 查找产品付费项（goodsId + station.getOrgId() + ChanPin，只会匹配到一个）
        ExpenseItemEntity firstGoodsItem = itemEntityList.stream()
            .filter(item -> goodsId.equals(item.getGoodsId())
                && station.getOrgId().equals(item.getOrgId())
                && ExpenseItemCategory.ChanPin.equals(item.getExpenseItemCategory()))
            .findFirst()
            .orElse(null);

        // 2. 查找运费付费项（YunFei + transOrgId，可能有多条）
        List<ExpenseItemEntity> freightItems = itemEntityList.stream()
            .filter(item -> transOrgId.equals(item.getOrgId())
                && ExpenseItemCategory.YunFei.equals(item.getExpenseItemCategory()))
            .toList();

        // 3. 过滤其他付费项（排除产品、运费）
        List<OrderExpenseItemsEntity> extraItems = itemEntityList.stream()
            .filter(cfg -> !ExpenseItemCategory.ChanPin.equals(cfg.getExpenseItemCategory())
                && !ExpenseItemCategory.YunFei.equals(cfg.getExpenseItemCategory()))
            // 复制配置为订单付费项
            .map(cfg -> {
                OrderExpenseItemsEntity entity = BeanUtil.copyProperties(cfg, OrderExpenseItemsEntity.class);
                entity.setOrderId(orderEntity.getId());
                entity.setOriginExpenseItemsId(cfg.getId());
                return entity;
            })
            .toList();

        // 第四步：合并集合并计算金额，然后批量落库
        List<OrderExpenseItemsEntity> allItems = Lists.newArrayList();
        if (firstGoodsItem != null) {
            allItems.add(BeanUtil.copyProperties(firstGoodsItem, OrderExpenseItemsEntity.class)
                .setOrderId(orderEntity.getId())
                .setOriginExpenseItemsId(firstGoodsItem.getId()));
        }
        // 添加所有运费付费项
        freightItems.forEach(item -> allItems.add(
            BeanUtil.copyProperties(item, OrderExpenseItemsEntity.class)
                .setOrderId(orderEntity.getId())
                .setOriginExpenseItemsId(item.getId())));
        allItems.addAll(extraItems);

        if (allItems.isEmpty()) {
            return;
        }

        // 批量保存付费项
        orderExpenseItemsService.saveBatch(allItems);

        // 获取订单的所有运输记录
        List<OrderTransEntity> transList = orderTransMapper.selectList(Wrappers.<OrderTransEntity>lambdaQuery()
            .eq(OrderTransEntity::getOrderId, orderEntity.getId()));

        List<OrderPaymentRecordEntity> recordList = Lists.newArrayList();
        for (OrderTransEntity transEntity : transList) {
            List<OrderPaymentRecordEntity> paymentRecords = allItems.stream()
                .map(item -> {
                    OrderPaymentRecordEntity record = new OrderPaymentRecordEntity()
                        .setOrderId(orderEntity.getId())
                        .setExpenseItemId(item.getId())
                        .setTransId(transEntity.getId())
                        .setPaymentStatus(PaymentStatus.WeiZhiFu);

                    // 根据归属字段获取结算方式和账户信息
                    Long customerId = item.getCustomerId();
                    CustomerEntity customer = customerMapper.selectOne(Wrappers.<CustomerEntity>lambdaQuery()
                        .eq(CustomerEntity::getId, customerId));
                    if (customer != null && customer.getSettlementWay() != null) {
                        record.setSettlementWay(customer.getSettlementWay());
                        record.setPayerCustomerId(customer.getId());
                        record.setPayerUserId(customer.getUserId());
                    } else {
                        throw Exceptions.clierr("付款人客户信息不存在或未配置付费方式");
                    }

                    // 查询资金账户
                    MoneyAccountEntity moneyAccount = moneyAccountMapper.selectOne(Wrappers.<MoneyAccountEntity>lambdaQuery()
                        .eq(MoneyAccountEntity::getCustomerId, customerId)
                        .eq(MoneyAccountEntity::getDeleted, Boolean.FALSE));
                    if (moneyAccount != null) {
                        record.setPayerMoneyAccountId(moneyAccount.getId());
                    } else {
                        throw Exceptions.clierr("付款人资金账户不存在");
                    }
                    return record;
                })
                .toList();
            recordList.addAll(paymentRecords);
        }

        // 批量新增付费记录
        orderPaymentRecordService.saveBatch(recordList);
    }
}
