# utils/weixin_broadcast.py - 强调试版本
import time
import logging
import json  # 新增，用于格式化打印
import requests
from django.core.cache import cache
from django.conf import settings
from yonghu.models import OfficialAccountUser

logger = logging.getLogger('weixin_broadcast')


class WeixinBroadcastSender:
    """
    微信模板消息广播发送器 - 调试版
    """

    def __init__(self):
        self.appid = getattr(settings, 'WEIXIN_OFFICIAL_APPID', '')
        self.secret = getattr(settings, 'WEIXIN_OFFICIAL_SECRET', '')
        self.template_id = getattr(settings, 'WEIXIN_TEMPLATE_ID', '')

        # 发送控制参数
        self.batch_size = 100
        self.delay_between_batches = 1.5

    def get_access_token(self):
        """获取服务号access_token"""
        cache_key = f'weixin_official_token_{self.appid}'
        token = cache.get(cache_key)
        if token:
            return token

        url = 'https://api.weixin.qq.com/cgi-bin/token'
        params = {'grant_type': 'client_credential', 'appid': self.appid, 'secret': self.secret}
        try:
            response = requests.get(url, params=params, timeout=10)
            result = response.json()
            if 'access_token' in result:
                token = result['access_token']
                expires_in = result.get('expires_in', 7200) - 300
                cache.set(cache_key, token, expires_in)
                logger.info("✅ 获取access_token成功")
                return token
            else:
                logger.error(f"❌ 获取access_token失败: {result}")
                return None
        except Exception as e:
            logger.error(f"❌ 获取access_token异常: {str(e)}")
            return None

    def build_order_message_data(self, order_info):
        """
        构建订单消息数据 - 【调试关键点1】
        打印传入的 order_info 和构建出的最终数据
        """
        # 🟡 调试点1：打印传入的参数
        logger.info(
            f"🟡【调试-输入】build_order_message_data 收到的 order_info: {json.dumps(order_info, ensure_ascii=False, indent=2)}")

        # 这是你现在的构建逻辑，我们原样保留但加上调试
        # 注意：这里保持你目前的字段名（short_thing5, short_thing4, thing15, amount8）
        data = {
            "short_thing5": {
                "value": order_info.get('order_type', '平台发单'),
                "color": "#173177"
            },
            "short_thing4": {
                "value": order_info.get('game_type', '游戏订单'),
                "color": "#173177"
            },
            "thing15": {
                "value": str(order_info.get('order_desc', '新订单'))[:20],
                "color": "#173177"
            },
            "amount8": {
                "value": f"{order_info.get('amount', '0')}元",
                "color": "#173177"
            }
        }

        # 🟡 调试点2：打印构建出的最终数据结构
        logger.info(f"🟡【调试-输出】构建完成的模板数据 data 字段：")
        for key, content in data.items():
            logger.info(f"      字段名: '{key}' -> 值: '{content.get('value', '')}'")
        logger.info(f"🟡【调试-输出】完整 data 结构: {json.dumps(data, ensure_ascii=False)}")

        # 🔴 关键检查：确认 short_thing5 是否存在，值是否为空
        if 'short_thing5' not in data:
            logger.error("❌【致命错误】构建的数据中根本没有 'short_thing5' 这个字段！")
        else:
            st5_value = data['short_thing5'].get('value', '')
            if not st5_value:
                logger.error(f"❌【致命错误】'short_thing5' 字段的值为空！")
            else:
                logger.info(f"✅ 'short_thing5' 字段存在，值为: '{st5_value}'")

        return data

    def send_to_user(self, official_openid, template_data, order_id=None):
        """发送模板消息给单个用户 - 【调试关键点2】"""
        # 🟡 调试点3：打印每次发送前的数据
        logger.info(f"🟡【调试-发送前】准备发送给 {official_openid[:10]}... 的数据:")
        logger.info(f"      模板ID: {self.template_id}")
        logger.info(
            f"      pagepath: pages/dingdan-xiangqing/dingdan-xiangqing?id={order_id}" if order_id else "      无pagepath")
        for key, content in template_data.items():
            logger.info(f"      字段 '{key}': '{content.get('value', '')}'")

        access_token = self.get_access_token()
        if not access_token:
            return {'success': False, 'msg': '获取access_token失败', 'retry': True}

        request_data = {
            "touser": official_openid,
            "template_id": self.template_id,
            "data": template_data
        }

        if order_id and hasattr(settings, 'WEIXIN_APPID'):
            request_data["miniprogram"] = {
                "appid": settings.WEIXIN_APPID,
                "pagepath": f"pages/jiedan/jiedan?id={order_id}"
            }

        send_url = f'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={access_token}'
        try:
            response = requests.post(send_url, json=request_data, timeout=10)
            result = response.json()
            logger.info(f"🟡【调试-微信响应】{official_openid[:10]}... 的发送结果: {result}")

            if result.get('errcode') == 0:
                return {'success': True, 'msg': '发送成功', 'msgid': result.get('msgid')}
            else:
                # 如果是未关注或拒收，更新本地状态
                if result.get('errcode') in [43004, 43101]:
                    try:
                        OfficialAccountUser.objects.filter(official_openid=official_openid).update(is_subscribed=False)
                    except:
                        pass
                return {'success': False, 'msg': f"[{result.get('errcode')}]{result.get('errmsg')}", 'retry': False}

        except Exception as e:
            logger.error(f"❌ 发送给用户异常: {official_openid[:10]}..., 错误: {str(e)}")
            return {'success': False, 'msg': f'请求异常: {str(e)}', 'retry': True}

    def broadcast_order(self, order_info):
        """广播订单消息给所有关注用户 - 【调试入口】"""
        logger.info(f"🚀【开始广播】订单: {order_info.get('dingdan_id')}")

        # 1. 获取所有关注用户
        try:
            subscribed_users = OfficialAccountUser.objects.filter(is_subscribed=True).values_list('official_openid',
                                                                                                  flat=True)
            total_users = subscribed_users.count()
            logger.info(f"📊【广播统计】将从数据库查询到 {total_users} 个订阅用户")
            if total_users == 0:
                return {'success': True, 'msg': '无订阅用户', 'total': 0}
        except Exception as e:
            logger.error(f"❌ 获取订阅用户列表失败: {str(e)}")
            return {'success': False, 'msg': f'获取用户失败: {str(e)}'}

        # 2. 构建模板数据（这里会触发上面的调试打印）
        template_data = self.build_order_message_data(order_info)
        order_id = order_info.get('dingdan_id')

        # 3. 分批发送
        success_count = 0
        fail_count = 0
        current_batch = 0
        openid_list = list(subscribed_users)

        logger.info(f"🟡【调试-广播循环】开始遍历 {len(openid_list)} 个用户进行发送...")
        for i, openid in enumerate(openid_list):
            try:
                result = self.send_to_user(openid, template_data, order_id)
                if result['success']:
                    success_count += 1
                else:
                    fail_count += 1
                    if fail_count <= 5:  # 只打印前几个失败原因
                        logger.warning(f"⚠️ 发送失败 {openid[:10]}...: {result.get('msg')}")

                # 分批控制
                current_batch += 1
                if current_batch >= self.batch_size:
                    time.sleep(self.delay_between_batches)
                    current_batch = 0

            except Exception as e:
                fail_count += 1
                logger.error(f"❌ 处理用户 {openid[:10]}... 异常: {str(e)}")

        logger.info(f"🏁【广播完成】订单 {order_id}，总计: {total_users}，成功: {success_count}，失败: {fail_count}")
        return {
            'success': True,
            'msg': f'广播完成: 成功{success_count}, 失败{fail_count}',
            'total': total_users,
            'success_count': success_count,
            'fail_count': fail_count
        }