import io
import os
import re
import time
import random
import secrets
import hashlib
import threading
import urllib.parse
from decimal import Decimal, InvalidOperation

from django.conf import settings
from django.db import transaction, connection
from django.db.models import Q, F, Max, Prefetch
from gvsdsdk.fluent import db, func, FQ
from django.core.cache import cache
from django.core.paginator import Paginator
from django.utils import timezone

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.parsers import JSONParser, MultiPartParser, FormParser
from rest_framework.throttling import AnonRateThrottle, SimpleRateThrottle

from utils.oss_utils import upload_to_oss, delete_from_oss, validate_image
from utils.weixin_broadcast import WeixinBroadcastSender
from utils.weixin_token import get_weixin_mini_access_token, is_weixin_token_invalid
# from utils.ip_security import *
from utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode

from backend.utils import update_shangjia_daily
from utils.chat_utils import subscribe_merchant_link_chat
from utils.pdd_order_validator import validate_pdd_order_id, validate_cn_mobile

from ..models import (
    Gonggao, Lunbo, Tupianpeizhi, Qunpeizhi,
    ShangjiaMoban, ShangjiaLianjie, PopupPage, PopupConfig, WithdrawConfig,
    MiniappScriptScene, MiniappScriptAutoReply,
)

from users.models import (
    AdminProfile, UserDashou, UserBoss,
    UserShangjia, UserGuanshi, UserZuzhang
)
from users.business_models import User

from orders.models import CommissionRate, Order, MerchantOrderExt
from orders.notice_tasks import dingdan_guangbo

from rank.models import Chenghao, DingdanBiaoqian

from products.models import ShangpinLeixing, Huiyuangoumai

from ..serializers import PopupConfigSerializer
import traceback
import requests

import logging
logger = logging.getLogger(__name__)

class ShangjiaMobanListView(APIView):
    """
    商家订单模板列表接口
    POST /peizhi/sjddmblb
    权限: JWT认证
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            user = request.user
            yonghu_id = user.UserUID

            leixing_id = request.data.get('shangpinTypeId')
            if not leixing_id:
                return Response({'code': 400, 'msg': '商品类型ID不能为空', 'data': {}}, status=400)

            get_type = int(request.data.get('getType', 2))
            page = int(request.data.get('page', 1))
            page_size = int(request.data.get('pageSize', 50))

            keyword = request.data.get('keyword', '')
            min_price = request.data.get('minPrice', '')
            label_id = request.data.get('labelId', None)
            if label_id is not None:
                try:
                    label_id = int(label_id)
                except (ValueError, TypeError):
                    label_id = None

            query = Q(UserID=yonghu_id, ProductTypeID=leixing_id)

            if get_type == 1:  # 搜索模式
                if keyword:
                    keyword = str(keyword).strip()
                    try:
                        mid = int(keyword)
                        query &= Q(id=mid) | Q(TemplateDesc__icontains=keyword)
                    except ValueError:
                        query &= Q(TemplateDesc__icontains=keyword)
                if min_price:
                    try:
                        query &= Q(Price__gte=Decimal(str(min_price)))
                    except:
                        pass
                if label_id:
                    query &= Q(TitleID=label_id)

                mobans = ShangjiaMoban.query.filter(query).order_by('-id')
                formatted = []
                for moban in mobans:
                    texiao_json = ''
                    label_name = ''
                    if moban.TitleID:
                        try:
                            ch = Chenghao.query.get(id=moban.TitleID)
                            label_name = ch.mingcheng
                            texiao_json = ch.texiao_miaoshu or ''
                        except Chenghao.DoesNotExist:
                            pass
                    formatted.append({
                        'mobanId': moban.id,
                        'shangpinTypeId': moban.ProductTypeID,
                        'jieshao': moban.TemplateDesc,
                        'jiage': str(moban.Price),
                        'fabushuliang': moban.PublishedCount,
                        'commissionEnabled': moban.CommissionGrabEnabled,
                        'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
                        'labelId': moban.TitleID,
                        'labelName': label_name,
                        'texiaoJson': texiao_json,
                        'createTime': moban.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if moban.CreateTime else ''
                    })
                return Response({'code': 200, 'msg': '搜索成功', 'data': {'list': formatted, 'total': len(formatted), 'hasMore': False}})

            # 分页模式
            queryset = ShangjiaMoban.query.filter(query).order_by('-id')
            paginator = Paginator(queryset, page_size)
            if page < 1 or page > paginator.num_pages:
                return Response({'code': 400, 'msg': '页码超出范围', 'data': {}}, status=400)

            current_page = paginator.page(page)
            # 批量预取所有称号，避免循环内 N+1
            _mobans_list = list(current_page.object_list)
            _title_ids = [m.TitleID for m in _mobans_list if m.TitleID]
            _ch_map = {
                ch.id: ch
                for ch in Chenghao.query.filter(id__in=_title_ids).only('id', 'mingcheng', 'texiao_miaoshu')
            } if _title_ids else {}
            formatted = []
            for moban in _mobans_list:
                texiao_json = ''
                label_name = ''
                ch = _ch_map.get(moban.TitleID)
                if ch:
                    label_name = ch.mingcheng
                    texiao_json = ch.texiao_miaoshu or ''
                formatted.append({
                    'mobanId': moban.id,
                    'shangpinTypeId': moban.ProductTypeID,
                    'jieshao': moban.TemplateDesc,
                    'jiage': str(moban.Price),
                    'fabushuliang': moban.PublishedCount,
                    'commissionEnabled': moban.CommissionGrabEnabled,
                    'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
                    'labelId': moban.TitleID,
                    'labelName': label_name,
                    'texiaoJson': texiao_json,
                    'createTime': moban.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if moban.CreateTime else ''
                })

            has_more = current_page.has_next()
            if len(formatted) < page_size:
                has_more = False

            return Response({
                'code': 200,
                'msg': '获取成功',
                'data': {
                    'list': formatted,
                    'total': paginator.count,
                    'hasMore': has_more,
                    'currentPage': page,
                    'pageSize': page_size,
                    'totalPages': paginator.num_pages
                }
            })

        except Exception as e:
            logger.error(f"获取模板列表失败: {str(e)}", exc_info=True)
            return Response({'code': 500, 'msg': '服务器内部错误', 'data': {}}, status=500)





class ShangjiaTianjiaMobanView(APIView):
    """
    商家添加订单模板接口
    POST /peizhi/sjtjddmb
    权限: JWT认证
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            # 1. 获取当前商家用户ID
            user = request.user
            yonghu_id = user.UserUID

            # 2. 接收并清洗参数，避免类型错误
            leixing_id = request.data.get('shangpinTypeId')
            jieshao = request.data.get('jieshao', '').strip() if request.data.get('jieshao') else ''
            jiage = request.data.get('jiage', '')
            # 佣金相关
            commission_enabled = request.data.get('commissionEnabled', False)
            commission_value = request.data.get('commissionValue', None)
            # 标签ID（称号ID）
            label_id = request.data.get('labelId', None)

            # 3. 必填验证
            if not leixing_id or not jieshao or not jiage:
                logger.warning(f"参数缺失 - leixing_id:{leixing_id}, jieshao:{jieshao}, jiage:{jiage}")
                return Response({
                    'code': 400,
                    'msg': '缺少必填字段（订单类型、介绍、价格）',
                    'data': {}
                }, status=400)

            # 4. 价格格式验证
            try:
                jiage_decimal = Decimal(str(jiage))
                if jiage_decimal <= 0:
                    return Response({'code': 400, 'msg': '价格必须大于0', 'data': {}}, status=400)
                if jiage_decimal > 10000:
                    return Response({'code': 400, 'msg': '价格不能超过10000元', 'data': {}}, status=400)
            except (InvalidOperation, ValueError, TypeError):
                return Response({'code': 400, 'msg': '价格格式错误', 'data': {}}, status=400)

            # 5. 介绍长度验证
            if len(jieshao) > 100:
                return Response({'code': 400, 'msg': '订单介绍不能超过100字', 'data': {}}, status=400)

            # 6. 佣金验证（若启用）
            CommissionGrabEnabled = False
            CommissionPrice = None
            if commission_enabled:
                CommissionGrabEnabled = True
                if not commission_value:
                    return Response({'code': 400, 'msg': '开启佣金时，佣金金额不能为空', 'data': {}}, status=400)
                try:
                    comm_decimal = Decimal(str(commission_value))
                    if comm_decimal <= 0:
                        return Response({'code': 400, 'msg': '佣金必须大于0', 'data': {}}, status=400)
                    CommissionPrice = comm_decimal
                except (InvalidOperation, ValueError, TypeError):
                    return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400)

            # 7. 标签ID清洗（前端可能传数字或字符串）
            cleaned_label_id = None
            if label_id is not None and str(label_id).strip():
                try:
                    cleaned_label_id = int(label_id)
                except (ValueError, TypeError):
                    return Response({'code': 400, 'msg': '标签ID格式错误', 'data': {}}, status=400)

            # 8. 验证商品类型是否存在且可用
            try:
                shangpin_obj = ShangpinLeixing.query.get(
                    id=leixing_id,
                    shenhezhuangtai=1        # 审核通过
                )
            except ShangpinLeixing.DoesNotExist:
                return Response({'code': 404, 'msg': '商品类型不存在或已禁用', 'data': {}}, status=404)

            # 9. 检查同一用户、同一类型下是否已存在相同介绍的模板
            if ShangjiaMoban.query.filter(
                UserID=yonghu_id,
                ProductTypeID=leixing_id,
                TemplateDesc=jieshao
            ).exists():
                return Response({'code': 400, 'msg': '已存在相同介绍的模板', 'data': {}}, status=400)

            # 10. 执行数据库创建（事务）
            with transaction.atomic():
                moban = ShangjiaMoban.query.create(
                    UserID=yonghu_id,
                    ProductTypeID=leixing_id,
                    TemplateDesc=jieshao,
                    Price=jiage_decimal,
                    PublishedCount=0,
                    CommissionGrabEnabled=CommissionGrabEnabled,
                    CommissionPrice=CommissionPrice,
                    TitleID=cleaned_label_id
                )

            # 11. 返回成功数据（字段与前端对齐）
            return Response({
                'code': 200,
                'msg': '模板创建成功',
                'data': {
                    'mobanId': moban.id,
                    'shangpinTypeId': leixing_id,
                    'jieshao': moban.TemplateDesc,
                    'jiage': str(moban.Price),
                    'fabushuliang': moban.PublishedCount,
                    'createTime': moban.CreateTime.strftime('%Y-%m-%d %H:%M:%S'),
                    'commissionEnabled': moban.CommissionGrabEnabled,
                    'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice is not None else None,
                    'labelId': moban.TitleID
                }
            })

        except Exception as e:
            # 打印完整错误堆栈到日志
            logger.error(f"添加模板失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'msg': '服务器内部错误，添加模板失败，请联系管理员',
                'data': {}
            }, status=500)




class ShangjiaShanchuMobanView(APIView):
    """
    删除模板
    POST /peizhi/sjddmbsc
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            user = request.user
            yonghu_id = user.UserUID

            moban_id = request.data.get('mobanId')
            leixing_id = request.data.get('shangpinTypeId')

            if not all([moban_id, leixing_id]):
                return Response({'code': 400, 'msg': '参数缺失', 'data': {}}, status=400)

            try:
                moban = ShangjiaMoban.query.get(id=moban_id, UserID=yonghu_id, ProductTypeID=leixing_id)
            except ShangjiaMoban.DoesNotExist:
                return Response({'code': 404, 'msg': '模板不存在', 'data': {}}, status=404)

            # 强制硬删除
            moban.delete()

            return Response({'code': 200, 'msg': '删除成功', 'data': {'mobanId': moban_id, 'shangpinTypeId': leixing_id}})
        except Exception as e:
            logger.error(f"删除模板失败: {str(e)}", exc_info=True)
            return Response({'code': 500, 'msg': '服务器内部错误', 'data': {}}, status=500)






class ShangjiaGengxinMobanView(APIView):
    """
    商家更新订单模板接口
    POST /peizhi/sjddmbgx
    权限: JWT认证
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            user = request.user
            yonghu_id = user.UserUID

            moban_id = request.data.get('mobanId')
            leixing_id = request.data.get('shangpinTypeId')
            new_jieshao = request.data.get('jieshao', '').strip()
            new_jiage = request.data.get('jiage', '').strip()
            # 新增字段
            commission_enabled = request.data.get('commissionEnabled')
            commission_value = request.data.get('commissionValue')
            label_id = request.data.get('labelId')

            if not all([moban_id, leixing_id]):
                return Response({'code': 400, 'msg': '模板ID和商品类型ID不能为空', 'data': {}}, status=400)

            # 查询模板
            try:
                moban = ShangjiaMoban.query.get(
                    id=moban_id,
                    UserID=yonghu_id,
                    ProductTypeID=leixing_id
                )
            except ShangjiaMoban.DoesNotExist:
                return Response({'code': 404, 'msg': '模板不存在或无权修改', 'data': {}}, status=404)

            update_fields = []

            # 修改介绍
            if new_jieshao:
                if len(new_jieshao) > 100:
                    return Response({'code': 400, 'msg': '订单介绍不能超过100字', 'data': {}}, status=400)
                if new_jieshao != moban.TemplateDesc:
                    moban.TemplateDesc = new_jieshao
                    update_fields.append('TemplateDesc')

            # 修改价格
            if new_jiage:
                try:
                    jiage_decimal = Decimal(new_jiage)
                    if jiage_decimal <= 0 or jiage_decimal > 10000:
                        return Response({'code': 400, 'msg': '价格必须在0.1-10000元之间', 'data': {}}, status=400)
                    if jiage_decimal != moban.Price:
                        moban.Price = jiage_decimal
                        update_fields.append('Price')
                except (InvalidOperation, ValueError, TypeError):
                    return Response({'code': 400, 'msg': '价格格式错误', 'data': {}}, status=400)

            # 修改标签
            if label_id is not None:  # 允许传空字符串或不传，传0表示清空
                new_label = int(label_id) if label_id else None
                if new_label != moban.TitleID:
                    moban.TitleID = new_label
                    update_fields.append('TitleID')

            # 修改佣金设置
            if commission_enabled is not None:
                enabled = bool(commission_enabled)
                if enabled:
                    if not commission_value:
                        return Response({'code': 400, 'msg': '佣金价格不能为空', 'data': {}}, status=400)
                    try:
                        comm_decimal = Decimal(commission_value)
                        if comm_decimal < 0.1 or comm_decimal > 50:
                            return Response({'code': 400, 'msg': '佣金需在0.1-50元之间', 'data': {}}, status=400)
                        if moban.CommissionGrabEnabled != True or moban.CommissionPrice != comm_decimal:
                            moban.CommissionGrabEnabled = True
                            moban.CommissionPrice = comm_decimal
                            update_fields.extend(['CommissionGrabEnabled', 'CommissionPrice'])
                    except (InvalidOperation, ValueError, TypeError):
                        return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400)
                else:
                    if moban.CommissionGrabEnabled != False or moban.CommissionPrice is not None:
                        moban.CommissionGrabEnabled = False
                        moban.CommissionPrice = None
                        update_fields.extend(['CommissionGrabEnabled', 'CommissionPrice'])

            if not update_fields:
                return Response({'code': 400, 'msg': '没有修改内容', 'data': {}}, status=400)

            # 检查介绍唯一性
            if 'TemplateDesc' in update_fields:
                if ShangjiaMoban.query.filter(
                    UserID=yonghu_id,
                    ProductTypeID=leixing_id,
                    TemplateDesc=moban.TemplateDesc
                ).exclude(id=moban_id).exists():
                    return Response({'code': 400, 'msg': '已存在相同介绍的模板', 'data': {}}, status=400)

            with transaction.atomic():
                moban.save(update_fields=update_fields)

            # 返回最新数据
            return Response({
                'code': 200,
                'msg': '模板修改成功',
                'data': {
                    'mobanId': moban.id,
                    'shangpinTypeId': moban.ProductTypeID,
                    'jieshao': moban.TemplateDesc,
                    'jiage': str(moban.Price),
                    'fabushuliang': moban.PublishedCount,
                    'commissionEnabled': moban.CommissionGrabEnabled,
                    'commissionValue': str(moban.CommissionPrice) if moban.CommissionPrice else None,
                    'labelId': moban.TitleID,
                    'updateTime': moban.UpdateTime.strftime('%Y-%m-%d %H:%M:%S')
                }
            })

        except Exception as e:
            logger = logging.getLogger(__name__)
            logger.error(f"修改商家模板失败: {str(e)}", exc_info=True)
            return Response({'code': 500, 'msg': '服务器内部错误', 'data': {}}, status=500)





