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

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinBackOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderVo;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;

import java.math.BigDecimal;
import java.util.HashMap;

@Component
@Slf4j
public class GoblinRefundHelper {
    @Autowired
    private GoblinRedisUtils redisUtils;

    @Value("${liquidnet.service.order.url-pay.goblinRefundUrl}")
    private String synUrl;
    @Value("${liquidnet.service.dragon.urls.refundApply}")
    private String refundApply;
    @Value("${liquidnet.service.order.url-pay.goblinRefundUrl}")
    private String goblinRefundUrl;
    @Value("${liquidnet.service.dragon.urls.refundResult}")
    private String refundApplyCallBack;

    public static BigDecimal remainRefundPrice(GoblinOrderSkuVo orderSkuVo, BigDecimal applyingRefundPrice) {
        BigDecimal priceActual = nullToZero(orderSkuVo.getSkuPriceActual());
        BigDecimal priceRefund = nullToZero(orderSkuVo.getPriceRefund());
        BigDecimal applying = nullToZero(applyingRefundPrice);
        BigDecimal remain = priceActual.subtract(priceRefund).subtract(applying);
        return remain.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : remain;
    }

    public static BigDecimal beforeShipRefundPrice(BigDecimal skuRefundPrice, BigDecimal priceExpress) {
        return nullToZero(skuRefundPrice).add(nullToZero(priceExpress));
    }

    public static GoblinBackOrderSkuVo buildBackOrderSkuVo(GoblinOrderSkuVo orderSkuVo, BigDecimal refundPrice, String nowStr) {
        GoblinBackOrderSkuVo backOrderSkuVo = GoblinBackOrderSkuVo.getNew();
        backOrderSkuVo.setOrderSkuId(orderSkuVo.getOrderSkuId());
        backOrderSkuVo.setSpuId(orderSkuVo.getSpuId());
        backOrderSkuVo.setSpuName(orderSkuVo.getSpuName());
        backOrderSkuVo.setSkuId(orderSkuVo.getSkuId());
        backOrderSkuVo.setSkuName(orderSkuVo.getSkuName());
        backOrderSkuVo.setRefundPrice(refundPrice);
        backOrderSkuVo.setSkuSpecs(orderSkuVo.getSkuSpecs());
        backOrderSkuVo.setCreatedAt(nowStr);
        backOrderSkuVo.setSkuPic(orderSkuVo.getSkuImage());
        backOrderSkuVo.setSkuType(orderSkuVo.getSkuType());
        return backOrderSkuVo;
    }

    public static boolean isBackOrderFinished(Integer status) {
        return status != null && (status == 2 || status == 3 || status == 5 || status == 8 || status == 9 || status == 10 || status == 11);
    }

    public static boolean isUnshippedSku(GoblinOrderSkuVo orderSkuVo) {
        return orderSkuVo != null && orderSkuVo.getStatus() == 2;
    }

    public static boolean isShippedSku(GoblinOrderSkuVo orderSkuVo) {
        if (orderSkuVo == null) {
            return false;
        }
        return orderSkuVo.getStatus() == 3 || orderSkuVo.getStatus() == 4;
    }

    /**
     * 推断退款单发起方：优先读已存储值；历史数据无 operationType 时按 describes/reason 兜底。
     */
    public static Integer resolveBackOrderOperationType(GoblinBackOrderVo backOrderVo) {
        if (backOrderVo == null) {
            return GoblinStatusConst.Type.OPERATION_TYPE_1.getValue();
        }
        if (backOrderVo.getOperationType() != null) {
            return backOrderVo.getOperationType();
        }
        if ("店铺退款".equals(backOrderVo.getDescribes())
                || GoblinStatusConst.Type.BACK_REASON_TYPE_8.getDesc().equals(backOrderVo.getReason())) {
            return GoblinStatusConst.Type.OPERATION_TYPE_2.getValue();
        }
        return GoblinStatusConst.Type.OPERATION_TYPE_1.getValue();
    }

    public String initRefund(GoblinStoreOrderVo orderVo, BigDecimal price, String refundCode) {
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("code", orderVo.getPayCode());
        params.add("notifyUrl", synUrl);
        params.add("orderCode", orderVo.getMasterOrderCode());
        params.add("orderRefundCode", refundCode);
        params.add("paymentId", orderVo.getPaymentId());
        params.add("paymentType", orderVo.getPaymentType());
        params.add("price", String.valueOf(price));
        params.add("priceTotal", String.valueOf(getMasterOrderActualPrice(orderVo)));
        params.add("reason", "按需退款");
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        String returnString = HttpUtil.post(refundApply, params, headers);
        log.debug("REFUND DATA = " + returnString);
        return returnString;
    }

    public String alipayCallBack(GoblinStoreOrderVo orderVo, String refundCode) {
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("callBackUrl", goblinRefundUrl);
        params.add("orderCode", orderVo.getMasterOrderCode());
        params.add("orderRefundCode", refundCode);
        params.add("paymentId", orderVo.getPaymentId());
        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");
        log.debug("REFUND CALLBACK params = " + params);
        String returnString = HttpUtil.post(refundApplyCallBack, params, headers);
        log.debug("REFUND CALLBACK DATA = " + returnString);
        return returnString;
    }

    public boolean isRefundSuccess(String returnString) {
        HashMap hashMapResult = JsonUtils.fromJson(returnString, HashMap.class);
        Boolean success = (Boolean) hashMapResult.get("success");
        return Boolean.TRUE.equals(success);
    }

    public String getRefundMessage(String returnString) {
        HashMap hashMapResult = JsonUtils.fromJson(returnString, HashMap.class);
        String message = (String) hashMapResult.get("message");
        return message == null ? "" : message;
    }

    private BigDecimal getMasterOrderActualPrice(GoblinStoreOrderVo orderVo) {
        BigDecimal totalPrice = BigDecimal.ZERO;
        String[] orderIds = redisUtils.getMasterCode(orderVo.getMasterOrderCode());
        if (orderIds == null || orderIds.length == 0) {
            return nullToZero(orderVo.getPriceActual());
        }
        for (String orderId : orderIds) {
            GoblinStoreOrderVo vo = redisUtils.getGoblinOrder(orderId);
            if (vo != null) {
                totalPrice = totalPrice.add(nullToZero(vo.getPriceActual()));
            }
        }
        return totalPrice.compareTo(BigDecimal.ZERO) > 0 ? totalPrice : nullToZero(orderVo.getPriceActual());
    }

    private static BigDecimal nullToZero(BigDecimal value) {
        return value == null ? BigDecimal.ZERO : value;
    }
}
