package com.sckw.order.dubbo;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.response.HttpResult;
import com.sckw.mongo.model.SckwTradeOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.ContractSignCompletedParam;
import com.sckw.order.api.model.OrderDetailRes;
import com.sckw.order.api.model.UpdateOrderAmountParam;
import com.sckw.order.api.model.UpdateOrderStatusParam;
import com.sckw.order.model.KwoTradeOrder;
import com.sckw.order.model.KwoTradeOrderContract;
import com.sckw.order.model.KwoTradeOrderTrack;
import com.sckw.order.serivce.KwoTradeOrderContractService;
import com.sckw.order.serivce.KwoTradeOrderService;
import com.sckw.order.serivce.KwoTradeOrderTrackService;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.stream.model.SckwBusSum;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @desc: 订单dubbo实现
 * @author: yzc
 * @date: 2023-07-18 18:26
 */
@DubboService(group = "design", version = "2.0.0")
@Slf4j
public class TradeOrderInfoServiceImpl implements TradeOrderInfoService {

    @Autowired
    private KwoTradeOrderService kwoTradeOrderService;
    @Autowired
    private StreamBridge streamBridge;
    @Autowired
    private KwoTradeOrderTrackService kwoTradeOrderTrackService;
    @Autowired
    private KwoTradeOrderContractService kwoTradeOrderContractService;


    @Override
    public OrderDetailRes getOrderDetailById(Long tOrderId) {
        return BeanUtils.copyProperties(kwoTradeOrderService.detail(tOrderId), OrderDetailRes.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult updateOrderStatus(UpdateOrderStatusParam param) {
        if (Objects.isNull(param.getUpdateBy()) || StringUtils.isBlank(param.getUpdateByName())) {
            return HttpResult.error("操作人信息不能为空!");
        }
        KwoTradeOrder order = kwoTradeOrderService.getById(param.getTOrderId());
        if (Objects.isNull(order)) {
            return HttpResult.error("订单不存在!");
        }
        Integer status = param.getStatus();
        Long updateBy = param.getUpdateBy();
        if (Objects.equals(String.valueOf(status), DictEnum.TORDER_STATUS_6.getValue())) {
            if (!Objects.equals(String.valueOf(status), DictEnum.TORDER_STATUS_5.getValue())) {
                return HttpResult.error("已完结的订单才可对账!");
            }
        } else if (Objects.equals(String.valueOf(status), DictEnum.TORDER_STATUS_7.getValue())) {
            if (!Objects.equals(String.valueOf(status), DictEnum.TORDER_STATUS_6.getValue())) {
                return HttpResult.error("已对账的订单才可结算!");
            }
        } else {
            return HttpResult.error("非法订单状态操作！");
        }
        order.setStatus(status).setUpdateBy(updateBy);
        kwoTradeOrderService.updateById(order);
        //订单状态记录
        KwoTradeOrderTrack track = new KwoTradeOrderTrack();
        track.setTOrderId(order.getId()).setTOrderNo(order.getTOrderNo()).setStatus(order.getStatus())
                .setCreateBy(updateBy).setUpdateBy(updateBy);
        kwoTradeOrderTrackService.insert(track);
        //更新mongodb
        SckwTradeOrder updateParam = new SckwTradeOrder();
        updateParam.setTOrderId(order.getId()).setStatus(order.getStatus()).setUpdateBy(param.getUpdateBy())
                .setUpdateByName(param.getUpdateByName()).setUpdateTime(new Date());
        saveMongoDb(3, updateParam);
        return HttpResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult updateOrderAmount(UpdateOrderAmountParam param) {
        if (Objects.isNull(param.getUpdateBy()) || StringUtils.isBlank(param.getUpdateByName())) {
            return HttpResult.error("操作人信息不能为空!");
        }
        Long id = param.getTOrderId();
        Long updateBy = param.getUpdateBy();
        String lockKey = String.format(RedisConstant.GOODS_UPDATE_AMOUNT_KEY, id);
        if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 3L, 3L))) {
            return HttpResult.error("业务繁忙，请稍后再试!");
        }
        KwoTradeOrder order = kwoTradeOrderService.getById(id);
        if (Objects.isNull(order)) {
            return HttpResult.error("订单不存在!");
        }
        if (!Objects.equals(String.valueOf(order.getStatus()), DictEnum.TORDER_STATUS_4.getValue())) {
            return HttpResult.error("执行中的订单才可物流托运！");
        }
        BigDecimal amount = order.getAmount();
        BigDecimal addEntrustAmount = order.getEntrustAmount();
        if (Objects.nonNull(param.getEntrustAmount())) {
            addEntrustAmount = addEntrustAmount.add(param.getActualAmount());
            if (amount.compareTo(addEntrustAmount) < 0) {
                return HttpResult.error("物流已委托总量不可大于订单总量！");
            }
        }
        BigDecimal addActualAmount = order.getActualAmount();
        if (Objects.nonNull(param.getActualAmount())) {
            addActualAmount = addActualAmount.add(param.getActualAmount());
            if (amount.compareTo(addActualAmount) < 0) {
                return HttpResult.error("物流实际交付总量不可大于订单总量！");
            }
        }
        order.setEntrustAmount(addEntrustAmount).setActualAmount(addActualAmount).setUpdateBy(param.getUpdateBy());
        //已履约量等于订单总量自动完结订单
        if (amount.compareTo(addActualAmount) == 0) {
            order.setStatus(Integer.valueOf(DictEnum.TORDER_STATUS_5.getValue()));
            KwoTradeOrderTrack track = new KwoTradeOrderTrack();
            track.setTOrderId(order.getId()).setTOrderNo(order.getTOrderNo()).setStatus(order.getStatus())
                    .setCreateBy(updateBy).setUpdateBy(updateBy);
            kwoTradeOrderTrackService.insert(track);
        }
        kwoTradeOrderService.updateById(order);
        //更新mongodb
        SckwTradeOrder updateParam = new SckwTradeOrder();
        updateParam.setTOrderId(order.getId()).setEntrustAmount(addEntrustAmount).setActualAmount(addActualAmount)
                .setStatus(order.getStatus()).setUpdateBy(param.getUpdateBy()).setUpdateByName(param.getUpdateByName()).setUpdateTime(new Date());
        saveMongoDb(3, updateParam);
        return HttpResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void contractSignCompleted(ContractSignCompletedParam param) {
        if (Objects.isNull(param.getUpdateBy()) || StringUtils.isBlank(param.getUpdateByName())) {
            throw new BusinessException("操作人信息不能为空!");
        }
        Long contractId = param.getContractId();
        Long updateBy = param.getUpdateBy();
        List<KwoTradeOrderContract> contracts = kwoTradeOrderContractService.getByContractId(contractId);
        if (CollectionUtils.isEmpty(contracts)) {
            log.info("合同：{}无相关联待签约的贸易订单", contractId);
            return;
        }
        List<Long> tOrderIds = contracts.stream().map(KwoTradeOrderContract::getTOrderId).toList();
        List<KwoTradeOrder> orders = kwoTradeOrderService.getWaitSignByIds(tOrderIds);
        if (CollectionUtils.isEmpty(orders)) {
            log.info("合同：{}无相关联待签约的贸易订单", contractId);
            return;
        }
        List<KwoTradeOrderTrack> tracks = Lists.newArrayList();
        List<SckwTradeOrder> tradeOrders = Lists.newArrayList();
        List<Long> ids = orders.stream().map(KwoTradeOrder::getId).toList();
        kwoTradeOrderService.contractCompletedUpdate(ids, updateBy);
        orders.forEach(e -> {
            KwoTradeOrderTrack track = new KwoTradeOrderTrack();
            track.setTOrderId(e.getId()).setTOrderNo(e.getTOrderNo()).setStatus(Integer.valueOf(DictEnum.TORDER_STATUS_4.getValue()))
                    .setCreateBy(updateBy).setUpdateBy(updateBy);
            tracks.add(track);
            SckwTradeOrder updateParam = new SckwTradeOrder();
            updateParam.setTOrderId(e.getId()).setStatus(Integer.valueOf(DictEnum.TORDER_STATUS_4.getValue()))
                    .setUpdateBy(updateBy).setUpdateByName(param.getUpdateByName()).setUpdateTime(new Date());
            tradeOrders.add(updateParam);
        });
        kwoTradeOrderTrackService.insertBatch(tracks);
        tradeOrders.forEach(e -> {
            saveMongoDb(3, e);
        });
    }

    /**
     * @desc: mq保存mongodb
     * @author: yzc
     * @date: 2023-07-17 8:43
     * @Param method:
     * @Param order:
     * @return: void
     */
    private void saveMongoDb(Integer method, Object order) {
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType("tradeOrder");
        busSum.setMethod(method);
        busSum.setObject(order);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
    }
}
