# utils/chat_utils.py
import json
import logging
import re
import requests
from django.conf import settings
from django.db.models import Q
from orders.models import Order, PlatformOrderExt, MerchantOrderExt
from users.models import UserDashou, UserBoss, UserShangjia
from users.business_models import User

logger = logging.getLogger('chat_utils')

ORDER_STATUS_TEXT = {
    1: '待抢单', 2: '进行中', 3: '已完成', 4: '退款审核中', 5: '已退款',
    7: '指定中', 8: '结算中', 9: '未支付', 14: '支付失败', 25: '已废弃',
}

# ========== 辅助配置获取 ==========
def _get_self_goeasy_appkey():
    return getattr(settings, 'GOEASY_APPKEY', '')

def _get_self_goeasy_secret():
    return getattr(settings, 'GOEASY_SECRET', '')

# ========== 头像拼接 ==========
def _full_local_avatar(relative_url):
    if not relative_url:
        return ''
    if relative_url.startswith('http'):
        return relative_url
    domain = getattr(settings, 'COS_DOMAIN', '') or ''
    if domain:
        return domain.rstrip('/') + '/' + relative_url.lstrip('/')
    return relative_url


def build_merchant_link_chat_meta(order, link_merchant_uid):
    """H5 商家链接页群聊：新单走配对群，旧单或无打手时回落 group_{orderId}"""
    pair_id = resolve_pair_group_id(order)
    legacy_id = f'group_{order.OrderID}'
    group_id = pair_id or legacy_id
    dashou_uid = order.PlayerID or ''
    self_user_id = f'B{link_merchant_uid}' if link_merchant_uid else ''
    shangjia_biaoshi = ''
    try:
        if order.Platform == 2 and getattr(order, 'shangjia_kuozhan', None):
            mid = order.shangjia_kuozhan.MerchantID
            if mid:
                shangjia_biaoshi = f'Sj{mid}'
    except Exception:
        pass
    return {
        'group_id': group_id,
        'is_pair_group': bool(pair_id),
        'legacy_group_id': legacy_id,
        'self_user_id': self_user_id,
        'dashou_biaoshi': f'Ds{dashou_uid}' if dashou_uid else '',
        'shangjia_biaoshi': shangjia_biaoshi,
        'you_dashou': bool(dashou_uid),
    }


def subscribe_merchant_link_chat(order, link_merchant_uid):
    """链接页有打手时，预订阅 B{商家} 与打手到对应群（新旧群 ID 均兼容）"""
    meta = build_merchant_link_chat_meta(order, link_merchant_uid)
    if not meta.get('you_dashou'):
        return meta, True
    appkey = _get_self_goeasy_appkey()
    secret = _get_self_goeasy_secret()
    if not appkey:
        return meta, False
    user_ids = []
    if meta.get('self_user_id'):
        user_ids.append(meta['self_user_id'])
    if meta.get('dashou_biaoshi'):
        user_ids.append(meta['dashou_biaoshi'])
    group_ids = [meta['group_id']]
    if meta.get('legacy_group_id') and meta['legacy_group_id'] != meta['group_id']:
        group_ids.append(meta['legacy_group_id'])
    ok = _subscribe_users_to_group(user_ids, group_ids, appkey, secret)
    return meta, ok


def resolve_pair_group_id(order):
    """打手+商家/老板配对群 ID，与前端 resolveLocalGroupId 一致（同两人共用一个群）"""
    dashou_uid = order.PlayerID or ''
    if not dashou_uid:
        return None
    if order.Platform == 2:
        try:
            sj_uid = order.shangjia_kuozhan.MerchantID
            if sj_uid:
                return f'group_Ds{dashou_uid}_Sj{sj_uid}'
        except Exception as e:
            logger.warning(f'配对群(商家)解析失败: {e}')
    elif order.Platform == 1:
        try:
            boss_uid = order.pingtai_kuozhan.BossID
            if boss_uid:
                return f'group_Ds{dashou_uid}_Boss{boss_uid}'
        except Exception as e:
            logger.warning(f'配对群(老板)解析失败: {e}')
    return None


def resolve_order_chat_group_id(order):
    """
    进订单聊天用的群 ID：始终优先配对群 group_Ds…_Sj/Boss…（抢单时已建）。
    组队只往该群加人/发公告，不再切到 group_{订单ID} 另起会话。
    """
    oid = (getattr(order, 'OrderID', None) or '').strip()
    return resolve_pair_group_id(order) or (f'group_{oid}' if oid else None)


def parse_pair_from_group_id(group_id):
    """从配对群 ID 解析打手 uid、对方 uid、对方角色(shangjia/boss)"""
    if not group_id:
        return None, None, None
    m = re.match(r'^group_Ds(\w+)_Sj(\w+)$', str(group_id))
    if m:
        return m.group(1), m.group(2), 'shangjia'
    m = re.match(r'^group_Ds(\w+)_Boss(\w+)$', str(group_id))
    if m:
        return m.group(1), m.group(2), 'boss'
    return None, None, None


def resolve_pair_from_order(order):
    """从订单解析打手与下单方配对信息"""
    dashou_uid = order.PlayerID or ''
    if not dashou_uid:
        return None, None, None
    if order.Platform == 2:
        try:
            sj_uid = order.shangjia_kuozhan.MerchantID
            if sj_uid:
                return dashou_uid, sj_uid, 'shangjia'
        except Exception:
            pass
    elif order.Platform == 1:
        try:
            boss_uid = order.pingtai_kuozhan.BossID
            if boss_uid:
                return dashou_uid, boss_uid, 'boss'
        except Exception:
            pass
    return dashou_uid, None, None


def check_pair_chat_permission(identity_type, uid, dashou_uid, partner_uid, partner_role):
    if identity_type == 'PlayerID':
        if uid != dashou_uid:
            return False, '你不是该会话的打手'
        return True, ''
    if identity_type == 'shangjia':
        if partner_role != 'shangjia' or uid != partner_uid:
            return False, '你不是该会话的商家'
        return True, ''
    if identity_type == 'boss':
        if partner_role != 'boss' or uid != partner_uid:
            return False, '你不是该会话的老板'
        return True, ''
    return False, '不支持的身份类型'


def order_to_chat_dict(order):
    """聊天侧订单摘要。金额不返回：老板/平台订单聊天页不得展示订单价格。"""
    return {
        'dingdan_id': order.OrderID,
        'jieshao': order.Description or '',
        # 故意不返回 jine，避免消息列表/订单条展示价格
        'jine': '',
        'beizhu': order.Remark or '',
        'zhuangtai': order.Status,
        'zhuangtaiText': ORDER_STATUS_TEXT.get(order.Status, ''),
        'nicheng': order.Nickname or '',
        'create_time': order.CreateTime.strftime('%Y-%m-%d %H:%M') if order.CreateTime else '',
    }


def query_pair_orders(dashou_uid, partner_uid, partner_role, keyword='', limit=30):
    if not dashou_uid or not partner_uid:
        return []
    qs = Order.objects.filter(PlayerID=dashou_uid).select_related('pingtai_kuozhan', 'shangjia_kuozhan')
    if partner_role == 'shangjia':
        qs = qs.filter(Platform=2, shangjia_kuozhan__MerchantID=partner_uid)
    elif partner_role == 'boss':
        qs = qs.filter(Platform=1, pingtai_kuozhan__BossID=partner_uid)
    else:
        return []
    qs = qs.exclude(Status__in=[9, 14, 25])
    if keyword:
        qs = qs.filter(Q(OrderID__icontains=keyword) | Q(Description__icontains=keyword))
    return [order_to_chat_dict(o) for o in qs.order_by('-CreateTime')[:limit]]


def _get_dashou_profile(order):
    dashou_uid = order.PlayerID or ''
    dashou_goeasy_id = f'Ds{dashou_uid}' if dashou_uid else ''
    dashou_nickname = f'打手{dashou_uid[:6]}' if dashou_uid else ''
    dashou_avatar = ''
    if dashou_uid:
        try:
            dashou_user = User.objects.get(UserUID=dashou_uid)
            dashou_avatar = _full_local_avatar(dashou_user.Avatar or '')
            dashou_profile = UserDashou.objects.get(user=dashou_user)
            if dashou_profile.nicheng:
                dashou_nickname = dashou_profile.nicheng
        except Exception as e:
            logger.warning(f'获取打手资料失败: {e}')
    return dashou_uid, dashou_goeasy_id, dashou_nickname, dashou_avatar


def build_order_group_chat_payload(order, viewer_backend_identity, viewer_uid):
    """构建前端 ltdhzb 所需群聊元数据（统一配对群，组队不另建群）"""
    group_id = resolve_order_chat_group_id(order) or f'group_{order.OrderID}'
    order_desc = order.Description or ''
    group_name = (
        (order_desc[:20] + '…') if order_desc and len(order_desc) > 20
        else (order_desc or f'订单{order.OrderID}')
    )
    dashou_uid, dashou_goeasy_id, dashou_name, dashou_avatar = _get_dashou_profile(order)
    partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
    partner_uid = ''
    if partner_goeasy_id:
        partner_uid = partner_goeasy_id.replace('Ds', '').replace('Sj', '').replace('Boss', '')

    counterpart_id = ''
    counterpart_yonghuid = ''
    counterpart_name = ''
    counterpart_avatar = ''
    if viewer_backend_identity == 'PlayerID':
        counterpart_id = partner_goeasy_id or ''
        counterpart_yonghuid = partner_uid
        counterpart_name = partner_name or ''
        counterpart_avatar = partner_avatar or ''
    else:
        counterpart_id = dashou_goeasy_id or ''
        counterpart_yonghuid = dashou_uid
        counterpart_name = dashou_name or ''
        counterpart_avatar = dashou_avatar or ''

    return {
        'groupId': group_id,
        'orderId': order.OrderID,
        'groupName': counterpart_name or group_name,
        'groupAvatar': counterpart_avatar or partner_avatar or dashou_avatar or '',
        'counterpartName': counterpart_name,
        'counterpartAvatar': counterpart_avatar,
        'counterpartId': counterpart_id,
        'counterpartYonghuid': counterpart_yonghuid,
        'orderDesc': order_desc,
        # 聊天页顶栏/会话元数据不带订单价格
        'orderJine': '',
        'orderZhuangtai': order.Status,
        'dashouGoEasyId': dashou_goeasy_id,
        'partnerGoEasyId': partner_goeasy_id or '',
        'dashouYonghuid': dashou_uid,
        'partnerYonghuid': partner_uid,
        'dashouName': dashou_name,
        'partnerName': partner_name or '',
        'dashouAvatar': dashou_avatar,
        'partnerAvatar': partner_avatar or '',
        'isCross': 0,
    }


def prepare_order_group_chat(order, viewer_backend_identity, viewer_uid, subscribe=True):
    """进入群聊前：订阅当前用户（及双方/组队成员）到目标群，不重复发送抢单初始化消息"""
    payload = build_order_group_chat_payload(order, viewer_backend_identity, viewer_uid)
    group_id = payload['groupId']
    appkey = _get_self_goeasy_appkey()
    secret = _get_self_goeasy_secret()
    if not appkey:
        logger.error('GoEasy AppKey 未配置')
        return payload, False

    prefix_map = {'PlayerID': 'Ds', 'shangjia': 'Sj', 'boss': 'Boss'}
    viewer_goeasy_id = prefix_map.get(viewer_backend_identity, 'Ds') + viewer_uid
    user_ids = {viewer_goeasy_id}
    if payload.get('dashouGoEasyId'):
        user_ids.add(payload['dashouGoEasyId'])
    if payload.get('partnerGoEasyId'):
        user_ids.add(payload['partnerGoEasyId'])

    # 有组队时：把在队打手一并订阅进同一配对群
    oid = (getattr(order, 'OrderID', None) or '').strip()
    if oid:
        try:
            from orders.models import TeamMember
            from orders.services.team_recruit import get_active_recruit
            rec = get_active_recruit(oid)
            if rec:
                for m in TeamMember.query.filter(
                    recruit_id=rec.id, join_status=TeamMember.JOIN_ACTIVE,
                ).only('user_uid')[:20]:
                    uid = (m.user_uid or '').strip()
                    if uid:
                        user_ids.add(f'Ds{uid}')
        except Exception as e:
            logger.warning('prepare 订阅组队成员失败 order=%s: %s', oid, e)

    subscribed = True
    if subscribe and user_ids:
        subscribed = _subscribe_users_to_group(list(user_ids), [group_id], appkey, secret)
    return payload, subscribed

# ========== GoEasy 订阅 ==========
def _subscribe_users_to_group(user_ids, group_ids, appkey=None, secret=None):
    if not appkey:
        appkey = _get_self_goeasy_appkey()
    if not secret:
        secret = _get_self_goeasy_secret()
    if not appkey:
        logger.error("GoEasy AppKey 未配置")
        return False
    url = 'https://rest-hangzhou.goeasy.io/v2/im/subscribe-groups'
    body = {"appkey": appkey, "userIds": user_ids, "groupIds": group_ids}
    headers = {"Content-Type": "application/json"}
    if secret:
        headers["Authorization"] = f"Bearer {secret}"
    try:
        resp = requests.post(url, headers=headers, json=body, timeout=10)
        if resp.status_code == 200:
            return True
        logger.error(f"订阅失败: {resp.status_code} {resp.text}")
        return False
    except Exception as e:
        logger.error(f"订阅异常: {e}", exc_info=True)
        return False

# ========== 发送群消息（完整参数） ==========
def _send_group_message(appkey, secret, group_id, sender_id, sender_name, sender_avatar,
                        message_text, custom_payload=None, group_name=None, order_id=None):
    if not appkey:
        appkey = _get_self_goeasy_appkey()
    if not secret:
        secret = _get_self_goeasy_secret()
    if not appkey:
        logger.error("GoEasy AppKey 未配置")
        return False

    url = 'https://rest-hangzhou.goeasy.io/v2/im/message'

    # to.data 包含群聊展示信息及业务字段
    to_data = {
        "name": group_name or group_id,
        "avatar": sender_avatar or "",
    }
    if order_id:
        to_data["orderId"] = order_id

    payload_str = custom_payload.get("text", message_text) if custom_payload else message_text

    request_body = {
        "appkey": appkey,
        "senderId": sender_id,
        "senderData": {"avatar": sender_avatar, "name": sender_name},
        "to": {
            "type": "group",
            "id": group_id,
            "data": to_data
        },
        "type": "text",
        "payload": payload_str
    }
    headers = {"Content-Type": "application/json"}
    if secret:
        headers["Authorization"] = f"Bearer {secret}"
    try:
        resp = requests.post(url, headers=headers, json=request_body, timeout=10)
        if resp.status_code == 200:
            return True
        logger.error(f"群聊消息发送失败，状态码:{resp.status_code}，响应:{resp.text}")
        return False
    except Exception as e:
        logger.error(f"发送群聊消息异常: {e}", exc_info=True)
        return False

# ========== 核心入口 ==========
def establish_order_chat(dingdan_id):
    try:
        order = Order.objects.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=dingdan_id)
    except Order.DoesNotExist:
        logger.error(f"订单 {dingdan_id} 不存在")
        return False

    dashou_uid = order.PlayerID
    dashou_goeasy_id = f"Ds{dashou_uid}"
    dashou_nickname = f'打手{dashou_uid[:6]}'
    dashou_avatar_relative = ''
    try:
        dashou_user = User.objects.get(UserUID=dashou_uid)
        dashou_avatar_relative = dashou_user.Avatar or ''
        dashou_profile = UserDashou.objects.get(user=dashou_user)
        if dashou_profile.nicheng:
            dashou_nickname = dashou_profile.nicheng
    except Exception as e:
        logger.warning(f"获取打手信息失败: {e}")
    dashou_avatar = _full_local_avatar(dashou_avatar_relative)

    appkey = _get_self_goeasy_appkey()
    secret = _get_self_goeasy_secret()
    if not appkey:
        logger.error("GoEasy AppKey 未配置")
        return False

    # 本地订单处理
    return _handle_local_order(order, dashou_goeasy_id, dashou_nickname, dashou_avatar, appkey, secret)

# ========== 普通订单 / 我方派单 ==========
def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
    # 与详情「联系」一致：统一配对群（组队不另建）
    group_id = resolve_order_chat_group_id(order) or f"group_{order.OrderID}"
    group_name = (order.Description[:20] + '…') if order.Description and len(order.Description) > 20 else (order.Description or f"订单{order.OrderID}")
    group_avatar = _full_local_avatar(order.ImageURL) if order.ImageURL else _full_local_avatar('')

    partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
    if not partner_goeasy_id:
        logger.error('抢单建聊失败：找不到商家/老板 partner order=%s', order.OrderID)
        return False

    subscribe_ids = [dashou_goeasy_id, partner_goeasy_id]
    # 组队订单：把在队队员也拉进群，避免队员消息列表空白
    try:
        from orders.models import TeamMember, TeamRecruit
        rec = TeamRecruit.query.filter(
            order_id=order.OrderID,
            status__in=[TeamRecruit.STATUS_RECRUITING, TeamRecruit.STATUS_LOCKED],
        ).first()
        if rec:
            for uid in TeamMember.query.filter(
                recruit_id=rec.id, join_status=TeamMember.JOIN_ACTIVE,
            ).values_list('user_uid', flat=True):
                u = (uid or '').strip()
                if u:
                    subscribe_ids.append(f'Ds{u}')
    except Exception as e:
        logger.warning('抢单建聊订阅组队成员失败: %s', e)

    # 订阅双方（失败则重试）
    subscribed = _subscribe_users_to_group(subscribe_ids, [group_id], appkey, secret)
    if not subscribed:
        subscribed = _subscribe_users_to_group(subscribe_ids, [group_id], appkey, secret)
    if not subscribed:
        logger.error('抢单建聊订阅失败 order=%s group=%s', order.OrderID, group_id)
        return False

    # 1. 打手代发进群消息：禁止带订单金额/价格
    init_msg_text = (
        f"订单已接单，内容：{order.Description or ''}，"
        f"备注：{order.Remark or ''}，游戏ID：{order.Nickname or ''}"
    )
    success1 = _send_group_message(
        appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
        init_msg_text, None, group_name=group_name, order_id=order.OrderID
    )
    if not success1:
        success1 = _send_group_message(
            appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
            init_msg_text, None, group_name=group_name, order_id=order.OrderID
        )

    # 2. 派单方也发一条，确保商家/老板会话列表能立刻出现该群（同样不带价格）
    partner_msg = "订单已被接单，请及时沟通。"
    success2 = _send_group_message(
        appkey, secret, group_id, partner_goeasy_id, partner_name, partner_avatar,
        partner_msg, None, group_name=group_name, order_id=order.OrderID
    )
    if not success2:
        success2 = _send_group_message(
            appkey, secret, group_id, partner_goeasy_id, partner_name, partner_avatar,
            partner_msg, None, group_name=group_name, order_id=order.OrderID
        )

    ok = bool(success1 or success2)
    if not ok:
        logger.error('抢单建聊发消息失败 order=%s group=%s', order.OrderID, group_id)
    return ok

def _get_local_partner_info(order):
    """本地订单下单方：老板或商家"""
    if order.Platform == 1:  # 老板
        try:
            ext = order.pingtai_kuozhan
            laoban_id = ext.BossID
            avatar_full = _full_local_avatar('')
            nickname = f'老板{laoban_id[:6]}'
            try:
                boss_user = User.objects.get(UserUID=laoban_id)
                avatar_full = _full_local_avatar(boss_user.Avatar or '')
                boss_profile = UserBoss.objects.get(user=boss_user)
                if boss_profile.nickname:
                    nickname = boss_profile.nickname
            except Exception:
                pass
            return f"Boss{laoban_id}", nickname, avatar_full
        except Exception as e:
            logger.error(f"获取老板信息失败: {e}")
            return None, None, None
    elif order.Platform == 2:  # 商家
        try:
            ext = order.shangjia_kuozhan
            shangjia_id = ext.MerchantID
            nickname = ext.MerchantNickname or f'商家{shangjia_id[:6]}'
            avatar_full = _full_local_avatar('')
            try:
                sj_user = User.objects.get(UserUID=shangjia_id)
                avatar_full = _full_local_avatar(sj_user.Avatar or '')
            except Exception:
                pass
            return f"Sj{shangjia_id}", nickname, avatar_full
        except Exception as e:
            logger.error(f"获取商家信息失败: {e}")
            return None, None, None
    else:
        if order.User1ID:
            return order.User1ID, "用户", _full_local_avatar('')
        return None, None, None