package com.gxwebsoft.shop.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.entity.ShopStoreUser;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopStoreUserService;
import com.gxwebsoft.shop.service.WxSubscribeMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 微信小程序订阅消息服务实现
 *
 * @author 科技小王子
 * @since 2026-07-04
 */
@Slf4j
@Service
public class WxSubscribeMessageServiceImpl implements WxSubscribeMessageService {

    /** 新订单通知模板 ID */
    private static final String NEW_ORDER_TMPL_ID = "sh1K9iK7vZjebUNFu6OsMsnsJxm4whThWGrhN7I4zVg";

    /** 消息跳转页面 */
    private static final String ORDER_PAGE = "pages/store/orders/index";

    @Resource
    private ShopStoreUserService shopStoreUserService;

    @Resource
    private ShopOrderGoodsService shopOrderGoodsService;

    @Resource
    private UserService userService;

    @Resource
    private WxMiniappAccessTokenService accessTokenService;

    @Override
    public void sendNewOrderNotification(ShopOrder order) {
        if (order == null || order.getStoreId() == null) {
            log.debug("订单无关联门店，跳过订阅消息推送，orderId={}", order != null ? order.getOrderId() : null);
            return;
        }

        try {
            // 1. 获取门店所有店员的 openid
            List<String> clerkOpenids = getClerkOpenids(order.getStoreId(), order.getTenantId());
            if (CollectionUtils.isEmpty(clerkOpenids)) {
                log.info("门店无店员或店员未绑定微信，跳过订阅消息推送，storeId={}", order.getStoreId());
                return;
            }

            // 2. 获取 access_token
            String accessToken;
            try {
                accessToken = accessTokenService.getAccessToken(order.getTenantId());
            } catch (Exception e) {
                log.error("获取微信 access_token 失败，跳过订阅消息推送，tenantId={}", order.getTenantId(), e);
                return;
            }

            // 3. 构建消息数据
            JSONObject messageData = buildMessageData(order);

            // 4. 逐个发送给店员
            for (String openid : clerkOpenids) {
                sendToOneClerk(accessToken, openid, messageData);
            }
        } catch (Exception e) {
            // 订阅消息推送失败不影响订单创建
            log.error("发送新订单订阅消息异常，orderNo={}", order.getOrderNo(), e);
        }
    }

    /**
     * 获取门店所有店员的微信小程序 openid
     */
    private List<String> getClerkOpenids(Integer storeId, Integer tenantId) {
        QueryWrapper<ShopStoreUser> wrapper = new QueryWrapper<>();
        wrapper.eq("store_id", storeId)
                .eq("tenant_id", tenantId)
                .eq("is_delete", 0);

        List<ShopStoreUser> clerks = shopStoreUserService.list(wrapper);
        if (CollectionUtils.isEmpty(clerks)) {
            return Collections.emptyList();
        }

        // 提取 userId 列表
        List<Integer> userIds = clerks.stream()
                .map(ShopStoreUser::getUserId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyList();
        }

        // 批量查询用户，获取 openid
        List<User> users = userService.listByIds(userIds);
        return users.stream()
                .map(User::getOpenid)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());
    }

    /**
     * 构建订阅消息数据
     */
    private JSONObject buildMessageData(ShopOrder order) {
        // 获取第一个商品名称（多个商品时显示第一个 + "等"）
        String goodsName = "";
        List<ShopOrderGoods> orderGoods = order.getOrderGoods();
        // 如果 order.getOrderGoods() 为空（创建订单时），从数据库查询
        if (CollectionUtils.isEmpty(orderGoods) && order.getOrderId() != null) {
            QueryWrapper<ShopOrderGoods> goodsWrapper = new QueryWrapper<>();
            goodsWrapper.eq("order_id", order.getOrderId());
            orderGoods = shopOrderGoodsService.list(goodsWrapper);
        }
        if (!CollectionUtils.isEmpty(orderGoods)) {
            goodsName = orderGoods.get(0).getGoodsName();
            if (orderGoods.size() > 1) {
                goodsName = goodsName + "等" + orderGoods.size() + "件";
            }
        }

        // 订阅消息数据（按模板字段映射）
        JSONObject data = new JSONObject();
        data.put("character_string1", buildField(limitStr(order.getOrderNo(), 32)));  // 订单号
        data.put("thing4", buildField(limitStr(goodsName, 20)));                      // 商品名称
        data.put("thing10", buildField(limitStr(order.getRealName(), 20)));           // 联系人
        data.put("phone_number7", buildField(limitStr(order.getPhone(), 17)));        // 联系电话
        data.put("thing8", buildField(limitStr(order.getAddress(), 20)));             // 送货地址

        return data;
    }

    /**
     * 构建单个字段值
     */
    private JSONObject buildField(String value) {
        JSONObject field = new JSONObject();
        field.put("value", value != null ? value : "");
        return field;
    }

    /**
     * 限制字符串长度（微信字段值有长度限制）
     */
    private String limitStr(String str, int maxLen) {
        if (str == null) return "";
        if (str.length() <= maxLen) return str;
        return str.substring(0, maxLen - 1) + "…";
    }

    /**
     * 向单个店员发送订阅消息
     */
    private void sendToOneClerk(String accessToken, String openid, JSONObject data) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;

        JSONObject body = new JSONObject();
        body.put("touser", openid);
        body.put("template_id", NEW_ORDER_TMPL_ID);
        body.put("page", ORDER_PAGE);
        body.put("miniprogram_state", "formal");
        body.put("lang", "zh_CN");
        body.put("data", data);

        try {
            String result = HttpUtil.post(url, body.toJSONString());
            JSONObject respJson = JSON.parseObject(result);

            if (respJson.containsKey("errcode") && respJson.getIntValue("errcode") == 0) {
                log.info("新订单订阅消息发送成功，openid={}，orderNo={}", openid,
                        data.getJSONObject("character_string1") != null
                                ? data.getJSONObject("character_string1").getString("value") : "");
            } else {
                Integer errcode = respJson.getInteger("errcode");
                String errmsg = respJson.getString("errmsg");
                // errcode 43101 表示用户未订阅（未授权），属于正常情况，不报错
                if (errcode != null && errcode == 43101) {
                    log.info("用户未订阅该消息，跳过，openid={}", openid);
                } else {
                    log.warn("订阅消息发送失败，openid={}，errcode={}，errmsg={}", openid, errcode, errmsg);
                }
            }
        } catch (Exception e) {
            log.warn("订阅消息发送异常，openid={}", openid, e);
        }
    }
}
