"""
Publisher ViewSet
Phase 5: Sites Renderer & Publishing
"""
import json
import os
from pathlib import Path
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from drf_spectacular.utils import extend_schema, extend_schema_view

from igny8_core.api.base import SiteSectorModelViewSet
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsEditorOrAbove
from igny8_core.api.response import success_response, error_response
from igny8_core.api.throttles import DebugScopedRateThrottle
from igny8_core.business.publishing.models import PublishingRecord, DeploymentRecord
from igny8_core.business.publishing.services.publisher_service import PublisherService


@extend_schema_view(
    list=extend_schema(tags=['Publisher']),
    create=extend_schema(tags=['Publisher']),
    retrieve=extend_schema(tags=['Publisher']),
    update=extend_schema(tags=['Publisher']),
    partial_update=extend_schema(tags=['Publisher']),
    destroy=extend_schema(tags=['Publisher']),
)
class PublishingRecordViewSet(SiteSectorModelViewSet):
    """
    ViewSet for PublishingRecord model.
    """
    queryset = PublishingRecord.objects.select_related('content')
    permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
    throttle_scope = 'publisher'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_serializer_class(self):
        # Dynamically create serializer
        from rest_framework import serializers
        
        class PublishingRecordSerializer(serializers.ModelSerializer):
            class Meta:
                model = PublishingRecord
                exclude = []  # Legacy: site_blueprint field removed from model
        
        return PublishingRecordSerializer


@extend_schema_view(
    list=extend_schema(tags=['Publisher']),
    create=extend_schema(tags=['Publisher']),
    retrieve=extend_schema(tags=['Publisher']),
    update=extend_schema(tags=['Publisher']),
    partial_update=extend_schema(tags=['Publisher']),
    destroy=extend_schema(tags=['Publisher']),
)
class DeploymentRecordViewSet(SiteSectorModelViewSet):
    """
    ViewSet for DeploymentRecord model.
    Legacy: SiteBlueprint functionality removed.
    """
    queryset = DeploymentRecord.objects.all()
    permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
    throttle_scope = 'publisher'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_serializer_class(self):
        # Dynamically create serializer
        from rest_framework import serializers
        
        class DeploymentRecordSerializer(serializers.ModelSerializer):
            class Meta:
                model = DeploymentRecord
                exclude = []  # Legacy: site_blueprint field removed from model
        
        return DeploymentRecordSerializer


@extend_schema_view()
class PublisherViewSet(viewsets.ViewSet):
    """
    Publisher actions for publishing content.
    Legacy SiteBlueprint publishing removed - only content publishing supported.
    """
    permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
    throttle_scope = 'publisher'
    throttle_classes = [DebugScopedRateThrottle]
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.publisher_service = PublisherService()
    
    @extend_schema(tags=['Publisher'])
    @action(detail=False, methods=['post'], url_path='publish')
    def publish(self, request):
        """
        Publish content to destinations.
        
        Request body:
        {
            "content_id": 123,  # Required: content to publish
            "destinations": ["wordpress"]  # Required: list of destinations
        }
        """
        import logging
        logger = logging.getLogger(__name__)
        
        content_id = request.data.get('content_id')
        destinations = request.data.get('destinations', [])
        
        logger.info(f"[PublisherViewSet.publish] 🚀 Publish request received: content_id={content_id}, destinations={destinations}")
        
        if not content_id:
            return error_response(
                'content_id is required',
                status.HTTP_400_BAD_REQUEST,
                request
            )
        
        if not destinations:
            return error_response(
                'destinations is required',
                status.HTTP_400_BAD_REQUEST,
                request
            )
        
        account = request.account
        
        # Publish content
        logger.info(f"[PublisherViewSet.publish] 📝 Publishing content {content_id} to {destinations}")
        result = self.publisher_service.publish_content(
            content_id,
            destinations,
            account
        )
        logger.info(f"[PublisherViewSet.publish] {'✅' if result.get('success') else '❌'} Publish result: {result}")
        return success_response(result, request=request)
    
    @action(detail=False, methods=['get'], url_path='status/(?P<id>[^/.]+)')
    def get_status(self, request, id):
        """
        Get publishing status.
        
        GET /api/v1/publisher/status/{id}/
        """
        account = request.account
        
        # Get publishing record
        try:
            publishing = PublishingRecord.objects.get(id=id, account=account)
            return success_response({
                'type': 'publishing',
                'status': publishing.status,
                'destination': publishing.destination,
                'destination_url': publishing.destination_url,
                'published_at': publishing.published_at,
                'error_message': publishing.error_message,
            }, request=request)
        except PublishingRecord.DoesNotExist:
            return error_response(
                f'Record {id} not found',
                status.HTTP_404_NOT_FOUND,
                request
            )


@method_decorator(csrf_exempt, name='dispatch')
class SiteDefinitionView(APIView):
    """
    Public endpoint to serve deployed site definitions.
    Used by Sites Renderer to load site definitions.
    No authentication required for public sites.
    """
    permission_classes = []  # Public endpoint
    authentication_classes = []  # No authentication required
    
    def get(self, request, site_id):
        """
        Get deployed site definition.
        
        GET /api/v1/publisher/sites/{site_id}/definition/
        """
        try:
            sites_data_path = os.getenv('SITES_DATA_PATH', '/data/app/sites-data')
            
            # Try to find latest deployed version
            site_dir = Path(sites_data_path) / 'clients' / str(site_id)
            
            if not site_dir.exists():
                return error_response(
                    error=f'Site {site_id} not found at {site_dir}. Site may not be deployed yet.',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
            
            # Look for latest version (check for 'latest' symlink or highest version number)
            latest_path = site_dir / 'latest' / 'site.json'
            if latest_path.exists():
                try:
                    with open(latest_path, 'r', encoding='utf-8') as f:
                        definition = json.load(f)
                    return Response(definition, status=status.HTTP_200_OK)
                except json.JSONDecodeError as e:
                    return error_response(
                        error=f'Invalid JSON in site definition file: {str(e)}',
                        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        request=request
                    )
                except Exception as e:
                    return error_response(
                        error=f'Failed to load site definition from {latest_path}: {str(e)}',
                        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        request=request
                    )
            
            # Fallback: find highest version number
            try:
                version_dirs = [d for d in site_dir.iterdir() if d.is_dir() and d.name.startswith('v')]
            except PermissionError as e:
                return error_response(
                    error=f'Permission denied accessing site directory: {str(e)}',
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    request=request
                )
            except Exception as e:
                return error_response(
                    error=f'Error reading site directory: {str(e)}',
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    request=request
                )
            
            if not version_dirs:
                return error_response(
                    error=f'No deployed versions found for site {site_id}. Site may not be deployed yet.',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
            
            # Sort by version number (extract number from 'v1', 'v2', etc.)
            try:
                version_dirs.sort(key=lambda d: int(d.name[1:]) if d.name[1:].isdigit() else 0, reverse=True)
                latest_version_dir = version_dirs[0]
                site_json_path = latest_version_dir / 'site.json'
                
                if site_json_path.exists():
                    with open(site_json_path, 'r', encoding='utf-8') as f:
                        definition = json.load(f)
                    return Response(definition, status=status.HTTP_200_OK)
                else:
                    return error_response(
                        error=f'Site definition file not found at {site_json_path}',
                        status_code=status.HTTP_404_NOT_FOUND,
                        request=request
                    )
            except json.JSONDecodeError as e:
                return error_response(
                    error=f'Invalid JSON in site definition file: {str(e)}',
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    request=request
                )
            except Exception as e:
                return error_response(
                    error=f'Failed to load site definition: {str(e)}',
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    request=request
                )
            
            return error_response(
                error=f'Site definition not found for site {site_id}',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except Exception as e:
            # Catch any unhandled exceptions
            import logging
            logger = logging.getLogger(__name__)
            logger.error(f'Unhandled exception in SiteDefinitionView: {str(e)}', exc_info=True)
            return error_response(
                error=f'Internal server error: {str(e)}',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )

