package com.liquidnet.service.goblin.service.impl;

import com.google.common.base.Joiner;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinBackOrder;
import com.liquidnet.service.goblin.entity.GoblinBackOrderLog;
import com.liquidnet.service.goblin.param.GoblinAppOrderRefundParam;
import com.liquidnet.service.goblin.service.IGoblinOrderAppService;
import com.liquidnet.service.goblin.util.*;
import io.github.classgraph.json.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
@Slf4j
public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService {

    @Autowired
    GoblinRedisUtils redisUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinOrderUtils orderUtils;


    @Override
    public ResponseDto<List<GoblinAppOrderListVo>> orderList(int page) {
        String uid = CurrentUtil.getCurrentUid();
        List<GoblinAppOrderListVo> orderVoList = ObjectUtil.goblinAppOrderListVoArrayList();
        List<String> orderIds = redisUtils.getOrderList(uid);
        int size = 40;
        int initCount = (page - 1) * size;
        int finalCount = page * size;
        if (finalCount >= orderIds.size()) {
            finalCount = orderIds.size();
        }
        for (int i = initCount; i < finalCount; i++) {
            String orderId = orderIds.get(i);
            GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
            GoblinAppOrderListVo vo = GoblinAppOrderListVo.getNew();
            BeanUtils.copyProperties(orderVo, vo);
            List<GoblinOrderSkuVo> skuVos = ObjectUtil.getGoblinOrderSkuVoArrayList();
            for (String orderSkuId : orderVo.getOrderSkuVoIds()) {
                GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuId);
                skuVos.add(orderSkuVo);
            }
            vo.setOrderSkuVos(skuVos);
            orderVoList.add(vo);
        }
        return ResponseDto.success(orderVoList);
    }

    @Override
    public ResponseDto<GoblinAppOrderDetailsVo> orderDetails(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
        if (!orderVo.getUserId().equals(uid)) {
            return ResponseDto.failure("无权查看");
        }
        GoblinAppOrderDetailsVo vo = GoblinAppOrderDetailsVo.getNew();
        List<GoblinOrderSkuVo> skuVos = ObjectUtil.getGoblinOrderSkuVoArrayList();
        for (String orderSkuId : orderVo.getOrderSkuVoIds()) {
            GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuId);
            skuVos.add(orderSkuVo);
        }
        vo.setStoreOrderVo(orderVo);
        vo.setOrderSkuVos(skuVos);
        return ResponseDto.success(vo);
    }

    @Override
    public ResponseDto<Boolean> applyRefund(GoblinAppOrderRefundParam param) {
        String uid = CurrentUtil.getCurrentUid();
        LocalDateTime now = LocalDateTime.now();
        String nowStr = DateUtil.getNowTime();
        GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(param.getOrderId());
        if (!orderVo.getUserId().equals(uid)) {
            return ResponseDto.failure("无权操作");
        }
        if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_0.getValue() ||
                orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_5.getValue()) {
            return ResponseDto.failure("不可操作");
        }
        GoblinBackOrder backOrder = GoblinBackOrder.getNew();
        backOrder.setBackOrderId(IDGenerator.nextTimeId2());
        backOrder.setBackCode(IDGenerator.storeRefundCode(orderVo.getMasterOrderCode()));
        backOrder.setOrderId(param.getOrderId());
        backOrder.setOrderCode(orderVo.getOrderCode());
        backOrder.setStoreId(orderVo.getStoreId());
        backOrder.setUserId(orderVo.getUserId());
        backOrder.setType(GoblinStatusConst.Type.BACK_TYPE_1.getValue());
        backOrder.setStatus(GoblinStatusConst.Status.ORDER_BACK_STATUS_1.getValue());
        backOrder.setCreatedAt(now);
        if (orderVo.getMailNo() == null || orderVo.getMailNo().equals("")) {//未发货
            backOrder.setRealBackPrice(orderVo.getPriceActual());
            backOrder.setReason(param.getReason());
            backOrder.setPics(param.getPics());
            backOrder.setDescribes(param.getDescribes());
            backOrder.setSkuIdNums(Joiner.on(",").join(orderVo.getOrderSkuVoIds()));
        } else {//已发货
            GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(param.getOrderSkuId());
            backOrder.setRealBackPrice(orderSkuVo.getSkuPriceActual());
            backOrder.setReason(param.getReason());
            backOrder.setPics(param.getPics());
            backOrder.setDescribes(param.getDescribes());
            backOrder.setType(param.getRefundType());
            backOrder.setSkuIdNums(param.getOrderSkuId());
        }
        GoblinBackOrderVo vo = GoblinBackOrderVo.getNew();
        BeanUtils.copyProperties(backOrder, vo);
        vo.setCreatedAt(nowStr);
        List<GoblinBackOrderSkuVo> orderSkuVoList = ObjectUtil.goblinBackOrderSkuVoArrayList();
        if (param.getOrderSkuId() == null) {
            for (String orderSkuId : orderVo.getOrderSkuVoIds()) {
                GoblinBackOrderSkuVo backOrderSkuVo = GoblinBackOrderSkuVo.getNew();
                backOrderSkuVo.setOrderSkuId(orderSkuId);
                GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuId);
                backOrderSkuVo.setSpuId(orderSkuVo.getSpuId());
                backOrderSkuVo.setSpuName(orderSkuVo.getSpuName());
                backOrderSkuVo.setSkuId(orderSkuVo.getSkuId());
                backOrderSkuVo.setSkuName(orderSkuVo.getSkuName());
                backOrderSkuVo.setSkuSpecs(orderSkuVo.getSkuSpecs());
                backOrderSkuVo.setCreatedAt(nowStr);
                orderSkuVoList.add(backOrderSkuVo);
                backOrderLog(orderVo, orderSkuVo, now);
            }
        } else {
            GoblinBackOrderSkuVo backOrderSkuVo = GoblinBackOrderSkuVo.getNew();
            backOrderSkuVo.setOrderSkuId(param.getOrderSkuId());
            GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(param.getOrderSkuId());
            backOrderSkuVo.setSpuId(orderSkuVo.getSpuId());
            backOrderSkuVo.setSpuName(orderSkuVo.getSpuName());
            backOrderSkuVo.setSkuId(orderSkuVo.getSkuId());
            backOrderSkuVo.setSkuName(orderSkuVo.getSkuName());
            backOrderSkuVo.setSkuSpecs(orderSkuVo.getSkuSpecs());
            backOrderSkuVo.setCreatedAt(nowStr);
            orderSkuVoList.add(backOrderSkuVo);
            backOrderLog(orderVo, orderSkuVo, now);
        }
        vo.setBackOrderSkuVos(orderSkuVoList);
        //添加日志
        GoblinBackOrderLog backOrderLog = initBackLog(param.getOrderId(), uid, now);
        backOrderLog.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_21.getValue());
        backOrderLog.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_1.getValue());
        backOrderLog.setMessage("用户发起发起：" + JsonUtils.toJson(param));
        //mysql
        redisUtils.setBackOrderVo(backOrder.getBackOrderId(), vo);
        //mongo
        mongoUtils.insertGoblinBackOrderVo(vo);
        //mysql
        queueUtils.sendMsgByRedis(
                MQConst.GoblinQueue.GOBLIN_USER_ORDER_OPERA.getKey(),
                SqlMapping.get("goblin_order.user.applyRefund",
                        backOrder.getBackOrderId(), backOrder.getBackCode(), backOrder.getOrderId(),
                        backOrder.getOrderCode(), backOrder.getStoreId(), backOrder.getUserId(),
                        backOrder.getSkuIdNums(), backOrder.getType(), backOrder.getReason(),
                        backOrder.getDescribes(), backOrder.getRealBackPrice(), backOrder.getStatus(),
                        backOrder.getCreatedAt()
                )
        );
        //添加日志
        queueUtils.sendMsgByRedis(
                MQConst.GoblinQueue.GOBLIN_USER_ORDER_OPERA.getKey(),
                SqlMapping.get("goblin_order.store.refundLog",
                        backOrderLog.getBackOrderLogId(), backOrderLog.getBackOrderId(), backOrderLog.getOperationType(),
                        backOrderLog.getMessage(), backOrderLog.getOperationName(), backOrderLog.getStatus(), now
                )
        );
        return ResponseDto.success();
    }

    private GoblinBackOrderLog initBackLog(String orderId, String uid, LocalDateTime now) {
        GoblinBackOrderLog log = GoblinBackOrderLog.getNew();
        log.setBackOrderId(orderId);
        log.setOperationName(uid);
        log.setBackOrderLogId(IDGenerator.nextTimeId2());
        log.setCreatedAt(now);
        return log;
    }

    private void backOrderLog(GoblinStoreOrderVo orderVo, GoblinOrderSkuVo orderSkuVo, LocalDateTime now) {
        //操作日志vo
        GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
        logVo.setOrderId(orderVo.getOrderId());
        logVo.setOrderCode(orderVo.getOrderCode());
        logVo.setPayCode(orderVo.getPayCode());
        if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()) > 0) {
            logVo.setOrderType("zhengzai");
        } else {
            logVo.setOrderType("order");
        }
        logVo.setStoreId(orderVo.getStoreId());
        logVo.setSpuId(orderSkuVo.getSpuId());
        logVo.setSpuName(orderSkuVo.getSpuName());
        logVo.setSkuId(orderSkuVo.getSkuId());
        logVo.setSkuPriceActual(orderSkuVo.getSkuPriceActual().multiply(BigDecimal.valueOf(100)).negate().longValue());
        logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue());
        logVo.setOperationId(orderVo.getUserId());
        logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_2.getValue());
        logVo.setCreatedAt(now);
        mongoUtils.insertGoblinOrderLogVo(logVo);
    }
}
