from rest_framework import viewsets, status, mixins, parsers, filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import serializers, permissions
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.utils import timezone
from django.db import models
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes

from shop.models import WeChatUser, Order
from shop.views import get_wechat_pay_client
from .models import Activity, ActivitySignup, Topic, Reply, TopicMedia, Announcement
from .serializers import ActivitySerializer, ActivitySignupSerializer, TopicSerializer, ReplySerializer, TopicMediaSerializer, AnnouncementSerializer, AdminActivitySerializer, AdminTopicSerializer
from .utils import get_current_wechat_user
from .permissions import IsAuthorOrReadOnly

class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
    """
    社区活动接口
    """
    queryset = Activity.objects.filter(is_active=True).order_by('-created_at')
    serializer_class = ActivitySerializer

    def get_queryset(self):
        qs = super().get_queryset()
        # list 接口过滤 is_visible=True
        if self.action == 'list':
            qs = qs.filter(is_visible=True)
        return qs

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        
        # Sync status for current user
        user = get_current_wechat_user(request)
        if user:
            # Use filter to avoid exception if multiple exist (though unique_together constraint exists)
            signup = instance.signups.filter(user=user).exclude(status='cancelled').first()
            if signup:
                has_changed = signup.check_payment_status()
                if has_changed:
                    print(f"DEBUG: Synced signup status for user {user.id} activity {instance.id}")

        serializer = self.get_serializer(instance)
        # Debug print to verify data
        print(f"DEBUG: Activity {instance.title} current_signups: {instance.current_signups}")
        return Response(serializer.data)

    @extend_schema(summary="报名活动")
    @action(detail=True, methods=['post'])
    def signup(self, request, pk=None):
        user = get_current_wechat_user(request)
        if not user:
            return Response({'error': '请先登录'}, status=401)
        
        activity = self.get_object()
        
        # 1. Check confirmed signup
        if ActivitySignup.objects.filter(activity=activity, user=user, status='confirmed').exists():
            return Response({'error': '您已报名该活动'}, status=400)
            
        # 2. Get pending signup (for retry)
        pending_signup = ActivitySignup.objects.filter(activity=activity, user=user, status='pending').first()
        
        # 3. Check limit (exclude cancelled, exclude current pending)
        query = activity.signups.exclude(status='cancelled')
        if pending_signup:
             query = query.exclude(id=pending_signup.id)
             
        if query.count() >= activity.max_participants:
             return Response({'error': '活动名额已满'}, status=400)
        
        # Get signup info
        signup_info = request.data.get('signup_info', {})
        
        # Validate signup info
        effective_config = activity.signup_form_config
        if not effective_config:
             effective_config = []
             if activity.ask_name:
                 effective_config.append({"name": "name", "label": "姓名", "type": "text", "required": True})
             if activity.ask_phone:
                 effective_config.append({"name": "phone", "label": "手机号", "type": "number", "required": True})
             if activity.ask_wechat:
                 effective_config.append({"name": "wechat", "label": "微信号", "type": "text", "required": True})
             if activity.ask_company:
                 effective_config.append({"name": "company", "label": "公司/机构", "type": "text", "required": False})

        if effective_config:
            required_fields = [f['name'] for f in effective_config if f.get('required')]
            for field in required_fields:
                val = signup_info.get(field)
                if val is None or (isinstance(val, str) and not val.strip()):
                     label = next((f['label'] for f in effective_config if f['name'] == field), field)
                     return Response({'error': f'请填写: {label}'}, status=400)

        # Handle Payment Logic
        if activity.is_paid and activity.price > 0:
            import time
            from wechatpayv3 import WeChatPayType
            
            # Create or Get Order
            order = None
            if pending_signup and pending_signup.order:
                # Reuse existing order if it's pending
                if pending_signup.order.status == 'pending':
                    order = pending_signup.order
                    # Update contact info if needed
                    contact_name = signup_info.get('name') or signup_info.get('participant_name') or user.nickname or 'Activity User'
                    contact_phone = signup_info.get('phone') or user.phone_number or ''
                    if contact_name: order.customer_name = contact_name
                    if contact_phone: order.phone_number = contact_phone
                    
                    # Ensure activity is linked
                    if not order.activity:
                        order.activity = activity
                    
                    order.save()
            
            if not order:
                # Check independent pending order
                pending_order = Order.objects.filter(
                    wechat_user=user, 
                    activity=activity, 
                    status='pending'
                ).first()
                
                if pending_order:
                    order = pending_order
                    # Ensure shipping address is up-to-date
                    order.shipping_address = activity.location or '线下活动'
                    order.save()
                else:
                    contact_name = signup_info.get('name') or signup_info.get('participant_name') or user.nickname or 'Activity User'
                    contact_phone = signup_info.get('phone') or user.phone_number or ''
                    
                    order = Order.objects.create(
                        wechat_user=user,
                        activity=activity,
                        total_price=activity.price,
                        status='pending',
                        quantity=1,
                        customer_name=contact_name,
                        phone_number=contact_phone,
                        shipping_address=activity.location or '线下活动',
                    )

            # Generate Pay Code
            out_trade_no = f"ACT{activity.id}U{user.id}T{int(time.time())}"
            order.out_trade_no = out_trade_no
            order.save()
            
            wxpay, error_msg = get_wechat_pay_client(pay_type=WeChatPayType.NATIVE)
            if not wxpay:
                return Response({'error': f'支付配置错误: {error_msg}'}, status=500)
                
            code, message = wxpay.pay(
                description=f"报名活动: {activity.title}",
                out_trade_no=out_trade_no,
                amount={
                    'total': int(activity.price * 100),
                    'currency': 'CNY'
                },
                notify_url=wxpay._notify_url,
                attach=f'{{"type":"activity","activity_id":{activity.id}}}'
            )
            
            import json
            result = json.loads(message)
            if code in range(200, 300):
                code_url = result.get('code_url')
                
                if pending_signup:
                    pending_signup.signup_info = signup_info
                    pending_signup.order = order
                    pending_signup.status = 'unpaid' # Explicitly set to unpaid
                    pending_signup.save()
                else:
                    ActivitySignup.objects.create(
                        activity=activity, 
                        user=user,
                        signup_info=signup_info,
                        status='unpaid',
                        order=order
                    )
                
                return Response({
                    'payment_required': True,
                    'code_url': code_url,
                    'order_id': order.id,
                    'price': activity.price,
                    'message': '请完成支付'
                }, status=200)
            else:
                 return Response({'error': '支付接口调用失败', 'detail': result}, status=500)

        # Free Activity Signup
        # Check auto_confirm
        status_val = 'confirmed' if activity.auto_confirm else 'pending'
        
        signup = ActivitySignup.objects.create(
            activity=activity, 
            user=user,
            signup_info=signup_info,
            status=status_val
        )

        # Send SMS for free activity signup (if confirmed)
        if status_val == 'confirmed':
             try:
                from shop.sms_utils import notify_user_activity_signup_success
                
                # Mock an order object for the SMS template
                # The template expects: customer_name, wechat_user, phone_number
                class MockOrder:
                    def __init__(self, user, signup_info):
                        # Ensure we get the name and phone from signup_info first
                        # signup_info keys might vary, let's try common ones
                        self.customer_name = signup_info.get('name') or signup_info.get('username') or user.nickname or "用户"
                        self.wechat_user = user
                        self.phone_number = signup_info.get('phone') or signup_info.get('mobile') or user.phone_number or ""
                
                mock_order = MockOrder(user, signup_info)
                
                # Check if we have a valid phone number before sending
                if mock_order.phone_number:
                    notify_user_activity_signup_success(mock_order, signup)
                else:
                    print(f"Skipping SMS for signup {signup.id}: No phone number found")
             except Exception as e:
                print(f"发送免费活动报名短信失败: {str(e)}")

        serializer = ActivitySignupSerializer(signup)
        return Response(serializer.data, status=201)

    @extend_schema(summary="我的报名记录")
    @action(detail=False, methods=['get'])
    def my_signups(self, request):
        user = get_current_wechat_user(request)
        if not user:
            return Response({'error': '请先登录'}, status=401)
        signups = ActivitySignup.objects.filter(user=user).order_by('-signup_time')
        
        # Sync payment status
        for signup in signups:
            signup.check_payment_status()
            
        serializer = ActivitySignupSerializer(signups, many=True)
        return Response(serializer.data)

class TopicViewSet(viewsets.ModelViewSet):
    """
    技术论坛帖子接口
    """
    queryset = Topic.objects.all()
    serializer_class = TopicSerializer
    permission_classes = [IsAuthorOrReadOnly]
    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['title', 'content']
    filterset_fields = ['category', 'is_pinned']
    ordering_fields = ['created_at', 'view_count', 'order']
    ordering = ['-is_pinned', 'order', '-created_at']

    def get_queryset(self):
        qs = super().get_queryset()
        # 列表接口仅显示已发布的帖子
        if self.action == 'list':
            qs = qs.filter(status='published')
        return qs

    def perform_create(self, serializer):
        user = get_current_wechat_user(self.request)
        # Auth check is done in create or permission, but here we need user for save
        if user:
            # 如果关联了系统用户(user字段不为空)，则是管理员/内部人员，直接发布
            # 否则进入审核流程
            status = 'published' if user.user else 'pending'
            serializer.save(author=user, status=status)
    
    def create(self, request, *args, **kwargs):
        user = get_current_wechat_user(request)
        if not user:
            return Response({'error': '请先登录'}, status=401)
        return super().create(request, *args, **kwargs)

    @action(detail=True, methods=['post'], permission_classes=[permissions.AllowAny])
    def like(self, request, pk=None):
        obj = self.get_object()
        user = get_current_wechat_user(request)
        if not user:
             return Response({'error': '请先登录'}, status=401)
        
        if obj.likes.filter(id=user.id).exists():
            obj.likes.remove(user)
            liked = False
        else:
            obj.likes.add(user)
            liked = True
            
        return Response({'liked': liked, 'count': obj.likes.count()})

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.view_count += 1
        instance.save(update_fields=['view_count'])
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

class ReplyViewSet(viewsets.ModelViewSet):
    """
    帖子回复接口
    """
    queryset = Reply.objects.all()
    serializer_class = ReplySerializer
    permission_classes = [IsAuthorOrReadOnly]

    def perform_create(self, serializer):
        user = get_current_wechat_user(self.request)
        if user:
            serializer.save(author=user)

    def create(self, request, *args, **kwargs):
        user = get_current_wechat_user(request)
        if not user:
            return Response({'error': '请先登录'}, status=401)
        return super().create(request, *args, **kwargs)

    @action(detail=True, methods=['post'], permission_classes=[permissions.AllowAny])
    def like(self, request, pk=None):
        obj = self.get_object()
        user = get_current_wechat_user(request)
        if not user:
             return Response({'error': '请先登录'}, status=401)
        
        if obj.likes.filter(id=user.id).exists():
            obj.likes.remove(user)
            liked = False
        else:
            obj.likes.add(user)
            liked = True
            
        return Response({'liked': liked, 'count': obj.likes.count()})

import requests

class TopicMediaViewSet(viewsets.ViewSet):
    """
    论坛多媒体资源上传接口 (代理到外部OSS服务)
    """
    permission_classes = [] # 内部鉴权
    parser_classes = [parsers.MultiPartParser, parsers.FormParser]

    @extend_schema(summary="上传媒体文件 (返回URL用于Markdown)")
    def create(self, request, *args, **kwargs):
        user = get_current_wechat_user(request)
        if not user:
            return Response({'error': '请先登录'}, status=401)
            
        file_obj = request.FILES.get('file')
        if not file_obj:
            return Response({'error': '未提供文件'}, status=400)
            
        # 转发到外部 OSS 上传服务
        upload_url = "https://data.tangledup-ai.com/upload?folder=uploads%2Fmarket%2Fforum_image"
        files = {'file': (file_obj.name, file_obj, file_obj.content_type)}
        
        try:
            # 这里的 headers 不需要 Content-Type，requests 会自动设置 multipart/form-data
            response = requests.post(upload_url, files=files, timeout=30)
            
            if response.status_code == 200:
                data = response.json()
                if data.get('success'):
                    # Create TopicMedia record
                    media_type = 'image' if 'image' in file_obj.content_type else 'video'
                    media_obj = TopicMedia.objects.create(
                        file_url=data.get('file_url'),
                        media_type=media_type,
                        # topic will be associated later
                    )
                    
                    # 返回符合前端预期的格式
                    return Response({
                        'id': media_obj.id, # Return real DB ID
                        'file': media_obj.file_url,
                        'media_type': media_obj.media_type,
                        'created_at': media_obj.created_at
                    })
                else:
                     return Response({'error': '外部服务上传失败', 'detail': data}, status=400)
            else:
                return Response({'error': f'上传服务响应错误: {response.status_code}', 'detail': response.text}, status=502)
                
        except Exception as e:
            return Response({'error': str(e)}, status=500)

class AnnouncementViewSet(viewsets.ReadOnlyModelViewSet):
    """
    社区公告接口
    """
    queryset = Announcement.objects.all()
    serializer_class = AnnouncementSerializer
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        now = timezone.now()
        qs = Announcement.objects.filter(is_active=True)
        # Filter by start_time (if set, must be <= now)
        qs = qs.filter(models.Q(start_time__isnull=True) | models.Q(start_time__lte=now))
        # Filter by end_time (if set, must be >= now)
        qs = qs.filter(models.Q(end_time__isnull=True) | models.Q(end_time__gte=now))
        return qs.order_by('-is_pinned', '-priority', '-created_at')

class AdminPublishViewSet(viewsets.ViewSet):
    """
    管理员/API发布接口
    """
    permission_classes = [] 
    authentication_classes = []

    def check_api_key(self, request):
        key = request.headers.get('X-API-KEY') or request.query_params.get('apikey')
        if key != '123quant-speed':
            return False
        return True

    def get_admin_user_by_phone(self, phone):
        if not phone:
            return None
        # Find WeChatUser by phone
        user = WeChatUser.objects.filter(phone_number=phone).first()
        if not user:
            return None
        
        # Check if linked to a system user and has admin privileges (is_staff)
        if user.user and user.user.is_staff:
            return user
            
        return None

    @extend_schema(
        summary="API发布活动",
        request=AdminActivitySerializer,
        parameters=[
            OpenApiParameter(
                name='apikey', 
                description='API访问密钥', 
                required=True, 
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY
            ),
             OpenApiParameter(
                name='phone_number', 
                description='管理员手机号 (用于关联发布者)', 
                required=True, 
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY
            )
        ]
    )
    @action(detail=False, methods=['post'])
    def publish_activity(self, request):
        if not self.check_api_key(request):
            return Response({'error': 'Invalid API Key'}, status=403)
        
        phone = request.data.get('phone_number') or request.query_params.get('phone_number')
        user = self.get_admin_user_by_phone(phone)
        if not user:
             return Response({'error': 'Admin user not found with this phone number'}, status=404)
        
        data = request.data.copy()
        serializer = AdminActivitySerializer(data=data)
        if serializer.is_valid():
            activity = serializer.save(author=user)
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

    @extend_schema(
        summary="API发布帖子",
        request=AdminTopicSerializer,
        parameters=[
            OpenApiParameter(
                name='apikey', 
                description='API访问密钥', 
                required=True, 
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY
            ),
             OpenApiParameter(
                name='phone_number', 
                description='管理员手机号 (用于关联发布者)', 
                required=True, 
                type=OpenApiTypes.STR,
                location=OpenApiParameter.QUERY
            )
        ]
    )
    @action(detail=False, methods=['post'])
    def publish_topic(self, request):
        if not self.check_api_key(request):
            return Response({'error': 'Invalid API Key'}, status=403)

        phone = request.data.get('phone_number') or request.query_params.get('phone_number')
        user = self.get_admin_user_by_phone(phone)
        if not user:
             return Response({'error': 'Admin user not found with this phone number'}, status=404)

        data = request.data.copy()
        serializer = AdminTopicSerializer(data=data)
        if serializer.is_valid():
            # Only set status to published if not provided, otherwise respect the input
            status = data.get('status', 'published')
            topic = serializer.save(author=user, status=status)
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)
