package com.sckw.transport.handler;


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.GatekeeperStatusEnum;
import com.sckw.core.model.enums.GatekeeperTypeEnum;
import com.sckw.core.utils.StringUtils;
import com.sckw.transport.model.*;
import com.sckw.transport.model.enuma.WeighbridgeTypeEnum;
import com.sckw.transport.model.param.WaybillOrderUnloadingWeighParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * Author: donglang
 * Time: 2026-01-20
 * Des: 卸货过磅
 * Version: 1.0
 */

@Slf4j
@Service
public class UnloadingWeighHandler extends AbstractWaybillOrderHandler<WaybillOrderUnloadingWeighParam> {

    @Override
    protected KwtWaybillOrder getWaybillOrder(WaybillOrderUnloadingWeighParam param) {
        return getWaybillOrder(param.getWaybillOrderId());
    }

    @Override
    protected void checkState(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder) {
        if (StringUtils.isBlank(param.getTruckNo())) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "车牌号不能为空！");
        }
    }

    @Override
    protected void doBusiness(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder) {
        KwtWaybillOrderTicket takeTicket = waybillOrderTicketRepository.queryByWOrderIdByIdAndType(param.getWaybillOrderId(), 2);
        if (takeTicket == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_TICKET_NOT_FOUND, "当前物流运单卸货单信息不存在，无法记录毛重！");
        }
        //校验是否第一次卸货过磅
        if (checkIsFirst(waybillOrder)) {
            //第一次卸货过磅
            firstWeighbridge(param, waybillOrder, takeTicket);
        } else {
            //第二次过磅
            laterWeighbridge(param,waybillOrder, takeTicket);
        }

    }

    /**
     * 校验是否第一次过磅
     * @param waybillOrder
     * @return
     */
    private Boolean checkIsFirst(KwtWaybillOrder waybillOrder) {
        List<KwtWaybillOrderWeighbridge> weighbridges = waybillOrderWeighbridgeRepository
                .queryWaybillOrderWeighbridgeByWOrderId(waybillOrder.getId(), WeighbridgeTypeEnum.UNLOADING.getCode());
        return CollectionUtils.isEmpty(weighbridges);
    }

    /**
     * 第一次过磅
     * @param param
     */
    private void firstWeighbridge(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder, KwtWaybillOrderTicket takeTicket) {
        if (param.getWeighAmount() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "毛重不能为空！");
        }
        // 校验运单
        if (!Objects.equals(CarWaybillV1Enum.WAIT_LOADING.getCode(), waybillOrder.getStatus())) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_STATUS_ERROR, "当前物流运单状态不是“已离场”状态，无法卸货称重过磅！");
        }

        // 1. 填充毛重
        updateWaybillTicketGrossAmount(param, takeTicket);

        // 2.修改门卫卸货状态：卸货已进场
        updateGatekeeperOrderStatus(waybillOrder);

        // 3.创建卸货过磅记录
        createWeighbridges(waybillOrder);
    }

    /**
     * 填充毛重
     * @param param
     */
    private void updateWaybillTicketGrossAmount(WaybillOrderUnloadingWeighParam param, KwtWaybillOrderTicket takeTicket) {
        //填充卸货单毛重
        takeTicket.setGrossAmount(param.getWeighAmount());
        waybillOrderTicketRepository.updateById(takeTicket);
    }

    /**
     * 修改门卫卸货状态：卸货已进场
     * @param waybillOrder
     * @return
     */
    public void updateGatekeeperOrderStatus(KwtWaybillOrder waybillOrder) {
        KwtGatekeeperWaybillOrder gatekeeper = gatekeeperWaybillOrderRepository
                .queryGatekeeperWaybillOrderByWOrderId(waybillOrder.getId(), GatekeeperTypeEnum.UNLOADING.getCode());
        if (gatekeeper == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.GATEKEEPER_ORDER_NOT_FOUND, "当前门卫订单数据不存在！");
        }
        if (!(GatekeeperStatusEnum.PENDING_ENTRY.getCode().equals(gatekeeper.getStatus()))) {
            throw new BusinessPlatfromException(ErrorCodeEnum.GATEKEEPER_ORDER_STATUS_ERROR, "当前门卫订单状态异常，不能推进为待放行状态！");
        }
        //修改门卫：卸货已进场
        gatekeeper.setStatus(GatekeeperStatusEnum.IN_YARD.getCode());
        gatekeeper.setIntoTime(new Date());
        gatekeeperWaybillOrderRepository.updateById(gatekeeper);
    }

    /**
     * 创建卸货过磅记录
     * @param waybillOrder
     */
    private void createWeighbridges(KwtWaybillOrder waybillOrder) {
        CompletableFuture.runAsync(() ->{
            try {
                log.debug("开始异步保存地磅记录，运单ID:{}", waybillOrder.getId());
                KwtWaybillOrderWeighbridge weighbridge = new KwtWaybillOrderWeighbridge();
                weighbridge.setWOrderId(waybillOrder.getId());
                weighbridge.setLOrderId(waybillOrder.getLOrderId());
                weighbridge.setTruckId(waybillOrder.getTruckId());
                weighbridge.setTruckNo(waybillOrder.getTruckNo());
                weighbridge.setType(WeighbridgeTypeEnum.UNLOADING.getCode());
                weighbridge.setWeighbridgeId(10001l);
                weighbridge.setWeight(BigDecimal.ZERO);
                weighbridge.setWeighUrl(null);
                weighbridge.setCreateTime(new Date());
                weighbridge.setCreateUser(waybillOrder.getDriverId());
                weighbridge.setUpdateUser(waybillOrder.getDriverId());

                waybillOrderWeighbridgeRepository.save(weighbridge);
                log.debug("异步保存过磅数据保存成功");
            } catch (Exception e) {
                throw new BusinessPlatfromException(ErrorCodeEnum.DATA_SAVE_FAIL, "异步保存过磅数据失败！");
            }
        });
    }


    /**
     * 第二次过磅
     * @param param
     */
    private void laterWeighbridge(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder, KwtWaybillOrderTicket takeTicket) {
        if (StringUtils.isBlank(param.getWeighAmount())) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "皮重不能为空！");
        }

        // 1.填充运单卸货单皮重、净重
        updateTareAmount(param, waybillOrder, takeTicket);

        // 2.创建卸货过磅记录
        createWeighbridges(waybillOrder);
    }

    /**
     * 填充皮重、卸货净重
     * @param param
     * @param takeTicket
     */
    private void updateTareAmount(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder, KwtWaybillOrderTicket takeTicket) {
        //皮重
        BigDecimal tareAmount = param.getWeighAmount();
        //毛重
        BigDecimal grossAmount = takeTicket.getGrossAmount();
        //卸货净重
        BigDecimal unloadAmount = grossAmount.subtract(Optional.ofNullable(tareAmount).orElse(BigDecimal.ZERO));

        takeTicket.setTareAmount(tareAmount);
        takeTicket.setAmount(unloadAmount);
        waybillOrderTicketRepository.updateById(takeTicket);

        //2.更新子运单卸货量
        updateWaybillOrderSubtask(waybillOrder, unloadAmount);
    }

    /**
     * 更新子运单卸货量
     * @param waybill
     */
    private void updateWaybillOrderSubtask(KwtWaybillOrder waybill, BigDecimal unloadAmount) {
        KwtWaybillOrderSubtask subtask = getWaybillSubtask(waybill.getId());
        subtask.setUnloadAmount(unloadAmount);
        subtask.setUnloadTime(new Date());
        waybillOrderSubtaskRepository.updateById(subtask);
    }


    @Override
    protected void calculateAutoDispatchScore(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder) {

    }

    @Override
    protected String getProcessName() {
        return "卸货离场过磅";
    }

    @Override
    protected void getStatus(KwtWaybillOrder waybillOrder) {
        // 校验是否第一次卸货过磅
        CarWaybillV1Enum status = Objects.equals(waybillOrder.getStatus(), CarWaybillV1Enum.WAIT_LOADING.getCode())
                ? CarWaybillV1Enum.UNLOADING_POINT : CarWaybillV1Enum.UNLOADING_WAIT_LEAVE;

        // 1. 修改运单状态
        waybillOrder.setStatus(status.getCode());
        waybillOrderRepository.updateById(waybillOrder);

        // 2. 修改子运单状态
        KwtWaybillOrderSubtask waybillSubtask = getWaybillSubtask(waybillOrder.getId());
        waybillSubtask.setStatus(status.getCode());
        waybillOrderSubtaskRepository.updateById(waybillSubtask);
    }


    @Override
    protected String getRemark(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder) {
        return "";
    }

    /**
     * 重写 createNodeTrace，生成两条轨迹记录
     */
    @Override
    protected void createNodeTrace(WaybillOrderUnloadingWeighParam param, KwtWaybillOrder waybillOrder) {
        List<KwtWaybillOrderWeighbridge> weighbridges = waybillOrderWeighbridgeRepository
                .queryWaybillOrderWeighbridgeByWOrderId(waybillOrder.getId(), WeighbridgeTypeEnum.UNLOADING.getCode());
        if (CollectionUtils.isEmpty(weighbridges)) {
            // 第一条：称重完成
            KwtWaybillOrderNode node1 = getWaybillOrderNode(param, waybillOrder);
            node1.setRemark("车辆[" + waybillOrder.getTruckNo() + "]已到达卸货点");
            waybillOrderNodeRepository.save(node1);
            log.info("记录【已到底卸货点】节点轨迹成功，节点ID：{}", node1.getId());
            // 间隔5秒钟，防止时间相同
            Date fiveSecondsLater = new Date(System.currentTimeMillis() + 5000);

            // 第二条：称重信息
            KwtWaybillOrderNode node2 = getWaybillOrderNode(param, waybillOrder);
            String grossAmount = Objects.isNull(param.getWeighAmount()) ? "0.00" : param.getWeighAmount().setScale(2, RoundingMode.HALF_UP).toPlainString();
            node2.setRemark("[" + param.getWeighbridgeName() + "]称重[" + grossAmount + "吨]");
            node2.setCreateTime(fiveSecondsLater);
            waybillOrderNodeRepository.save(node2);
            log.info("记录【卸货首次过磅称重】节点轨迹成功，节点ID：{}", node2.getId());
        } else {
            // 第一条：称重完成
            KwtWaybillOrderNode node1 = getWaybillOrderNode(param, waybillOrder);
            //过磅次数
            String tareAmount = Objects.isNull(param.getWeighAmount()) ? "0.00" : param.getWeighAmount().setScale(2, RoundingMode.HALF_UP).toPlainString();
            node1.setRemark("[" + param.getWeighbridgeName() + "]称重[" + tareAmount + "吨]");
            waybillOrderNodeRepository.save(node1);
            log.info("记录【卸货过磅称重】节点轨迹成功，节点ID：{}", node1.getId());
        }
    }
}
