package com.sckw.order.dubbo;

import cn.hutool.core.collection.CollUtil;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.response.HttpResult;
import com.sckw.order.api.dubbo.RemoteTradeOrderAmountService;
import com.sckw.order.api.model.AddressActualAmountParam;
import com.sckw.order.api.model.UpdateAddressActualAmountParam;
import com.sckw.order.api.model.UpdateAddressEntrustAmountParam;
import com.sckw.order.enums.DeliveryTypeEnum;
import com.sckw.order.enums.OrderAddressTypeEnum;
import com.sckw.order.enums.OrderStatusEnum;
import com.sckw.order.model.KwoTradeOrder;
import com.sckw.order.model.KwoTradeOrderAmount;
import com.sckw.order.serivce.KwoTradeOrderAddressService;
import com.sckw.order.serivce.KwoTradeOrderAmountService;
import com.sckw.order.serivce.KwoTradeOrderService;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: yzc
 * @date: 2024-03-12  16:23
 * @desc: 贸易订单地址分配量信息相关dubbo实现
 */
@DubboService(group = "design", version = "1.0.0")
@Slf4j
@RequiredArgsConstructor
public class RemoteTradeOrderAmountServiceImpl implements RemoteTradeOrderAmountService {

    private final KwoTradeOrderService tradeOrderService;
    private final KwoTradeOrderAmountService tradeOrderAmountService;
    private final KwoTradeOrderAddressService tradeOrderAddressService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult updateAddressEntrustAmount(UpdateAddressEntrustAmountParam param) {
        Long tOrderId = param.getTOrderId();
        if (Objects.isNull(tOrderId)) {
            return HttpResult.error("贸易订单id不能为空!");
        }
        Long tAddressId = param.getTAddressId();
        if (Objects.isNull(tAddressId)) {
            return HttpResult.error("贸易订单地址id不能为空!");
        }
        BigDecimal entrustAmount = param.getEntrustAmount();
        Long updateBy = param.getUpdateBy();
        String updateByName = param.getUpdateByName();
        if (Objects.isNull(updateBy) || StringUtils.isBlank(updateByName)) {
            return HttpResult.error("操作人信息不能为空!");
        }
        if (Objects.isNull(entrustAmount)) {
            return HttpResult.error("任务量不能为空!");
        }
        String lockKey = String.format(RedisConstant.TORDER_ADDRESS_UPDATE_ENTRUST_AMOUNT, tAddressId);
        if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
            return HttpResult.error("业务繁忙，请稍后再试!");
        }
        try {
            KwoTradeOrder order = tradeOrderService.getById(tOrderId);
            if (Objects.isNull(order)) {
                return HttpResult.error("订单不存在!");
            }
            if (!Objects.equals(order.getStatus(), OrderStatusEnum.EXECUTING.getCode())) {
                return HttpResult.error("执行中的订单才可物流托运！");
            }
            KwoTradeOrderAmount orderAmount = tradeOrderAmountService.getByOrderIdAndTaddressId(tOrderId, tAddressId);
            if (Objects.isNull(orderAmount)) {
                return HttpResult.error("地址下分配量信息不存在!");
            }
            BigDecimal totalEntrustAmount = Objects.isNull(order.getEntrustAmount()) ?
                    entrustAmount : entrustAmount.add(order.getEntrustAmount());
            orderAmount.setEntrustAmount(totalEntrustAmount).setUpdateBy(param.getUpdateBy());
            tradeOrderAmountService.updateById(orderAmount);
            //更新mongodb??
        } finally {
            RedissonUtils.unlock(lockKey);
        }
        return HttpResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult updateAddressActualAmount(UpdateAddressActualAmountParam param) {
        Long tOrderId = param.getTOrderId();
        if (Objects.isNull(tOrderId)) {
            return HttpResult.error("贸易订单id不能为空!");
        }
        List<AddressActualAmountParam> addressActualAmountParams = param.getAddressActualAmountParams();
        if (CollUtil.isEmpty(addressActualAmountParams) || addressActualAmountParams.size() != 2) {
            return HttpResult.error("地址实际成交量参数有误!");
        }
        Map<Long, BigDecimal> map = addressActualAmountParams.stream().collect(Collectors.toMap
                (AddressActualAmountParam::getTAddressId, AddressActualAmountParam::getActualAmount, (k1, k2) -> k1));
        if (map.size() != 2) {
            return HttpResult.error("地址实际成交量参数有误!");
        }
        Long updateBy = param.getUpdateBy();
        String updateByName = param.getUpdateByName();
        if (Objects.isNull(updateBy) || StringUtils.isBlank(updateByName)) {
            return HttpResult.error("操作人信息不能为空!");
        }
        KwoTradeOrder order = tradeOrderService.getById(tOrderId);
        if (Objects.isNull(order)) {
            return HttpResult.error("订单不存在!");
        }
        if (!Objects.equals(order.getStatus(), OrderStatusEnum.EXECUTING.getCode())) {
            return HttpResult.error("执行中的订单才可物流托运！");
        }
        Map<String, Long> addressTypeMap = tradeOrderAddressService.getByIdsAndTOrderId(map.keySet(), tOrderId);
        String addressType = Objects.equals(order.getDeliveryType(), DeliveryTypeEnum.ISSUE.getType()) ? OrderAddressTypeEnum.LOAD.getType() : OrderAddressTypeEnum.UNLOAD.getType();
        Long addressId = addressTypeMap.get(addressType);
        if (Objects.isNull(addressId)) {
            return HttpResult.error("未查询到订单交付类型对应的地址实际成交量参数!");
        }
        BigDecimal actualAmount = map.get(addressId);
        if (Objects.isNull(actualAmount)) {
            return HttpResult.error("地址实际成交量不能为空!");
        }
        KwoTradeOrderAmount orderAmount = tradeOrderAmountService.getByOrderIdAndTaddressId(tOrderId, addressId);
        if (Objects.isNull(orderAmount)) {
            return HttpResult.error("地址下分配量信息不存在!");
        }
        String lockKey = String.format(RedisConstant.TORDER_ADDRESS_UPDATE_ACTUAL_AMOUNT, addressId);
        if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
            return HttpResult.error("业务繁忙，请稍后再试!");
        }
        try {
            orderAmount.setActualAmount(Objects.isNull(orderAmount.getActualAmount()) ? actualAmount : orderAmount.getActualAmount().add(actualAmount))
                    .setUpdateBy(param.getUpdateBy());
            tradeOrderAmountService.updateById(orderAmount);
            //更新mongodb??
        } finally {
            RedissonUtils.unlock(lockKey);
        }
        return HttpResult.ok();
    }
}