from rest_framework import generics, permissions, status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django.shortcuts import get_object_or_404
from django.db.models import Q, Count, Sum, Value
from django.db.models.functions import Coalesce
from django.utils import timezone
from datetime import timedelta

from .models import Market, MarketVendor
from .serializers import (
    MarketListSerializer, MarketDetailSerializer, MarketVendorSerializer,
)


# --- Pagination ---

class MarketPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 50


class ProductPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 50


# --- Helpers ---

def get_market_or_404(slug):
    return get_object_or_404(Market, slug=slug, status='active')


def get_active_vendor_user_ids(market):
    return market.vendors.filter(status='active').values_list('vendor_id', flat=True)


# --- Public endpoints ---

class MarketListView(generics.ListAPIView):
    """GET / - List/search markets"""
    serializer_class = MarketListSerializer
    pagination_class = MarketPagination
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        qs = Market.objects.filter(status='active').select_related('created_by')
        search = self.request.query_params.get('search')
        category = self.request.query_params.get('category')
        county = self.request.query_params.get('county')

        if search:
            qs = qs.filter(Q(name__icontains=search) | Q(description__icontains=search))
        if category:
            qs = qs.filter(category=category)
        if county:
            qs = qs.filter(county=county)

        return qs

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            paginated = self.get_paginated_response(serializer.data)
            return Response({
                'success': True,
                'data': paginated.data['results'],
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        serializer = self.get_serializer(queryset, many=True)
        return Response({'success': True, 'data': serializer.data, 'count': len(serializer.data)})


class MarketDetailView(generics.RetrieveAPIView):
    """GET /<slug>/ - Market detail"""
    serializer_class = MarketDetailSerializer
    permission_classes = [permissions.AllowAny]
    lookup_field = 'slug'

    def get_queryset(self):
        return Market.objects.filter(status='active').select_related('created_by')

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response({'success': True, 'data': serializer.data})


class MarketVendorsView(generics.ListAPIView):
    """GET /<slug>/vendors/ - List market vendors"""
    serializer_class = MarketVendorSerializer
    pagination_class = MarketPagination
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        market = get_market_or_404(self.kwargs['slug'])
        return market.vendors.filter(status='active').select_related('vendor')

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            paginated = self.get_paginated_response(serializer.data)
            return Response({
                'success': True,
                'data': paginated.data['results'],
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        serializer = self.get_serializer(queryset, many=True)
        return Response({'success': True, 'data': serializer.data})


class MarketProductsView(APIView):
    """GET /<slug>/products/ - Products from market vendors"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, slug):
        from products.models import Product
        from promotions.utils import annotate_priority
        market = get_market_or_404(slug)
        vendor_user_ids = get_active_vendor_user_ids(market)

        qs = Product.objects.filter(
            vendor__user_id__in=vendor_user_ids,
            status='active',
        ).select_related('vendor', 'vendor__user').annotate(
            total_likes=Count('likes'),
        )
        qs = annotate_priority(qs, 'product').order_by('-priority', '-created_at')

        search = request.query_params.get('search')
        category = request.query_params.get('category')
        if search:
            qs = qs.filter(Q(name__icontains=search) | Q(description__icontains=search))
        if category:
            qs = qs.filter(category=category)

        paginator = ProductPagination()
        page = paginator.paginate_queryset(qs, request)

        data = []
        for p in (page if page is not None else qs[:50]):
            img_url = None
            if p.primary_image:
                img_url = request.build_absolute_uri(p.primary_image.url)
            vendor_name = ''
            try:
                vendor_name = p.vendor.shop_name
            except Exception:
                pass
            data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'name': p.name,
                'slug': p.slug,
                'price': str(p.price),
                'old_price': str(p.old_price) if p.old_price else None,
                'category': p.category,
                'primary_image': img_url,
                'likes_count': p.total_likes,
                'vendor_name': vendor_name,
                'vendor_slug': p.vendor.slug if p.vendor.slug else '',
                'is_sponsored': getattr(p, 'is_sponsored', False),
                'created_at': p.created_at.isoformat(),
            })

        if page is not None:
            paginated = paginator.get_paginated_response(data)
            return Response({
                'success': True,
                'data': data,
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        return Response({'success': True, 'data': data, 'count': len(data)})


class MarketServicesView(APIView):
    """GET /<slug>/services/ - Services from market vendors"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, slug):
        from services.models import Service
        from promotions.utils import annotate_priority
        market = get_market_or_404(slug)
        vendor_user_ids = get_active_vendor_user_ids(market)

        qs = Service.objects.filter(
            vendor__user_id__in=vendor_user_ids,
            status='active',
        ).select_related('vendor', 'vendor__user').annotate(
            total_likes=Count('likes'),
        )
        qs = annotate_priority(qs, 'service').order_by('-priority', '-created_at')

        search = request.query_params.get('search')
        category = request.query_params.get('category')
        if search:
            qs = qs.filter(Q(name__icontains=search) | Q(description__icontains=search))
        if category:
            qs = qs.filter(category=category)

        paginator = ProductPagination()
        page = paginator.paginate_queryset(qs, request)

        data = []
        for s in (page if page is not None else qs[:50]):
            img_url = None
            if s.image:
                img_url = request.build_absolute_uri(s.image.url)
            data.append({
                'id': s.id,
                'name': s.name,
                'slug': s.slug,
                'category': s.category,
                'description': s.description,
                'price_type': s.price_type,
                'price': str(s.price) if s.price else None,
                'max_price': str(s.max_price) if s.max_price else None,
                'image': img_url,
                'likes_count': s.total_likes,
                'vendor_name': s.vendor.shop_name,
                'vendor_slug': s.vendor.slug or '',
                'is_sponsored': getattr(s, 'is_sponsored', False),
                'created_at': s.created_at.isoformat(),
            })

        if page is not None:
            paginated = paginator.get_paginated_response(data)
            return Response({
                'success': True,
                'data': data,
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        return Response({'success': True, 'data': data, 'count': len(data)})


class MarketVideosView(APIView):
    """GET /<slug>/videos/ - Videos from market vendors"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, slug):
        from videos.models import VideoListing
        market = get_market_or_404(slug)
        vendor_user_ids = get_active_vendor_user_ids(market)

        qs = VideoListing.objects.filter(
            vendor_id__in=vendor_user_ids,
            is_active=True,
        ).select_related('vendor').order_by('-created_at')

        paginator = ProductPagination()
        page = paginator.paginate_queryset(qs, request)

        data = []
        for v in (page if page is not None else qs[:50]):
            thumb = None
            if v.thumbnail:
                thumb = request.build_absolute_uri(v.thumbnail.url)
            video_url = None
            if v.video:
                video_url = request.build_absolute_uri(v.video.url)
            data.append({
                'id': v.id,
                'uuid': str(v.uuid),
                'title': v.title,
                'slug': v.slug,
                'thumbnail': thumb,
                'video_url': video_url,
                'views_count': v.views_count,
                'likes_count': v.likes_count,
                'vendor_name': v.vendor.full_name,
                'created_at': v.created_at.isoformat(),
            })

        if page is not None:
            paginated = paginator.get_paginated_response(data)
            return Response({
                'success': True,
                'data': data,
                'count': paginated.data['count'],
                'next': paginated.data['next'],
                'previous': paginated.data['previous'],
            })
        return Response({'success': True, 'data': data, 'count': len(data)})


class MarketTrendingProductsView(APIView):
    """GET /<slug>/trending/ - Trending products (likes in 7 days)"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, slug):
        from products.models import Product
        from promotions.utils import annotate_priority
        market = get_market_or_404(slug)
        vendor_user_ids = get_active_vendor_user_ids(market)
        week_ago = timezone.now() - timedelta(days=7)

        qs = Product.objects.filter(
            vendor__user_id__in=vendor_user_ids,
            status='active',
        ).select_related('vendor', 'vendor__user').annotate(
            total_likes=Count('likes'),
        )
        qs = annotate_priority(qs, 'product').order_by('-priority', '-total_likes')[:20]

        data = []
        for p in qs:
            img_url = None
            if p.primary_image:
                img_url = request.build_absolute_uri(p.primary_image.url)
            vendor_name = ''
            try:
                vendor_name = p.vendor.shop_name
            except Exception:
                pass
            data.append({
                'id': p.id,
                'uuid': str(p.uuid),
                'name': p.name,
                'slug': p.slug,
                'price': str(p.price),
                'old_price': str(p.old_price) if p.old_price else None,
                'category': p.category,
                'primary_image': img_url,
                'likes_count': p.total_likes,
                'vendor_name': vendor_name,
                'vendor_slug': p.vendor.slug if p.vendor.slug else '',
                'is_sponsored': getattr(p, 'is_sponsored', False),
                'created_at': p.created_at.isoformat(),
            })

        return Response({'success': True, 'data': data})


class MarketTopVendorsView(APIView):
    """GET /<slug>/top-vendors/ - Top vendors (by products + followers)"""
    permission_classes = [permissions.AllowAny]

    def get(self, request, slug):
        market = get_market_or_404(slug)
        mvs = market.vendors.filter(status='active').select_related('vendor')[:20]
        serializer = MarketVendorSerializer(mvs, many=True, context={'request': request})
        # Sort by products_count descending
        data = sorted(serializer.data, key=lambda x: x.get('products_count', 0), reverse=True)[:10]
        return Response({'success': True, 'data': data})


# --- Vendor actions ---

class MarketJoinView(APIView):
    """POST /<slug>/join/ - Vendor joins market"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, slug):
        if request.user.user_type != 'vendor':
            return Response({'success': False, 'message': 'Only vendors can join markets.'}, status=403)

        market = get_market_or_404(slug)
        existing = market.vendors.filter(vendor=request.user).first()

        if existing:
            if existing.status == 'active':
                return Response({'success': False, 'message': 'You are already a member.'}, status=400)
            if existing.status == 'pending':
                return Response({'success': False, 'message': 'Your join request is pending.'}, status=400)
            if existing.status == 'removed':
                existing.delete()
            if existing.status == 'suspended':
                return Response({'success': False, 'message': 'You are suspended from this market.'}, status=403)

        vendor_status = 'pending' if market.vendor_approval == 'manual' else 'active'
        MarketVendor.objects.create(market=market, vendor=request.user, status=vendor_status)

        if vendor_status == 'active':
            market.update_counts()
            message = 'You have joined the market.'
        else:
            message = 'Your join request has been sent.'

        return Response({'success': True, 'message': message, 'status': vendor_status})


class MarketLeaveView(APIView):
    """POST /<slug>/leave/ - Vendor leaves market"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, slug):
        market = get_market_or_404(slug)
        mv = market.vendors.filter(vendor=request.user, status='active').first()
        if not mv:
            return Response({'success': False, 'message': 'You are not a member.'}, status=400)

        mv.delete()
        market.update_counts()
        return Response({'success': True, 'message': 'You have left the market.'})


# --- Admin CRUD ---

class MarketCreateView(APIView):
    """POST /create/ - Admin creates market"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)

        name = request.data.get('name', '').strip()
        description = request.data.get('description', '').strip()
        if not name or not description:
            return Response({'success': False, 'message': 'Name and description are required.'}, status=400)

        featured_val = request.data.get('featured', False)
        if isinstance(featured_val, str):
            featured_val = featured_val.lower() in ('true', '1', 'yes')

        market = Market(
            name=name,
            description=description,
            category=request.data.get('category', 'general'),
            county=request.data.get('county') or None,
            town_area=request.data.get('town_area', ''),
            vendor_approval=request.data.get('vendor_approval', 'instant'),
            featured=featured_val,
            created_by=request.user,
        )

        if 'logo' in request.FILES:
            market.logo = request.FILES['logo']
        if 'cover_image' in request.FILES:
            market.cover_image = request.FILES['cover_image']

        market.save()
        serializer = MarketDetailSerializer(market, context={'request': request})
        return Response({
            'success': True,
            'message': 'Market created successfully.',
            'data': serializer.data,
        }, status=status.HTTP_201_CREATED)


class MarketUpdateView(APIView):
    """PATCH /<slug>/update/ - Admin updates market"""
    permission_classes = [permissions.IsAuthenticated]

    def patch(self, request, slug):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)

        market = get_object_or_404(Market, slug=slug)
        allowed_fields = [
            'name', 'description', 'category', 'county', 'town_area',
            'vendor_approval', 'featured', 'status',
        ]
        for field in allowed_fields:
            if field in request.data:
                value = request.data[field]
                if field == 'featured' and isinstance(value, str):
                    value = value.lower() in ('true', '1', 'yes')
                if field == 'county' and not value:
                    value = None
                setattr(market, field, value)

        if 'logo' in request.FILES:
            market.logo = request.FILES['logo']
        if 'cover_image' in request.FILES:
            market.cover_image = request.FILES['cover_image']

        market.save()
        serializer = MarketDetailSerializer(market, context={'request': request})
        return Response({
            'success': True,
            'message': 'Market updated successfully.',
            'data': serializer.data,
        })


class MarketDeleteView(APIView):
    """DELETE /<slug>/delete/ - Admin soft-deletes market"""
    permission_classes = [permissions.IsAuthenticated]

    def delete(self, request, slug):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)

        market = get_object_or_404(Market, slug=slug)
        market.status = 'deleted'
        market.save(update_fields=['status'])
        return Response({'success': True, 'message': 'Market deleted.'})


# --- Admin vendor management ---

class MarketPendingVendorsView(generics.ListAPIView):
    """GET /<slug>/pending-vendors/ - Pending vendor list"""
    serializer_class = MarketVendorSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        if self.request.user.user_type != 'admin':
            return MarketVendor.objects.none()
        market = get_market_or_404(self.kwargs['slug'])
        return market.vendors.filter(status='pending').select_related('vendor')

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response({'success': True, 'data': serializer.data})


class ApproveVendorView(APIView):
    """POST /<slug>/vendors/<id>/approve/"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, slug, vendor_id):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)
        market = get_market_or_404(slug)
        mv = get_object_or_404(MarketVendor, id=vendor_id, market=market, status='pending')
        mv.status = 'active'
        mv.save(update_fields=['status'])
        market.update_counts()
        return Response({'success': True, 'message': 'Vendor approved.'})


class RejectVendorView(APIView):
    """POST /<slug>/vendors/<id>/reject/"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, slug, vendor_id):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)
        market = get_market_or_404(slug)
        mv = get_object_or_404(MarketVendor, id=vendor_id, market=market, status='pending')
        mv.status = 'removed'
        mv.save(update_fields=['status'])
        return Response({'success': True, 'message': 'Vendor rejected.'})


class RemoveVendorView(APIView):
    """POST /<slug>/vendors/<id>/remove/"""
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, slug, vendor_id):
        if request.user.user_type != 'admin':
            return Response({'success': False, 'message': 'Admin only.'}, status=403)
        market = get_market_or_404(slug)
        mv = get_object_or_404(MarketVendor, id=vendor_id, market=market, status='active')
        mv.status = 'removed'
        mv.save(update_fields=['status'])
        market.update_counts()
        return Response({'success': True, 'message': 'Vendor removed.'})
