import logging import requests from django.conf import settings from django.core.exceptions import ImproperlyConfigured from rest_framework import status from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from apps.core.utils import capture_and_log from apps.core.utils.cloudflare import get_direct_upload_url logger = logging.getLogger(__name__) class GenerateUploadURLView(APIView): permission_classes = [IsAuthenticated] def post(self, request): try: # Pass user_id for metadata if needed result = get_direct_upload_url(user_id=str(request.user.id)) return Response(result, status=status.HTTP_200_OK) except ImproperlyConfigured as e: capture_and_log(e, 'Generate upload URL - configuration error', source='api') return Response({"detail": "Server configuration error."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) except requests.RequestException as e: capture_and_log(e, 'Generate upload URL - Cloudflare API error', source='api') return Response({"detail": "Failed to generate upload URL."}, status=status.HTTP_502_BAD_GATEWAY) except Exception as e: capture_and_log(e, 'Generate upload URL - unexpected error', source='api') return Response({"detail": "An unexpected error occurred."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) class DeleteImageView(APIView): """ POST /images/delete/ Delete an image from Cloudflare Images. """ permission_classes = [IsAuthenticated] def post(self, request): image_id = request.data.get("image_id") if not image_id: return Response( {"detail": "image_id is required"}, status=status.HTTP_400_BAD_REQUEST, ) try: # Get Cloudflare credentials account_id = getattr(settings, "CLOUDFLARE_IMAGES_ACCOUNT_ID", None) api_token = getattr(settings, "CLOUDFLARE_IMAGES_API_TOKEN", None) if not account_id or not api_token: logger.warning("Cloudflare Images not configured, mock deleting image") return Response({"success": True, "mock": True}) # Delete from Cloudflare url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/{image_id}" response = requests.delete( url, headers={"Authorization": f"Bearer {api_token}"}, timeout=10, ) if response.status_code in (200, 404): # 404 = already deleted return Response({"success": True}) else: logger.error(f"Cloudflare delete failed: {response.text}") return Response( {"detail": "Failed to delete image"}, status=status.HTTP_502_BAD_GATEWAY, ) except requests.RequestException as e: capture_and_log(e, "Delete image - Cloudflare API error", source="api") return Response( {"detail": "Failed to delete image"}, status=status.HTTP_502_BAD_GATEWAY, ) except Exception as e: capture_and_log(e, "Delete image - unexpected error", source="api") return Response( {"detail": "An unexpected error occurred"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, ) class GenerateOGImageView(APIView): """ POST /images/og-image/ Generate an Open Graph image for social sharing. """ permission_classes = [] # Public endpoint def post(self, request): title = request.data.get("title", "") description = request.data.get("description", "") entity_type = request.data.get("entity_type", "") image_url = request.data.get("image_url", "") if not title: return Response( {"detail": "title is required"}, status=status.HTTP_400_BAD_REQUEST, ) try: # This is a placeholder for OG image generation # In production, you would: # 1. Use an image generation service (Cloudinary, imgix, etc.) # 2. Or use a headless browser service (Puppeteer, Playwright) # 3. Or use a dedicated OG image service # For now, return a template URL or placeholder base_url = getattr(settings, "SITE_URL", "https://thrillwiki.com") og_image_url = f"{base_url}/api/v1/images/og-preview/?title={title[:100]}" return Response({ "success": True, "og_image_url": og_image_url, "title": title, "description": description[:200] if description else "", "entity_type": entity_type, "note": "Placeholder - configure OG image service for production", }) except Exception as e: capture_and_log(e, "Generate OG image", source="api") return Response( {"detail": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, )