package com.sckw.transport.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.contract.api.model.dto.res.ContractCommonInfoResDto;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.model.enums.LogisticsOrderEnum;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.OrderDetailRes;
import com.sckw.order.api.model.UpdateOrderAmountParam;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.transport.api.model.dto.vo.LogisticsOrderDTO;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.DocumentParamDTO;
import com.sckw.transport.model.dto.OrderDTO;
import com.sckw.transport.model.param.LogisticsOrderParam;
import com.sckw.transport.model.vo.OrderDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author lfdc
 * @description 运输服务公共service接口
 * @date 2023-06-29 15:06:45
 */
@Slf4j
@Service
public class TransportCommonService {

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

    @DubboReference(version = "2.0.0", group = "design", check = false)
    TradeOrderInfoService tradeOrderInfoService;

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

    @Autowired
    public KwtLogisticsOrderGoodsMapper logisticsOrderGoodsMapper;

    @Autowired
    public KwtLogisticsOrderContractMapper logisticsOrderContractMapper;

    @Autowired
    public KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    public KwtLogisticsOrderAddressMapper logisticsOrderAddressMapper;

    @Autowired
    public KwtLogisticsOrderTrackMapper logisticsOrderTrackMapper;

    @Autowired
    public KwtLogisticsOrderUnitMapper logisticsOrderUnitMapper;

    @Autowired
    public KwtWaybillOrderMapper waybillOrderMapper;

    /**
     * 查看订单详情
     *
     * @param dto
     * @return
     */
    public HttpResult getOrderDetail(DocumentParamDTO dto) {
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(HttpStatus.SUCCESS_CODE);
        if (String.valueOf(NumberConstant.THREE).equals(dto.getDocumentType())) {
            //托运订单
            OrderDetailVO orderDetailVO = getOrderData(dto);
            httpResult.setData(orderDetailVO);
        } else if (String.valueOf(NumberConstant.TWO).equals(dto.getDocumentType())) {
            //承运订单
            OrderDetailVO orderDetailVO = getOrderData(dto);
            httpResult.setData(orderDetailVO);
        } else if (String.valueOf(NumberConstant.ZERO).equals(dto.getDocumentType())) {
            //销售订单
            OrderDetailVO orderDetailVO = getOrderData(dto);
            httpResult.setData(orderDetailVO);
        } else if (String.valueOf(NumberConstant.ONE).equals(dto.getDocumentType())) {
            //采购订单
            OrderDetailVO orderDetailVO = getOrderData(dto);
            httpResult.setData(orderDetailVO);
        } else {
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            httpResult.setMsg("单据类型错误");
        }
        return httpResult;
    }

    /**
     * 获取订单详情
     *
     * @param dto
     * @return
     */
    private OrderDetailVO getOrderData(DocumentParamDTO dto) {
        KwtLogisticsOrder logisticsOrder = logisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, dto.getId())
                .eq(StringUtils.isNotBlank(dto.getDocumentNo()), KwtLogisticsOrder::getLOrderNo, dto.getDocumentNo())
                /**.eq(KwtLogisticsOrder::getEntId, LoginUserHolder.getEntId())*/);
        if (logisticsOrder == null) {
            log.info("查无单据:{}", JSONObject.toJSONString(dto));
            throw new RuntimeException("查无单据");

        }
        KwtLogisticsOrderContract contract = logisticsOrderContractMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                .eq(StringUtils.isNotBlank(dto.getId()), KwtLogisticsOrderContract::getLOrderId, dto.getId()));
        KwtLogisticsOrderUnit unitOne = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                .eq(StringUtils.isNotBlank(dto.getId()), KwtLogisticsOrderUnit::getLOrderId, dto.getId())
                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
        KwtLogisticsOrderUnit unitTwo = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                .eq(StringUtils.isNotBlank(dto.getId()), KwtLogisticsOrderUnit::getLOrderId, dto.getId())
                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
        KwtLogisticsOrderAddress loadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                .eq(StringUtils.isNotBlank(dto.getId()), KwtLogisticsOrderAddress::getLOrderId, dto.getId())
                .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE));
        KwtLogisticsOrderAddress unloadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                .eq(StringUtils.isNotBlank(dto.getId()), KwtLogisticsOrderAddress::getLOrderId, dto.getId())
                .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO));
        KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                .eq(StringUtils.isNotBlank(logisticsOrder.getId()), KwtLogisticsOrderGoods::getLOrderId, logisticsOrder.getId()));
        OrderDetailVO orderDetailVO = new OrderDetailVO();
        orderDetailVO.setId(String.valueOf(logisticsOrder.getId()));
        if (contract != null) {
            orderDetailVO.setContractId(contract.getContractId() == null ? null : String.valueOf(contract.getContractId()));
            //todo 接口调用合同服务查询合同信息
            List<Long> list = new ArrayList<>(NumberConstant.SIXTEEN);
            list.add(contract.getContractId());
            Map<Long, ContractCommonInfoResDto> contractBaseInfo = remoteContractService.queryContractBaseInfo(list);
            if (CollectionUtils.isNotEmpty(contractBaseInfo) && !ObjectUtils.isEmpty(contractBaseInfo.get(contract.getContractId()))) {
                orderDetailVO.setContractName(contractBaseInfo.get(contract.getContractId()).getContactName());
                orderDetailVO.setContractNo(contractBaseInfo.get(contract.getContractId()).getContractCode());
            }
        }
        if (unitOne != null) {
            orderDetailVO.setConsignCompany(unitOne.getFirmName());
            orderDetailVO.setConsignContacts(unitOne.getContacts());
            orderDetailVO.setConsignPhone(unitOne.getPhone());
            orderDetailVO.setCollectionCompany(unitOne.getFirmName());
        }
        if (unitTwo != null) {
            orderDetailVO.setCarrierCompany(unitTwo.getFirmName());
            orderDetailVO.setCarrierContacts(unitTwo.getContacts());
            orderDetailVO.setCarrierPhone(unitTwo.getPhone());
        }
        orderDetailVO.setGoodsName(orderGoods == null ? null : orderGoods.getGoodsName());
        orderDetailVO.setNumber(logisticsOrder.getAmount() == null ? null : String.valueOf(logisticsOrder.getAmount()));
        orderDetailVO.setPrice(logisticsOrder.getPrice() == null ? null : String.valueOf(logisticsOrder.getPrice()));
        orderDetailVO.setLoss(logisticsOrder.getLoss() == null ? null : String.valueOf(logisticsOrder.getLoss()));
        orderDetailVO.setDeduct(logisticsOrder.getGoodsPrice() == null ? null : String.valueOf(logisticsOrder.getGoodsPrice()));
        orderDetailVO.setLoadAddress(loadOrderAddress.getName());
        orderDetailVO.setLoadContacts(loadOrderAddress.getContacts());
        orderDetailVO.setLoadPhone(loadOrderAddress.getPhone());
        orderDetailVO.setLoadAddressDetail(loadOrderAddress.getDetailAddress());
        orderDetailVO.setUnloadAddress(unloadOrderAddress.getName());
        orderDetailVO.setUnloadContacts(unloadOrderAddress.getContacts());
        orderDetailVO.setUnloadPhone(unloadOrderAddress.getPhone());
        orderDetailVO.setUnloadAddressDetail(unloadOrderAddress.getDetailAddress());
        orderDetailVO.setSettlementCycle(logisticsOrder.getSettlementCycle() == null ? null : String.valueOf(logisticsOrder.getSettlementCycle()));
        orderDetailVO.setBillingMode(logisticsOrder.getBillingMode());
        orderDetailVO.setScheduleStartTime(logisticsOrder.getStartTime() == null ? null : DateUtil.getDateTime(logisticsOrder.getStartTime()));
        orderDetailVO.setScheduleEndTime(logisticsOrder.getEndTime() == null ? null : DateUtil.getDateTime(logisticsOrder.getEndTime()));
        orderDetailVO.setPerformanceAmount(logisticsOrder.getLoadAmount() == null ? null : String.valueOf(logisticsOrder.getLoadAmount()));
        return orderDetailVO;
    }

    /**
     * 撤销托运
     *
     * @param orderDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult cancelConsign(OrderDTO orderDto) {
        log.info("订单-撤销托运请求参数:{}", JSONObject.toJSONString(orderDto));
        HttpResult result = new HttpResult();
        KwtLogisticsOrder logisticsOrder = logisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, orderDto.getId())
                .eq(KwtLogisticsOrder::getLOrderNo, orderDto.getOrderNo())
                /**.eq(KwtLogisticsOrder::getEntId, LoginUserHolder.getEntId())*/);
        if (logisticsOrder == null) {
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            result.setMsg("单据不存在");
            return result;
        }
        if (!LogisticsOrderEnum.TO_BE_PLANNED.getCode().equals(logisticsOrder.getStatus())) {
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            result.setMsg("待接单才允许撤销托运");
            return result;
        }
        /**以此字段判别是否存在分包操作*/
        if (ObjectUtils.isEmpty(logisticsOrder.getPid())) {
            /**并不存在分包，撤销数据回归到贸易订单，[待接单状态]下才能撤销托运*/
            /**调用dubbo 修改数值*/
            Long tOrderId = logisticsOrder.getTOrderId();
            OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(tOrderId);
            UpdateOrderAmountParam param = new UpdateOrderAmountParam();
            param.setTOrderId(tOrderId);
            param.setActualAmount(orderDetailRes.getActualAmount().add(logisticsOrder.getLoadAmount()));
            param.setEntrustAmount(orderDetailRes.getEntrustAmount().add(logisticsOrder.getEntrustAmount().subtract(logisticsOrder.getLoadAmount())));
            tradeOrderInfoService.updateOrderAmount(param);
            logisticsOrder.setDelFlag(1);
            logisticsOrder.setUpdateTime(new Date());
            logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
            logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, logisticsOrder.getId())
                    .set(KwtLogisticsOrder::getDelFlag, NumberConstant.ONE)
                    .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                    .set(KwtLogisticsOrder::getUpdateTime, new Date()));
        } else {
            /**即代表存在分包,当次是属于被分包.需要将数据回归到上游数据。*/
            Long pid = logisticsOrder.getPid();
            /**指的是上游单据进行回归*/
            KwtLogisticsOrder order = logisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, pid));
            //上游分配量
            BigDecimal amount = logisticsOrder.getAmount();
            //已经完成的量
            BigDecimal unloadAmount = logisticsOrder.getUnloadAmount();
            //未完成的量
            BigDecimal subtract = amount.subtract(unloadAmount);
            //.setScale(2,BigDecimal.ROUND_HALF_DOWN)
            BigDecimal add = order.getSubcontractAmount().add(subtract);
            logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, order.getId())
                    .set(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
                    .set(KwtLogisticsOrder::getSubcontractAmount, add)
                    .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                    .set(KwtLogisticsOrder::getUpdateTime, new Date()));
            /**下游订单进行删除*/
            logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, logisticsOrder.getId())
                    .set(KwtLogisticsOrder::getDelFlag, NumberConstant.ONE)
                    .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                    .set(KwtLogisticsOrder::getUpdateTime, new Date()));
        }
        return result;
    }

    /**
     * 对账管理-运费收款对账界面查询接口
     * @param logisticsOrderParam
     * @return
     */
    public HttpResult getAcceptCarriageOrder(LogisticsOrderParam logisticsOrderParam) {
        SysDictResDto sysDictResDto = remoteSystemService.queryDictByTypeAndValue(logisticsOrderParam.getPaymentType(), logisticsOrderParam.getPayment());
        Long dictId = sysDictResDto.getId();
        if (StringUtils.isNotBlank(logisticsOrderParam.getStartTime())) {
            logisticsOrderParam.setStartTime(logisticsOrderParam.getStartTime() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(logisticsOrderParam.getEndTime())) {
            logisticsOrderParam.setEndTime(logisticsOrderParam.getEndTime() + " 23:59:59");
        }
        Integer page = logisticsOrderParam.getPage();
        logisticsOrderParam.setPage(logisticsOrderParam.getPage() - 1);
        List<LogisticsOrderDTO> list = logisticsOrderMapper.selectLogisticOrderData(logisticsOrderParam, dictId);
        Long count = logisticsOrderMapper.selectLogisticOrderCount(logisticsOrderParam, dictId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (LogisticsOrderDTO logisticsOrderDTO : list) {
                KwtLogisticsOrderUnit orderUnit = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
                KwtLogisticsOrderUnit orderUnit1 = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
                logisticsOrderDTO.setCarrierCompany(orderUnit1 == null ? null : orderUnit1.getFirmName());
                logisticsOrderDTO.setConsignCompany(orderUnit == null ? null : orderUnit.getFirmName());
                logisticsOrderDTO.setCount(waybillOrderMapper.selectCount(new LambdaQueryWrapper<KwtWaybillOrder>().eq(KwtWaybillOrder::getLOrderId, logisticsOrderDTO.getLOrderId())));
            }
        }
        PageResult build = PageResult.build(page, logisticsOrderParam.getPageSize(), count, list);
        return HttpResult.ok(build);
    }
}
