"""orders.views.chat - auto-generated by split script."""
# ==================== 标准库 ====================
import hmac
import os
import json
import time
import random
import string
import traceback
import threading
import requests
import hashlib
import xml.etree.ElementTree as ET
import xmltodict
import logging
from decimal import Decimal

from django.conf import settings
from django.db import models, transaction
from gvsdsdk.fluent import db, func, FQ
from django.db.models import F, Q, OuterRef, Subquery
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from django.utils import timezone

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions, status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.parsers import JSONParser
from rest_framework.throttling import AnonRateThrottle
from rest_framework_simplejwt.authentication import JWTAuthentication

from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.sts.v20180813 import sts_client, models

from utils.weixin_broadcast import WeixinBroadcastSender
from utils.money import yuan_to_fen
from utils.chat_utils import (
    _send_group_message, _subscribe_users_to_group, establish_order_chat,
    prepare_order_group_chat, resolve_pair_group_id, resolve_order_chat_group_id,
    parse_pair_from_group_id, resolve_pair_from_order, check_pair_chat_permission,
    query_pair_orders, order_to_chat_dict,
)
from utils.fadan_utils import check_fadan_qiangdan_eligible

from orders.utils import (
    calc_shangjia_order_fencheng,
    update_daily_payout,
    settle_shangjia_order_guanshi_fenhong
)
from shop.utils import calculate_pingtai_and_dianpu_shouyi, validate_shangpin_and_dianpu, update_dianpu_daily_stat
from products.utils import update_shangpin_daily_stat
from backend.utils import update_shangjia_daily, update_dashou_daily_by_action, pick_leixing_id, datetime_aliases, fmt_datetime
from rank.services import record_dashou_biaoxian
from rank.utils import check_dashou_biaoqian_required

from orders.notice_tasks import dingdan_guangbo

from ..models import (
    Order, MerchantOrderExt, PlatformOrderExt, PlayerDeliveryImage,
    PenaltyRecord, PenaltyEvidenceImage, Penalty, PenaltyAppealImage, PenaltyBonus, PenaltyBonusRate,
    CommissionRate, PlayerRating, RefundRecord,
)
from jituan.services.club_config import get_commission_rate, get_commission_rate_object
from jituan.services.club_context import resolve_club_id_from_request
from jituan.services.club_user import get_payment_openid
from jituan.services.club_penalty import resolve_penalty_club_id, resolve_penalty_record_club_id
from users.fadan_fenhong_utils import lock_penalty_bonus
from users.fadan_fenhong_utils import lock_penalty_bonus
from products.models import Shangpin, ShangpinLeixing, Huiyuangoumai
from users.models import UserDashou, UserShangjia, UserBoss
from users.business_models import User
from rank.models import DashouBiaoxian, Chenghao, DingdanBiaoqian, YonghuChenghao
from config.models import (
    ShangjiaLianjie
)



logger = logging.getLogger(__name__)

def get_self_goeasy_appkey():
    try:
        return getattr(settings, 'GOEASY_APPKEY', None)
    except Exception:
        return None


def get_self_goeasy_secret():
    try:
        return getattr(settings, 'GOEASY_SECRET', None)
    except Exception:
        return None


def get_self_storage_domain():
    try:
        return getattr(settings, 'COS_DOMAIN', '')
    except Exception:
        return ''


def full_avatar(relative_url, bucket_domain=None):
    if not relative_url:
        return ''
    if relative_url.startswith('http'):
        return relative_url
    domain = bucket_domain or get_self_storage_domain()
    if domain:
        domain = domain.rstrip('/') + '/'
        return domain + relative_url.lstrip('/')
    return relative_url


# ----------------- GoEasy API 封装 -----------------
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:
        r = requests.post(url, headers=headers, json=body, timeout=10)
        if r.status_code == 200:
            logger.info(f"订阅成功：用户 {user_ids} -> 群 {group_ids}")
            return True
        logger.error(f"订阅失败：{r.status_code} {r.text}")
        return False
    except Exception as e:
        logger.exception("订阅异常")
        return False


def send_group_message(
    appkey, secret, group_id, sender_id, sender_name, sender_avatar,
    message_text='', custom_payload=None, group_name='', order_id=''
):
    """
    通过 GoEasy REST API 发送群消息。
    message_text: 普通文本内容
    custom_payload: 自定义消息体（如订单卡片），此时 type 设为 'order'
    """
    url = 'https://rest-hangzhou.goeasy.io/v2/im/message'
    to_data = {
        "name": group_name or group_id,
        "avatar": sender_avatar or '',
        "orderId": order_id,
    }
    msg_type = 'order' if custom_payload else 'text'
    payload = custom_payload if custom_payload else message_text

    body = {
        "appkey": appkey,
        "senderId": sender_id,
        "senderData": {"avatar": sender_avatar, "name": sender_name},
        "to": {"type": "group", "id": group_id, "data": to_data},
        "type": msg_type,
        "payload": payload
    }
    headers = {"Content-Type": "application/json"}
    if secret:
        headers["Authorization"] = f"Bearer {secret}"

    for attempt in range(3):  # 最多重试3次
        try:
            r = requests.post(url, headers=headers, json=body, timeout=10)
            if r.status_code == 200:
                logger.info(f"消息发送成功：sender={sender_id}, group={group_id}, type={msg_type}")
                return True
            logger.warning(f"消息发送失败 (尝试 {attempt+1}/3)：状态码 {r.status_code}, 响应 {r.text}")
        except Exception as e:
            logger.warning(f"消息发送异常 (尝试 {attempt+1}/3)：{e}")
        if attempt < 2:
            time.sleep(1)
    logger.error(f"消息最终发送失败：sender={sender_id}, group={group_id}")
    return False


# ----------------- 权限校验 -----------------
def check_user_permission(identity_type, uid, order):
    """验证用户身份、账号状态、以及是否属于该订单"""
    try:
        user = User.query.select_related('DashouProfile').get(UserUID=uid)
    except User.DoesNotExist:
        return False, '用户不存在'

    if identity_type == 'PlayerID':
        try:
            dashou = user.DashouProfile
            if dashou.zhanghaozhuangtai != 1 :
                return False, '打手账号已被封禁或状态异常'
        except UserDashou.DoesNotExist:
            return False, '该用户不是打手'
        if order.PlayerID != uid:
            # 组队队友也可进订单组队群
            try:
                from orders.models import TeamMember, TeamRecruit
                in_team = TeamMember.query.filter(
                    order_id=order.OrderID,
                    user_uid=uid,
                    join_status=TeamMember.JOIN_ACTIVE,
                ).exists()
                recruit_ok = TeamRecruit.query.filter(
                    order_id=order.OrderID,
                    status__in=[TeamRecruit.STATUS_RECRUITING, TeamRecruit.STATUS_LOCKED],
                ).exists()
                if not (in_team and recruit_ok):
                    return False, '你不是该订单的接单打手'
            except Exception:
                return False, '你不是该订单的接单打手'

    elif identity_type == 'shangjia':
        try:
            shop = UserShangjia.query.get(user=user)
            if shop.zhuangtai != 1:
                return False, '商家账号已被禁用'
        except UserShangjia.DoesNotExist:
            return False, '该用户不是商家'
        try:
            if order.shangjia_kuozhan.MerchantID != uid:
                return False, '你不是该订单的发布商家'
        except MerchantOrderExt.DoesNotExist:
            return False, '订单缺少商家信息'

    elif identity_type == 'boss':
        try:
            UserBoss.query.get(user=user)  # 老板暂无封禁字段，仅需存在
        except UserBoss.DoesNotExist:
            return False, '该用户不是老板'
        try:
            if order.pingtai_kuozhan.BossID != uid:
                return False, '你不是该订单的老板'
        except PlatformOrderExt.DoesNotExist:
            return False, '订单缺少平台信息'

    else:
        return False, '不支持的身份类型'
    return True, ''


# ----------------- 主视图 -----------------


class DaiLiQunLiaoXiaoXiView(APIView):
    """
    代理发送群聊消息
    """
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        # ===== 1. 参数解析 =====
        order_id = request.data.get('orderId')
        identity_type = request.data.get('identityType')  # dashou / PlayerID / shangjia / boss
        sender_name = request.data.get('senderName', '')
        sender_avatar_raw = request.data.get('senderAvatar', '')
        message_type = request.data.get('messageType', 'text')
        message_text = request.data.get('text', '')
        order_payload = request.data.get('orderPayload', None)

        if identity_type == 'dashou':
            identity_type = 'PlayerID'

        logger.info(f"[群聊代理] 收到请求: orderId={order_id}, identityType={identity_type}, "
                    f"messageType={message_type}, text={message_text[:20]}...")

        if not order_id or not identity_type:
            return Response({'code': 400, 'msg': '缺少 orderId 或 identityType'})
        if identity_type not in ('PlayerID', 'shangjia', 'boss'):
            return Response({'code': 400, 'msg': 'identityType 无效'})

        # ===== 2. 构造 senderId =====
        uid = request.user.UserUID
        prefix_map = {'PlayerID': 'Ds', 'shangjia': 'Sj', 'boss': 'Boss'}
        sender_id = prefix_map[identity_type] + uid
        logger.info(f"[群聊代理] 登录用户 UserID={uid}, 构造 senderId={sender_id}")

        # ===== 3. 查询订单 =====
        try:
            order = Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=order_id)
        except Order.DoesNotExist:
            logger.warning(f"[群聊代理] 订单 {order_id} 不存在")
            return Response({'code': 404, 'msg': '订单不存在'})

        # ===== 4. 权限校验 =====
        valid, err_msg = check_user_permission(identity_type, uid, order)
        if not valid:
            logger.warning(f"[群聊代理] 权限校验失败: {err_msg}, uid={uid}, identity={identity_type}")
            return Response({'code': 403, 'msg': err_msg})

        # ===== 5. 我方 GoEasy 配置 =====
        self_appkey = get_self_goeasy_appkey()
        self_secret = get_self_goeasy_secret()
        if not self_appkey:
            logger.error("[群聊代理] 我方 GoEasy AppKey 未配置")
            return Response({'code': 500, 'msg': '系统配置错误(APPKEY)'})

        # ===== 6. 有组队用 group_{订单}，否则配对群 =====
        real_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 f"订单{order.OrderID}"
        sender_avatar = full_avatar(sender_avatar_raw) if sender_avatar_raw else full_avatar('')

        # ===== 7. 订阅发送者到群 =====
        if not subscribe_users_to_group([sender_id], [real_group_id], self_appkey, self_secret):
            logger.error("[群聊代理] 订阅群组失败")
            return Response({'code': 500, 'msg': '订阅群组失败'})

        custom_payload = order_payload if message_type == 'order' else None
        text_content = message_text

        # ---------- 向我方群发送消息 ----------
        local_ok = send_group_message(
            appkey=self_appkey,
            secret=self_secret,
            group_id=real_group_id,
            sender_id=sender_id,
            sender_name=sender_name,
            sender_avatar=sender_avatar,
            message_text=text_content,
            custom_payload=custom_payload,
            group_name=group_name,
            order_id=order.OrderID,
        )
        if not local_ok:
            return Response({'code': 500, 'msg': '消息发送失败'})

        return Response({'code': 200, 'msg': '发送成功'})



class ShangjiaLianjieLiuYanZhuanFaView(APIView):
    """
    商家链接留言转发接口
    路径：POST /dingdan/sjljlbxxzf
    固定以 B{商家ID} 身份发送群消息。
    """
    permission_classes = []

    def post(self, request):
        token = request.data.get('token', '').strip()
        dingdan_id = str(request.data.get('dingdan_id') or request.data.get('dingdanId') or '').strip()
        text = (request.data.get('text') or '').strip()

        if not text or (not token and not dingdan_id):
            return Response({'code': 400, 'msg': '缺少参数'})

        if token:
            try:
                lianjie = ShangjiaLianjie.query.get(LinkToken=token)
            except ShangjiaLianjie.DoesNotExist:
                return Response({'code': 404, 'msg': '链接不存在或已失效'})
        else:
            try:
                lianjie = ShangjiaLianjie.query.get(OrderID=dingdan_id)
            except ShangjiaLianjie.DoesNotExist:
                return Response({'code': 404, 'msg': '订单链接不存在或已失效'})

        if not lianjie.OrderID:
            return Response({'code': 400, 'msg': '链接缺少订单ID'})

        try:
            order = Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=lianjie.OrderID)
        except Order.DoesNotExist:
            return Response({'code': 500, 'msg': '订单数据异常'})

        shangjia_uid = lianjie.UserID
        sender_id = f"B{shangjia_uid}"
        sender_name = "老板"
        sender_avatar = ''

        appkey = get_self_goeasy_appkey()
        secret = get_self_goeasy_secret()
        if not appkey:
            return Response({'code': 500, 'msg': '系统配置错误(APPKEY)'})

        group_id = resolve_pair_group_id(order) or f"group_{order.OrderID}"
        group_name = (order.Description[:20] + '…') if order.Description and len(order.Description) > 20 else f"订单{order.OrderID}"

        if not _subscribe_users_to_group([sender_id], [group_id], appkey, secret):
            return Response({'code': 500, 'msg': '订阅群组失败'})

        local_ok = _send_group_message(
            appkey=appkey,
            secret=secret,
            group_id=group_id,
            sender_id=sender_id,
            sender_name=sender_name,
            sender_avatar=sender_avatar,
            message_text=text,
            custom_payload=None,
            group_name=group_name,
            order_id=order.OrderID,
        )
        if not local_ok:
            return Response({'code': 500, 'msg': '消息发送失败'})

        return Response({'code': 200, 'msg': '发送成功'})


class LianTongDuiHuaZhunBeiView(APIView):
    """进入订单群聊前准备：返回配对 groupId 及双方资料，并订阅 GoEasy 群（不影响抢单校验）"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    IDENTITY_MAP = {
        'dashou': 'PlayerID',
        'shangjia': 'shangjia',
        'normal': 'boss',
        'boss': 'boss',
    }

    def post(self, request):
        dingdan_id = request.data.get('dingdan_id') or request.data.get('orderId')
        identity_type = request.data.get('identityType') or ''
        if not dingdan_id:
            return Response({'code': 400, 'msg': '缺少 dingdan_id'})

        backend_identity = self.IDENTITY_MAP.get(identity_type, identity_type)
        if backend_identity not in ('PlayerID', 'shangjia', 'boss'):
            return Response({'code': 400, 'msg': 'identityType 无效'})

        uid = request.user.UserUID
        try:
            order = Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=dingdan_id)
        except Order.DoesNotExist:
            return Response({'code': 404, 'msg': '订单不存在'})

        valid, err_msg = check_user_permission(backend_identity, uid, order)
        if not valid:
            return Response({'code': 403, 'msg': err_msg})

        if backend_identity == 'PlayerID' and not order.PlayerID:
            return Response({'code': 400, 'msg': '订单尚未接单，暂无法进入群聊'})

        data, subscribed = prepare_order_group_chat(order, backend_identity, uid, subscribe=True)
        if not subscribed:
            logger.warning(f'ltdhzb 订阅群失败 order={dingdan_id} uid={uid}')

        return Response({'code': 0, 'msg': 'ok', 'data': data})


class LianTongPeiDuiDingDanLieBiaoView(APIView):
    """聊天页：获取打手与商家/老板之间的历史订单列表（可搜索）"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    IDENTITY_MAP = {
        'dashou': 'PlayerID',
        'shangjia': 'shangjia',
        'normal': 'boss',
        'boss': 'boss',
    }

    def post(self, request):
        group_id = request.data.get('groupId') or request.data.get('group_id')
        dingdan_id = request.data.get('dingdan_id') or request.data.get('orderId')
        keyword = (request.data.get('keyword') or '').strip()
        identity_type = request.data.get('identityType') or ''
        backend_identity = self.IDENTITY_MAP.get(identity_type, identity_type)
        if backend_identity not in ('PlayerID', 'shangjia', 'boss'):
            return Response({'code': 400, 'msg': 'identityType 无效'})

        dashou_uid, partner_uid, partner_role = parse_pair_from_group_id(group_id)
        if not dashou_uid and dingdan_id:
            try:
                order = Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=dingdan_id)
            except Order.DoesNotExist:
                return Response({'code': 404, 'msg': '订单不存在'})
            dashou_uid, partner_uid, partner_role = resolve_pair_from_order(order)

        if not dashou_uid or not partner_uid:
            return Response({'code': 400, 'msg': '无法解析配对信息，请确认订单已接单'})

        uid = request.user.UserUID
        valid, err_msg = check_pair_chat_permission(backend_identity, uid, dashou_uid, partner_uid, partner_role)
        if not valid:
            return Response({'code': 403, 'msg': err_msg})

        orders = query_pair_orders(dashou_uid, partner_uid, partner_role, keyword=keyword, limit=40)
        latest = orders[0] if orders else None
        return Response({'code': 0, 'msg': 'ok', 'data': {'list': orders, 'latest': latest}})


class LianTongDingDanZhuangTaiView(APIView):
    """聊天页：刷新单个订单状态"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    IDENTITY_MAP = LianTongPeiDuiDingDanLieBiaoView.IDENTITY_MAP

    def post(self, request):
        dingdan_id = request.data.get('dingdan_id') or request.data.get('orderId')
        identity_type = request.data.get('identityType') or ''
        if not dingdan_id:
            return Response({'code': 400, 'msg': '缺少 dingdan_id'})

        backend_identity = self.IDENTITY_MAP.get(identity_type, identity_type)
        if backend_identity not in ('PlayerID', 'shangjia', 'boss'):
            return Response({'code': 400, 'msg': 'identityType 无效'})

        try:
            order = Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(OrderID=dingdan_id)
        except Order.DoesNotExist:
            return Response({'code': 404, 'msg': '订单不存在'})

        valid, err_msg = check_user_permission(backend_identity, request.user.UserUID, order)
        if not valid:
            return Response({'code': 403, 'msg': err_msg})

        data = order_to_chat_dict(order)
        return Response({'code': 0, 'msg': 'ok', 'data': data})


class LianTongDingDanZhuangTaiPiLiangView(APIView):
    """消息列表：批量刷新订单状态"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request):
        order_ids = request.data.get('order_ids') or []
        if not isinstance(order_ids, list):
            return Response({'code': 400, 'msg': 'order_ids 格式错误'})

        uid = request.user.UserUID
        # 批量查询订单，避免循环内 N+1
        oids = [str(oid).strip() for oid in order_ids[:20] if str(oid).strip()]
        orders_map = {
            o.OrderID: o
            for o in Order.query.select_related('pingtai_kuozhan', 'shangjia_kuozhan').filter(OrderID__in=oids)
        }
        result = {}
        for oid in oids:
            order = orders_map.get(oid)
            if not order:
                continue
            for identity in ('PlayerID', 'shangjia', 'boss'):
                valid, _ = check_user_permission(identity, uid, order)
                if valid:
                    d = order_to_chat_dict(order)
                    result[oid] = {
                        'jieshao': d['jieshao'],
                        # 聊天列表不回传订单价格
                        'jine': '',
                        'zhuangtai': d['zhuangtai'],
                        'zhuangtaiText': d['zhuangtaiText'],
                    }
                    break
        return Response({'code': 0, 'msg': 'ok', 'data': result})


