package com.gxwebsoft.shop.service.impl;

import cn.binarywang.wx.miniapp.bean.shop.request.shipping.OrderKeyBean;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.PayerBean;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.ShippingListBean;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.WxMaOrderShippingInfoUploadRequest;
import cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.common.system.service.WxMiniappAccessTokenService;
import com.gxwebsoft.shop.entity.ShopExpress;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderDelivery;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopWechatShippingSyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 同步系统发货信息到微信小程序后台（发货信息录入）。
 */
@Slf4j
@Service
public class ShopWechatShippingSyncServiceImpl implements ShopWechatShippingSyncService {

    private static final int ORDER_NUMBER_TYPE_OUT_TRADE_NO = 1;
    private static final int ORDER_NUMBER_TYPE_TRANSACTION_ID = 2;

    // 这两个值在项目原有注释代码中已经使用过（实物快递）。
    private static final int LOGISTICS_TYPE_PHYSICAL = 1;
    private static final int DELIVERY_MODE_EXPRESS = 1;

    // 无需物流/自提：微信侧会在“发货信息录入”里变为已发货（具体枚举以微信接口为准）。
    private static final int LOGISTICS_TYPE_NO_LOGISTICS = 3;
    private static final int DELIVERY_MODE_NO_LOGISTICS = 3;

    private static final Gson GSON = new Gson();

    @Resource
    private WxMiniappAccessTokenService wxMiniappAccessTokenService;
    @Resource
    private UserService userService;
    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;
    @Resource
    private ShopGoodsService shopGoodsService;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public boolean uploadExpressShippingInfo(ShopOrder order, ShopOrderDelivery orderDelivery, ShopExpress express) {
        if (order == null || order.getOrderId() == null) {
            return false;
        }
        if (orderDelivery == null || StrUtil.isBlank(orderDelivery.getExpressNo())) {
            log.warn("上传微信发货信息跳过：缺少运单号 - orderId={}", order.getOrderId());
            return false;
        }
        if (express == null || StrUtil.isBlank(express.getWxCode())) {
            log.warn("上传微信发货信息跳过：缺少微信快递公司编码(wxCode) - orderId={}", order.getOrderId());
            return false;
        }

        List<ShippingListBean> shippingList = new ArrayList<>();
        ShippingListBean item = new ShippingListBean();
        item.setTrackingNo(orderDelivery.getExpressNo());
        item.setExpressCompany(express.getWxCode());
        item.setItemDesc(buildItemDesc(order.getOrderId()));
        shippingList.add(item);

        return doUpload(order, LOGISTICS_TYPE_PHYSICAL, DELIVERY_MODE_EXPRESS, shippingList);
    }

    @Override
    public boolean uploadNoLogisticsShippingInfo(ShopOrder order) {
        if (order == null || order.getOrderId() == null) {
            return false;
        }
        // 无需物流情况下通常不需要 shipping_list
        return doUpload(order, LOGISTICS_TYPE_NO_LOGISTICS, DELIVERY_MODE_NO_LOGISTICS, Collections.emptyList());
    }

    private boolean doUpload(ShopOrder order, int logisticsType, int deliveryMode, List<ShippingListBean> shippingList) {
        // 仅对微信支付订单尝试同步（微信后台“待发货”来自微信支付交易）
        if (!ObjectUtil.equals(order.getPayType(), 1) && !ObjectUtil.equals(order.getPayType(), 102)) {
            return false;
        }
        if (!Boolean.TRUE.equals(order.getPayStatus())) {
            return false;
        }
        if (order.getTenantId() == null) {
            return false;
        }

        // payer openid：必须是下单用户，不是后台操作员
        User buyer = userService.getByIdIgnoreTenant(order.getUserId());
        if (buyer == null || StrUtil.isBlank(buyer.getOpenid())) {
            log.warn("上传微信发货信息失败：买家openid为空 - orderId={}, userId={}", order.getOrderId(), order.getUserId());
            return false;
        }

        String accessToken;
        try {
            accessToken = wxMiniappAccessTokenService.getAccessToken(order.getTenantId());
        } catch (Exception e) {
            log.error("获取小程序access_token失败 - orderId={}, tenantId={}", order.getOrderId(), order.getTenantId(), e);
            return false;
        }

        OrderKeyBean orderKey = buildOrderKey(order);
        if (orderKey == null) {
            log.warn("上传微信发货信息跳过：无法构建order_key - orderId={}", order.getOrderId());
            return false;
        }

        WxMaOrderShippingInfoUploadRequest uploadRequest = new WxMaOrderShippingInfoUploadRequest();
        uploadRequest.setOrderKey(orderKey);
        uploadRequest.setLogisticsType(logisticsType);
        uploadRequest.setDeliveryMode(deliveryMode);
        uploadRequest.setIsAllDelivered(true);
        if (shippingList != null && !shippingList.isEmpty()) {
            uploadRequest.setShippingList(shippingList);
        }
        uploadRequest.setUploadTime(new DateTime().toString(DatePattern.UTC_WITH_ZONE_OFFSET_PATTERN));

        PayerBean payerBean = new PayerBean();
        payerBean.setOpenid(buyer.getOpenid());
        uploadRequest.setPayer(payerBean);

        String url = WxMaApiUrlConstants.OrderShipping.UPLOAD_SHIPPING_INFO + "?access_token=" + accessToken;
        String body = GSON.toJson(uploadRequest);

        try {
            String resp = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .body(body)
                    .timeout(10000)
                    .execute()
                    .body();
            JsonObject json = JsonParser.parseString(resp).getAsJsonObject();
            int errcode = json.has("errcode") ? json.get("errcode").getAsInt() : -1;
            String errmsg = json.has("errmsg") ? json.get("errmsg").getAsString() : resp;
            if (errcode == 0) {
                log.info("✅ 微信发货信息同步成功 - orderId={}, logisticsType={}, deliveryMode={}",
                        order.getOrderId(), logisticsType, deliveryMode);
                return true;
            }
            log.error("❌ 微信发货信息同步失败 - orderId={}, errcode={}, errmsg={}, req={}",
                    order.getOrderId(), errcode, errmsg, body);
            return false;
        } catch (Exception e) {
            log.error("❌ 微信发货信息同步异常 - orderId={}, req={}", order.getOrderId(), body, e);
            return false;
        }
    }

    private OrderKeyBean buildOrderKey(ShopOrder order) {
        if (StrUtil.isNotBlank(order.getTransactionId())) {
            OrderKeyBean key = new OrderKeyBean();
            key.setOrderNumberType(ORDER_NUMBER_TYPE_TRANSACTION_ID);
            key.setTransactionId(order.getTransactionId());
            return key;
        }

        // transactionId 为空时，尝试使用 out_trade_no + mchid
        if (StrUtil.isBlank(order.getOrderNo())) {
            return null;
        }

        Payment payment = loadWechatPaymentConfig(order.getTenantId());
        if (payment == null || StrUtil.isBlank(payment.getMchId())) {
            return null;
        }

        OrderKeyBean key = new OrderKeyBean();
        key.setOrderNumberType(ORDER_NUMBER_TYPE_OUT_TRADE_NO);
        key.setOutTradeNo(order.getOrderNo());
        key.setMchId(payment.getMchId());
        return key;
    }

    private Payment loadWechatPaymentConfig(Integer tenantId) {
        if (tenantId == null) {
            return null;
        }
        // 与微信支付回调一致：Payment:1:{tenantId}
        String key = "Payment:1:" + tenantId;
        try {
            return redisUtil.get(key, Payment.class);
        } catch (Exception e) {
            log.warn("读取支付配置失败 - key={}", key, e);
            return null;
        }
    }

    private String buildItemDesc(Integer orderId) {
        try {
            List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderId(orderId);
            if (orderGoodsList == null || orderGoodsList.isEmpty()) {
                return "订单商品";
            }
            ShopGoods shopGoods = shopGoodsService.getById(orderGoodsList.get(0).getGoodsId());
            String itemDesc = shopGoods != null && StrUtil.isNotBlank(shopGoods.getName()) ? shopGoods.getName() : "订单商品";
            if (orderGoodsList.size() > 1) {
                itemDesc += "等" + orderGoodsList.size() + "件商品";
            }
            return itemDesc;
        } catch (Exception e) {
            log.warn("构建微信发货 item_desc 失败 - orderId={}", orderId, e);
            return "订单商品";
        }
    }
}
