from drf_spectacular.utils import extend_schema, OpenApiResponse
from django.db.models import Prefetch

from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework import status
from .serializers import (
    AdvertiseContentSerializer,
    CategorySerializer,
    EmailSerializer,
    GuidelineDetailSerializer,
    GuidelineListSerializer,
    GuidelineMinimalSerializer,
    OwnerInfoSerializer,
    PageSerializer,
)
from .models import AdvertiseContent, Category, Category, Guideline, OwnerInfo, Message, Page, PageSection, PageSectionItem
from blog.models import Blog
from project.models import Event
from service.models import Service
from service.serializers import ServiceListSerializer
from blog.serializers import BlogListSerializer
from project.serializers import EventListSerializer
import os
from django.core.mail import send_mail
from rest_framework.permissions import AllowAny


from rest_framework.decorators import action
from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ReadOnlyModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from django.db.models import Q
from rest_framework.views import APIView
from django.shortcuts import get_object_or_404


@extend_schema(
    tags=["Base"],
    description="Sends an email using the provided subject, message, and recipient email.",
    request=EmailSerializer,
    responses={
        200: OpenApiResponse(
            response={"detail": "Email sent successfully."},
            description="Email Sent Successfully",
        ),
        400: OpenApiResponse(
            response={"errors": ["Email: This field is required."]},
            description="Validation Error",
        ),
        500: OpenApiResponse(
            response={"error": "Email could not be sent"}, description="Server Error"
        ),
    },
)
@api_view(["POST"])
@permission_classes([AllowAny])
def send_msg_view(request, *args, **kwargs):
    try:
        if request.method == "POST":
            serializer = EmailSerializer(data=request.data)
            if serializer.is_valid():
                email = serializer.validated_data["email"]
                subject = serializer.validated_data["subject"]
                message = serializer.validated_data["message"]
                phone = serializer.validated_data["phone"]
                email_host = os.environ.get("DEFAULT_FROM_EMAIL")
                CONTACT_EMAIL = os.environ.get("CONTACT_EMAIL")
                recipient_list = [CONTACT_EMAIL]
                msg = Message.objects.create(
                    email=email, subject=subject, message=message, phone=phone
                )
                msg.save()
                send_mail(subject, message, email_host, recipient_list)
                return Response(
                    {"detail": "Message sent successfully."}, status=status.HTTP_200_OK
                )
            else:
                errors = serializer.errors
                error_messages = []

                for field, messages in errors.items():
                    for message in messages:
                        error_messages.append(f"{field.capitalize()}: {message}")

                return Response(
                    {"errors": error_messages}, status=status.HTTP_400_BAD_REQUEST
                )
    except Exception as e:
        print(e)
        return Response(
            {"error": "Email could not be sent"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
        )


class GuidelinePagination(PageNumberPagination):
    page_size = 12
    page_size_query_param = "page_size"
    max_page_size = 100

class CategoryViewSet(ReadOnlyModelViewSet):
    permission_classes = [AllowAny]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['name', 'description']
    ordering_fields = ['name', 'id']
    ordering = ['name']

    def get_queryset(self):
        return Category.objects.all().order_by('name')
    

    def get_serializer_class(self):
        return CategorySerializer
class GuidelineViewSet(ReadOnlyModelViewSet):
    permission_classes = [AllowAny]
    # pagination_class = GuidelinePagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['country', 'study_level', 'is_featured']
    search_fields = ['title', 'short_description', 'country']
    ordering_fields = ['is_featured', 'order', 'published_date']
    ordering = ['-is_featured', 'order', '-published_date']

    def get_queryset(self):
        return Guideline.objects.filter(status="published")

    def get_serializer_class(self):
        if self.action == "list":
            return GuidelineListSerializer
        return GuidelineDetailSerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.views_count += 1
        instance.save()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

    @action(detail=False, methods=["get"])
    def countries(self, request):
        countries = (
            Guideline.objects.filter(status="published")
            .values_list("country", "get_country_display")
            .distinct()
        )

        country_list = [
            {"value": country[0], "label": country[1]} for country in countries
        ]

        return Response({"success": True, "countries": country_list})

    @action(detail=False, methods=["get"])
    def study_levels(self, request):
        study_levels = (
            Guideline.objects.filter(status="published")
            .values_list("study_level", "get_study_level_display")
            .distinct()
        )

        level_list = [{"value": level[0], "label": level[1]} for level in study_levels]

        return Response({"success": True, "study_levels": level_list})

    @action(detail=False, methods=["get"])
    def featured(self, request):
        """
        Get featured guidelines
        """
        featured_guidelines = Guideline.objects.filter(
            status="published", is_featured=True
        ).order_by("order", "-published_date")[:6]

        serializer = GuidelineListSerializer(
            featured_guidelines, many=True, context={"request": request}
        )

        return Response(
            {
                "success": True,
                "count": featured_guidelines.count(),
                "guidelines": serializer.data,
            }
        )

    @action(detail=True, methods=["get"])
    def related(self, request, pk=None):
        """
        Get related guidelines (same country)
        """
        guideline = self.get_object()
        related_guidelines = (
            Guideline.objects.filter(country=guideline.country, status="published")
            .exclude(id=guideline.id)
            .order_by("-is_featured", "-views_count")[:4]
        )

        serializer = GuidelineListSerializer(
            related_guidelines, many=True, context={"request": request}
        )

        return Response(
            {
                "success": True,
                "count": related_guidelines.count(),
                "guidelines": serializer.data,
            }
        )


@extend_schema(
    tags=["Base"],
    description="Fetches website data including owner info and various sections.",
)
@api_view(["GET"])
@permission_classes([AllowAny])
def website_data(request, *args, **kwargs):
    try:
        owner_info = OwnerInfo.objects.latest("id")
        advertisments = AdvertiseContent.objects.filter(is_active=True)
        events = Event.objects.all().order_by("-created_at")[:12]
        services = Service.objects.all().order_by("-created_at")[:6]
        blogs = Blog.objects.all().order_by("-created_at")[:3]

        # Get featured guidelines for homepage
        featured_guidelines = Guideline.objects.filter(
            status="published", is_featured=True
        ).order_by("order", "-published_date")

        # Get all active pages with their sections and items
        all_pages = (
            Page.objects.filter(is_active=True)
            .prefetch_related(
                Prefetch(
                    "sections",
                    queryset=PageSection.objects.filter(is_visible=True)
                    .prefetch_related(
                        Prefetch(
                            "items",
                            queryset=PageSectionItem.objects.filter(
                                is_active=True
                            ).order_by("order"),
                        )
                    )
                    .order_by("order"),
                )
            )
            .order_by("order")
        )

        # Serialize all data
        pages_data = PageSerializer(
            all_pages, many=True, context={"request": request}
        ).data
        serialized_owner_info = OwnerInfoSerializer(
            owner_info, context={"request": request}
        ).data
        serialized_events = EventListSerializer(
            events, many=True, context={"request": request}
        ).data
        serialized_services = ServiceListSerializer(
            services, many=True, context={"request": request}
        ).data
        serialized_blogs = BlogListSerializer(
            blogs, many=True, context={"request": request}
        ).data
        serialized_guidelines = GuidelineMinimalSerializer(
            featured_guidelines, many=True, context={"request": request}
        ).data

        serialized_advertisments = AdvertiseContentSerializer(
            advertisments, many=True, context={"request": request}
        ).data

        data = {
            "owner_info": serialized_owner_info,
            "events": serialized_events,
            "services": serialized_services,
            "blogs": serialized_blogs,
            "featured_guidelines": serialized_guidelines,
            "advertisments": serialized_advertisments,
            "pages": pages_data,
        }

        return Response(
            {"success": True, "message": "Status OK", "data": data},
            status=status.HTTP_200_OK,
        )

    except OwnerInfo.DoesNotExist:
        return Response(
            {"error": "OwnerInfo not found"}, status=status.HTTP_404_NOT_FOUND
        )
    except Exception as e:
        return Response(
            {"error": "Internal Server Error", "details": str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
        )


class PageDetailView(APIView):
    permission_classes = [AllowAny]

    def get(self, request, identifier):
        try:
            if identifier.isdigit():
                page = get_object_or_404(Page, id=int(identifier), is_active=True)
            else:
                page = get_object_or_404(
                    Page.objects.filter(is_active=True),
                    Q(slug=identifier) | Q(name__iexact=identifier)
                )
            
            serializer = PageSerializer(page)
            return Response(serializer.data)
            
        except Page.DoesNotExist:
            return Response(
                {
                    "error": "Page not found",
                    "message": f"No active page found with identifier: {identifier}",
                    "suggestions": [
                        "Check if the page exists and is active",
                        "Try using the exact slug or name",
                        "Verify the page ID is correct"
                    ]
                },
                status=status.HTTP_404_NOT_FOUND
            )
        except ValueError:
            return Response(
                {
                    "error": "Invalid identifier",
                    "message": "Identifier must be a valid ID, slug, or name"
                },
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            return Response(
                {
                    "error": "Internal server error",
                    "message": str(e)
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )