from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from .models import (BlogPost, BlogStatus, BlogCategory, BlogTag, BlogSEO)
from .permissions import IsBlogAdmin
from .admin_serializers import (BlogPostAdminDetailSerializer, BlogPostAdminWriteSerializer, BlogPostAdminListSerializer)
from .serializers import BlogTagSerializer, BlogCategorySerializer
from django.utils import timezone
from .services.dashboard_service import DashboardService
from django.conf import settings
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
import os
import uuid
from datetime import datetime



class AdminBlogPostListCreateView(generics.ListCreateAPIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]
    #pagination_class = None

    queryset = (
        BlogPost.objects
        .select_related("author", "category")
        .order_by("-created_at")
    )

    def get_queryset(self):
        queryset = BlogPost.objects.select_related(
            "author",
            "category"
        ).order_by("-created_at")

        search = self.request.query_params.get("search", "")
        category = self.request.query_params.get("category", "")
        status = self.request.query_params.get("status", "")

        if search:
            queryset = queryset.filter(title__icontains=search)

        if category:
            queryset = queryset.filter(category__slug=category)

        if status:
            queryset = queryset.filter(status=status)

        return queryset

    def get_serializer_class(self):

        if self.request.method == "GET":
            return BlogPostAdminListSerializer

        return BlogPostAdminWriteSerializer

    def perform_create(self, serializer):

        post = serializer.save(
            author=self.request.user,
            created_by=self.request.user,
            updated_by=self.request.user,
        )

        self._save_seo(post)

        self._set_publisher(post)

    def _save_seo(self, post):

        BlogSEO.objects.create(
            post=post,

            meta_title=self.request.data.get(
                "meta_title",
                "",
            ),

            meta_description=self.request.data.get(
                "meta_description",
                "",
            ),

            keywords=self.request.data.get(
                "keywords",
                "",
            ),

            canonical_url=self.request.data.get(
                "canonical_url",
                "",
            ),

            og_title=self.request.data.get(
                "og_title",
                "",
            ),

            og_description=self.request.data.get(
                "og_description",
                "",
            ),

            og_image=self.request.FILES.get(
                "og_image"
            ),
        )

    def _set_publisher(self, post):

        if (
            post.status == "published"
            and not post.published_by
        ):
            post.published_by = self.request.user
            post.save(update_fields=["published_by"])


class AdminBlogPostDetailView(generics.RetrieveUpdateDestroyAPIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    queryset = (
        BlogPost.objects
        .select_related(
            "author",
            "category",
            "seo",
        )
        .prefetch_related("tags")
    )

    def get_serializer_class(self):

        if self.request.method == "GET":
            return BlogPostAdminDetailSerializer

        return BlogPostAdminWriteSerializer

    def perform_update(self, serializer):

        post = serializer.save(
            updated_by=self.request.user
        )

        self._save_seo(post)

        self._set_publisher(post)

    def _save_seo(self, post):

        seo, _ = BlogSEO.objects.get_or_create(
            post=post
        )

        seo.meta_title = self.request.data.get(
            "meta_title",
            seo.meta_title,
        )

        seo.meta_description = self.request.data.get(
            "meta_description",
            seo.meta_description,
        )

        seo.keywords = self.request.data.get(
            "keywords",
            seo.keywords,
        )

        seo.canonical_url = self.request.data.get(
            "canonical_url",
            seo.canonical_url,
        )

        seo.og_title = self.request.data.get(
            "og_title",
            seo.og_title,
        )

        seo.og_description = self.request.data.get(
            "og_description",
            seo.og_description,
        )

        if "og_image" in self.request.FILES:
            seo.og_image = self.request.FILES["og_image"]

        seo.save()

    def _set_publisher(self, post):

        if (
            post.status == "published"
            and not post.published_by
        ):
            post.published_by = self.request.user
            post.save(update_fields=["published_by"])



class PublishPostView(APIView):

    permission_classes = [IsAuthenticated, IsBlogAdmin,]

    def post(self, request, pk):

        post = get_object_or_404(BlogPost,pk=pk)

        post.status = BlogStatus.PUBLISHED
        post.published_by = request.user

        if not post.published_at:
            post.published_at = timezone.now()

        post.save()

        return Response({
            "message": "Post published successfully"
        })
    
class ArchivePostView(APIView):

    permission_classes = [IsAuthenticated, IsBlogAdmin,]

    def post(self, request, pk):

        post = get_object_or_404(BlogPost, pk=pk)

        post.status = BlogStatus.ARCHIVED

        post.save()

        return Response({
            "message": "Post archived successfully"
        })

from rest_framework import generics, filters

class AdminCategoryListCreateView(generics.ListCreateAPIView):

    serializer_class = BlogCategorySerializer
    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]
    pagination_class = None

    queryset = BlogCategory.objects.all()

    filter_backends = [filters.SearchFilter]

    search_fields = [
        "name",
        "description",
        "slug",
    ]

class AdminCategoryDetailView(
    generics.RetrieveUpdateDestroyAPIView
):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    serializer_class = BlogCategorySerializer

    queryset = BlogCategory.objects.all()


# List tags
from rest_framework.filters import SearchFilter

class TagListCreateView(generics.ListCreateAPIView):
    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]
    pagination_class = None
    serializer_class = BlogTagSerializer
    queryset = BlogTag.objects.all().order_by("name")

    filter_backends = [SearchFilter]
    search_fields = ["name", "slug"]

    def perform_create(self, serializer):
        serializer.save()

class TagDetailView(generics.RetrieveUpdateDestroyAPIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    serializer_class = BlogTagSerializer

    queryset = BlogTag.objects.all()
    
class DashboardView(APIView):

    permission_classes = [IsAuthenticated, IsBlogAdmin,]

    def get(self, request):

        return Response({
            "summary": DashboardService.get_summary(),
            "top_posts": DashboardService.get_top_posts(),
            "recent_posts": DashboardService.get_recent_posts(),
            "cta_breakdown": DashboardService.get_cta_breakdown(),
            "banner_performance": DashboardService.get_banner_performance(),
        })
    



class UploadBlogImageView(APIView):
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        try:
            if 'image' not in request.FILES:
                return Response(
                    {'error': 'No image provided'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            image = request.FILES['image']
            
            # Validate image type
            if not image.content_type.startswith('image/'):
                return Response(
                    {'error': 'File must be an image'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # Validate image size (max 5MB)
            if image.size > 5 * 1024 * 1024:
                return Response(
                    {'error': 'Image size must be less than 5MB'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # Generate unique filename
            ext = os.path.splitext(image.name)[1]
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"blog_images/{timestamp}_{uuid.uuid4().hex[:8]}{ext}"
            
            # Save file
            saved_path = default_storage.save(filename, ContentFile(image.read()))
            
            # Get the URL - make it absolute
            file_url = default_storage.url(saved_path)
            
            # IMPORTANT: Build absolute URL
            # Get the base URL from request
            base_url = request.build_absolute_uri('/').rstrip('/')
            
            # If the URL starts with '/', prepend the base URL
            if file_url.startswith('/'):
                full_url = f"{base_url}{file_url}"
            else:
                full_url = file_url
            
            return Response({
                'url': full_url,  # This will be something like: http://localhost:8000/media/blog_images/20250101_123456_abc12345.jpg
                'filename': filename,
                'message': 'Image uploaded successfully'
            }, status=status.HTTP_201_CREATED)
            
        except Exception as e:
            return Response(
                {'error': str(e)}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

# blog/views.py
class DeleteBlogImageView(APIView):
    permission_classes = [IsAuthenticated]
    
    def delete(self, request):
        try:
            filename = request.query_params.get('filename')
            if not filename:
                return Response(
                    {'error': 'Filename required'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # Delete the file
            if default_storage.exists(filename):
                default_storage.delete(filename)
                return Response(
                    {'message': 'Image deleted successfully'}, 
                    status=status.HTTP_200_OK
                )
            else:
                return Response(
                    {'error': 'File not found'}, 
                    status=status.HTTP_404_NOT_FOUND
                )
                
        except Exception as e:
            return Response(
                {'error': str(e)}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )