"""
IGNY8 Content Publishing Celery Tasks - WITH COMPREHENSIVE LOGGING

Handles automated publishing of content from IGNY8 to WordPress sites.
All workflow steps are logged to files for debugging and monitoring.
"""
from celery import shared_task
from django.conf import settings
from django.utils import timezone
from datetime import timedelta
import requests
import logging
import time
import json
from typing import Dict, List, Any, Optional

# Standard logger
logger = logging.getLogger(__name__)
# Dedicated file loggers
publish_logger = logging.getLogger('publish_sync')
api_logger = logging.getLogger('wordpress_api')


@shared_task(bind=True, max_retries=3)
def publish_content_to_wordpress(self, content_id: int, site_integration_id: int, task_id: Optional[int] = None) -> Dict[str, Any]:
    """
    Publish a single content item to WordPress with comprehensive logging
    
    Args:
        content_id: IGNY8 content ID
        site_integration_id: WordPress site integration ID
        task_id: Optional IGNY8 task ID
        
    Returns:
        Dict with success status and details
    """
    start_time = time.time()
    
    try:
        from igny8_core.business.content.models import Content
        from igny8_core.business.integration.models import SiteIntegration, SyncEvent
        from igny8_core.modules.writer.models import Images
        from django.utils.html import strip_tags
        
        publish_logger.info("="*80)
        publish_logger.info(f"🎯 PUBLISH WORKFLOW STARTED")
        publish_logger.info(f"   Content ID: {content_id}")
        publish_logger.info(f"   Site Integration ID: {site_integration_id}")
        publish_logger.info(f"   Task ID: {task_id}")
        publish_logger.info("="*80)
        
        # STEP 1: Load content and integration from database
        try:
            publish_logger.info(f"STEP 1: Loading content and integration from database...")
            content = Content.objects.get(id=content_id)
            site_integration = SiteIntegration.objects.get(id=site_integration_id)
            
            # Extract site info for logging context
            site_id = site_integration.site.id if site_integration.site else 'unknown'
            base_url = site_integration.config_json.get('site_url', '') or site_integration.config_json.get('base_url', '')
            site_domain = base_url.replace('https://', '').replace('http://', '').split('/')[0] if base_url else 'unknown'
            log_prefix = f"[{site_id}-{site_domain}]"
            
            # Extract API key from credentials
            api_key = site_integration.get_credentials().get('api_key', '')
            
            publish_logger.info(f"   ✅ Content loaded:")
            publish_logger.info(f"      {log_prefix} Title: '{content.title}'")
            publish_logger.info(f"      {log_prefix} Status: {content.status}")
            publish_logger.info(f"      {log_prefix} Type: {content.content_type}")
            publish_logger.info(f"      {log_prefix} Site: {content.site.name if content.site else 'None'}")
            publish_logger.info(f"      {log_prefix} Account: {content.account.name if content.account else 'None'}")
            
            publish_logger.info(f"   ✅ Integration loaded:")
            publish_logger.info(f"      {log_prefix} Platform: {site_integration.platform}")
            publish_logger.info(f"      {log_prefix} Site: {site_integration.site.name}")
            publish_logger.info(f"      {log_prefix} Base URL: {base_url}")
            publish_logger.info(f"      {log_prefix} API Key: {'***' + api_key[-4:] if api_key else 'None'}")
        except (Content.DoesNotExist, SiteIntegration.DoesNotExist) as e:
            publish_logger.error(f"   ❌ Database lookup failed: {e}")
            return {"success": False, "error": str(e)}
        
        # STEP 2: Check if already published
        publish_logger.info(f"{log_prefix} STEP 2: Checking if content is already published...")
        if content.external_id:
            publish_logger.info(f"   {log_prefix} ⚠️ Content already published:")
            publish_logger.info(f"      {log_prefix} External ID: {content.external_id}")
            publish_logger.info(f"      {log_prefix} External URL: {content.external_url}")
            publish_logger.info(f"   {log_prefix} ⏭️  Skipping publish workflow")
            return {"success": True, "message": "Already published", "external_id": content.external_id}
        else:
            publish_logger.info(f"   {log_prefix} ✅ Content not yet published, proceeding...")
        
        # STEP 3: Generate excerpt from HTML content
        publish_logger.info(f"{log_prefix} STEP 3: Generating excerpt from content HTML...")
        excerpt = ''
        if content.content_html:
            excerpt = strip_tags(content.content_html)[:150].strip()
            if len(content.content_html) > 150:
                excerpt += '...'
            publish_logger.info(f"   {log_prefix} ✅ Excerpt generated:")
            publish_logger.info(f"      {log_prefix} Content HTML length: {len(content.content_html)} chars")
            publish_logger.info(f"      {log_prefix} Excerpt: {excerpt[:80]}...")
        else:
            publish_logger.warning(f"   {log_prefix} ⚠️ No content_html found - excerpt will be empty")
        
        # STEP 4: Get taxonomy terms (categories and tags)
        publish_logger.info(f"{log_prefix} STEP 4: Loading taxonomy terms from Content.taxonomy_terms...")
        
        # Get categories from ContentTaxonomy many-to-many relationship
        # This is the CORRECT way - matching ContentSerializer.get_categories()
        categories = [
            term.name
            for term in content.taxonomy_terms.filter(taxonomy_type='category')
        ]
        
        publish_logger.info(f"   {log_prefix} Found {len(categories)} categories from taxonomy_terms")
        for cat in categories:
            publish_logger.info(f"   {log_prefix} 📁 Category: '{cat}'")
        
        # FALLBACK: If no categories from taxonomy_terms, use Cluster as category (matches UI display)
        if not categories and content.cluster:
            categories.append(content.cluster.name)
            publish_logger.info(f"   {log_prefix} 📁 Category (fallback from cluster): '{content.cluster.name}'")
        
        if not categories:
            publish_logger.warning(f"   {log_prefix} ⚠️ No categories found for content")
        else:
            publish_logger.info(f"   {log_prefix} ✅ TOTAL categories: {len(categories)}")
        
        # STEP 5: Get tags from taxonomy_terms AND keywords
        publish_logger.info(f"{log_prefix} STEP 5: Loading tags from taxonomy_terms and keywords...")
        
        # First, get tags from ContentTaxonomy many-to-many relationship
        # This matches ContentSerializer.get_tags()
        tags = [
            term.name
            for term in content.taxonomy_terms.filter(taxonomy_type='tag')
        ]
        
        publish_logger.info(f"   {log_prefix} Found {len(tags)} tags from taxonomy_terms")
        for tag in tags:
            publish_logger.info(f"   {log_prefix} 🏷️  Tag: '{tag}'")
        
        # Add primary keyword as tag (if not already in tags)
        if content.primary_keyword:
            if content.primary_keyword not in tags:
                tags.append(content.primary_keyword)
                publish_logger.info(f"   {log_prefix} 🏷️  Primary keyword: '{content.primary_keyword}'")
        else:
            publish_logger.warning(f"   {log_prefix} ⚠️ No primary keyword found")
        
        # Add secondary keywords as tags (if not already in tags)
        if content.secondary_keywords:
            if isinstance(content.secondary_keywords, list):
                for keyword in content.secondary_keywords:
                    if keyword not in tags:
                        tags.append(keyword)
                publish_logger.info(f"   {log_prefix} 🏷️  Secondary keywords (list): {content.secondary_keywords}")
            elif isinstance(content.secondary_keywords, str):
                try:
                    keywords = json.loads(content.secondary_keywords)
                    if isinstance(keywords, list):
                        for keyword in keywords:
                            if keyword not in tags:
                                tags.append(keyword)
                        publish_logger.info(f"   {log_prefix} 🏷️  Secondary keywords (JSON): {keywords}")
                except (json.JSONDecodeError, TypeError):
                    publish_logger.warning(f"   {log_prefix} ⚠️ Failed to parse secondary_keywords as JSON: {content.secondary_keywords}")
        else:
            publish_logger.warning(f"   {log_prefix} ⚠️ No secondary keywords found")
        
        publish_logger.info(f"   {log_prefix} ✅ TOTAL tags: {len(tags)}")

        
        if not tags:
            publish_logger.warning(f"   {log_prefix} ⚠️ No tags found for content")
        else:
            publish_logger.info(f"   {log_prefix} ✅ TOTAL tags: {len(tags)}")
        
        # STEP 6: Get images (featured + gallery)
        publish_logger.info(f"{log_prefix} STEP 6: Loading images for content...")
        images = Images.objects.filter(content=content).order_by('position')
        publish_logger.info(f"   {log_prefix} Found {images.count()} images")
        
        featured_image_url = None
        gallery_images = []
        
        def convert_image_path_to_url(image_path):
            """Convert local image path to public URL"""
            if not image_path:
                return None
            # Convert: /data/app/igny8/frontend/public/images/... -> https://app.igny8.com/images/...
            if '/frontend/public/' in image_path:
                relative_path = image_path.split('/frontend/public/')[-1]
                return f"https://app.igny8.com/{relative_path}"
            return image_path
        
        for image in images:
            # Use image_path (local file) and convert to public URL
            image_url = convert_image_path_to_url(image.image_path) if hasattr(image, 'image_path') and image.image_path else None
            
            if image.image_type == 'featured' and image_url:
                featured_image_url = image_url
                publish_logger.info(f"   {log_prefix} 🖼️  Featured image: {image_url[:80]}...")
            elif image.image_type == 'in_article' and image_url:
                gallery_images.append({
                    'url': image_url,
                    'alt': getattr(image, 'alt', '') or '',
                    'caption': getattr(image, 'caption', '') or ''
                })
                publish_logger.info(f"   {log_prefix} 🖼️  Gallery image {len(gallery_images)}: {image_url[:60]}...")
        
        if not featured_image_url:
            publish_logger.warning(f"   {log_prefix} ⚠️ No featured image found")
        if not gallery_images:
            publish_logger.info(f"   {log_prefix} ℹ️  No gallery images found")
        else:
            publish_logger.info(f"   {log_prefix} ✅ Gallery images: {len(gallery_images)}")
        
        # STEP 7: Prepare content payload
        publish_logger.info(f"{log_prefix} STEP 7: Building WordPress API payload...")
        content_data = {
            'content_id': content.id,
            'task_id': task_id,
            'title': content.title,
            'content_html': content.content_html or '',
            'excerpt': excerpt,
            'status': 'publish',
            'author_email': None,
            'author_name': None,
            'published_at': None,
            'seo_title': content.meta_title or '',
            'seo_description': content.meta_description or '',
            'primary_keyword': content.primary_keyword or '',
            'secondary_keywords': content.secondary_keywords or [],
            'featured_image_url': featured_image_url,
            'gallery_images': gallery_images,
            'cluster_id': content.cluster.id if content.cluster else None,
            'sector_id': content.sector.id if content.sector else None,
            'categories': categories,
            'tags': tags,
            'sectors': [],
            'clusters': []
        }
        
        publish_logger.info(f"   {log_prefix} ✅ Payload built:")
        publish_logger.info(f"      {log_prefix} Title: {content.title}")
        publish_logger.info(f"      {log_prefix} Content HTML: {len(content_data['content_html'])} chars")
        publish_logger.info(f"      {log_prefix} Categories: {len(categories)}")
        publish_logger.info(f"      {log_prefix} Tags: {len(tags)}")
        publish_logger.info(f"      {log_prefix} Featured image: {'Yes' if featured_image_url else 'No'}")
        publish_logger.info(f"      {log_prefix} Gallery images: {len(gallery_images)}")
        publish_logger.info(f"      {log_prefix} SEO title: {'Yes' if content_data['seo_title'] else 'No'}")
        publish_logger.info(f"      {log_prefix} SEO description: {'Yes' if content_data['seo_description'] else 'No'}")
        publish_logger.info(f"      {log_prefix} Cluster ID: {content_data['cluster_id']}")
        publish_logger.info(f"      {log_prefix} Sector ID: {content_data['sector_id']}")
        
        # STEP 8: Send API request to WordPress
        base_url = site_integration.config_json.get('site_url', '') or site_integration.config_json.get('base_url', '')
        api_key = site_integration.get_credentials().get('api_key', '')
        
        if not base_url:
            error_msg = "No base_url/site_url configured in integration"
            publish_logger.error(f"   {log_prefix} ❌ {error_msg}")
            return {"success": False, "error": error_msg}
        
        if not api_key:
            error_msg = "No API key configured in integration"
            publish_logger.error(f"   {log_prefix} ❌ {error_msg}")
            return {"success": False, "error": error_msg}
        
        wordpress_url = f"{base_url}/wp-json/igny8/v1/publish"
        headers = {
            'X-IGNY8-API-Key': api_key,
            'Content-Type': 'application/json',
        }
        
        publish_logger.info(f"{log_prefix} STEP 8: Sending POST request to WordPress...")
        api_logger.info(f"{log_prefix} API REQUEST: POST {wordpress_url}")
        api_logger.info(f"   {log_prefix} Headers: X-IGNY8-API-Key: ***{api_key[-4:] if api_key else 'None'}")
        api_logger.info(f"   {log_prefix} Payload: {json.dumps(content_data, indent=2)[:500]}...")
        
        try:
            response = requests.post(
                wordpress_url,
                json=content_data,
                headers=headers,
                timeout=30
            )
            
            api_logger.info(f"{log_prefix} API RESPONSE: {response.status_code}")
            api_logger.info(f"   {log_prefix} Response body: {response.text[:500]}")
            publish_logger.info(f"   {log_prefix} ✅ WordPress responded: HTTP {response.status_code}")
            
        except requests.exceptions.Timeout as e:
            error_msg = f"WordPress API timeout after 30s: {str(e)}"
            api_logger.error(f"{log_prefix} API ERROR: {error_msg}")
            publish_logger.error(f"   {log_prefix} ❌ Request timed out after 30 seconds")
            
            # Log failure event
            SyncEvent.objects.create(
                integration=site_integration,
                site=content.site,
                account=content.account,
                event_type='error',
                action='content_publish',
                description=f"Timeout publishing '{content.title}' to WordPress",
                success=False,
                content_id=content.id,
                error_message=error_msg,
                duration_ms=int((time.time() - start_time) * 1000)
            )
            return {"success": False, "error": error_msg}
        
        except requests.exceptions.RequestException as e:
            error_msg = f"WordPress API request failed: {str(e)}"
            api_logger.error(f"{log_prefix} API ERROR: {error_msg}")
            publish_logger.error(f"   {log_prefix} ❌ Request exception: {str(e)}")
            
            # Log failure event
            SyncEvent.objects.create(
                integration=site_integration,
                site=content.site,
                account=content.account,
                event_type='error',
                action='content_publish',
                description=f"Request error publishing '{content.title}' to WordPress",
                success=False,
                content_id=content.id,
                error_message=error_msg,
                duration_ms=int((time.time() - start_time) * 1000)
            )
            return {"success": False, "error": error_msg}
        
        # STEP 9: Process response
        publish_logger.info(f"{log_prefix} STEP 9: Processing WordPress response...")
        
        if response.status_code == 201:
            # SUCCESS - Post created
            publish_logger.info(f"   {log_prefix} ✅ WordPress post created successfully (HTTP 201)")
            
            try:
                response_data = response.json()
                wp_data = response_data.get('data', {})
                wp_status = wp_data.get('post_status', 'publish')
                
                publish_logger.info(f"      {log_prefix} Post ID: {wp_data.get('post_id')}")
                publish_logger.info(f"      {log_prefix} Post URL: {wp_data.get('post_url')}")
                publish_logger.info(f"      {log_prefix} Post status: {wp_status}")
                
                # Update Content model
                publish_logger.info(f"{log_prefix} STEP 10: Updating IGNY8 Content model...")
                content.external_id = str(wp_data.get('post_id'))
                content.external_url = wp_data.get('post_url')
                content.status = 'published'
                
                if not hasattr(content, 'metadata') or content.metadata is None:
                    content.metadata = {}
                content.metadata['wordpress_status'] = wp_status
                
                content.save(update_fields=['external_id', 'external_url', 'status', 'metadata', 'updated_at'])
                
                publish_logger.info(f"   {log_prefix} ✅ Content model updated:")
                publish_logger.info(f"      {log_prefix} External ID: {content.external_id}")
                publish_logger.info(f"      {log_prefix} External URL: {content.external_url}")
                publish_logger.info(f"      {log_prefix} Status: published")
                publish_logger.info(f"      {log_prefix} WordPress status: {wp_status}")
                
                # Log success event
                duration_ms = int((time.time() - start_time) * 1000)
                SyncEvent.objects.create(
                    integration=site_integration,
                    site=content.site,
                    account=content.account,
                    event_type='publish',
                    action='content_publish',
                    description=f"Published content '{content.title}' to WordPress",
                    success=True,
                    content_id=content.id,
                    external_id=str(content.external_id),
                    details={
                        'post_url': content.external_url,
                        'wordpress_status': wp_status,
                        'categories': categories,
                        'tags': tags,
                        'has_featured_image': bool(featured_image_url),
                        'gallery_images_count': len(gallery_images),
                    },
                    duration_ms=duration_ms
                )
                
                publish_logger.info(f"="*80)
                publish_logger.info(f"{log_prefix} 🎉 PUBLISH WORKFLOW COMPLETED SUCCESSFULLY")
                publish_logger.info(f"   {log_prefix} Duration: {duration_ms}ms")
                publish_logger.info(f"   {log_prefix} WordPress Post ID: {content.external_id}")
                publish_logger.info("="*80)
                
                return {
                    "success": True,
                    "external_id": content.external_id,
                    "external_url": content.external_url,
                    "wordpress_status": wp_status
                }
                
            except (json.JSONDecodeError, KeyError) as e:
                error_msg = f"Failed to parse WordPress response: {str(e)}"
                publish_logger.error(f"   ❌ Response parsing error: {error_msg}")
                publish_logger.error(f"      Raw response: {response.text[:200]}")
                return {"success": False, "error": error_msg}
        
        elif response.status_code == 409:
            # CONFLICT - Post already exists
            publish_logger.info(f"   {log_prefix} ⚠️ Content already exists in WordPress (HTTP 409)")
            
            try:
                response_data = response.json()
                wp_data = response_data.get('data', {})
                wp_status = wp_data.get('post_status', 'publish')
                
                publish_logger.info(f"      {log_prefix} Existing Post ID: {wp_data.get('post_id')}")
                publish_logger.info(f"      {log_prefix} Post URL: {wp_data.get('post_url')}")
                
                # Update Content model
                content.external_id = str(wp_data.get('post_id'))
                content.external_url = wp_data.get('post_url')
                content.status = 'published'
                
                if not hasattr(content, 'metadata') or content.metadata is None:
                    content.metadata = {}
                content.metadata['wordpress_status'] = wp_status
                
                content.save(update_fields=['external_id', 'external_url', 'status', 'metadata', 'updated_at'])
                
                # Log sync event
                duration_ms = int((time.time() - start_time) * 1000)
                SyncEvent.objects.create(
                    integration=site_integration,
                    site=content.site,
                    account=content.account,
                    event_type='sync',
                    action='content_publish',
                    description=f"Content '{content.title}' already exists in WordPress",
                    success=True,
                    content_id=content.id,
                    external_id=str(content.external_id),
                    details={
                        'post_url': content.external_url,
                        'wordpress_status': wp_status,
                        'already_exists': True,
                    },
                    duration_ms=duration_ms
                )
                
                publish_logger.info(f"="*80)
                publish_logger.info(f"{log_prefix} ✅ PUBLISH WORKFLOW COMPLETED (already exists)")
                publish_logger.info(f"   {log_prefix} Duration: {duration_ms}ms")
                publish_logger.info("="*80)
                
                return {
                    "success": True,
                    "message": "Content already exists",
                    "external_id": content.external_id,
                    "wordpress_status": wp_status
                }
                
            except (json.JSONDecodeError, KeyError) as e:
                error_msg = f"Failed to parse 409 response: {str(e)}"
                publish_logger.error(f"   ❌ Response parsing error: {error_msg}")
                return {"success": False, "error": error_msg}
        
        else:
            # ERROR - Unexpected status code
            error_msg = f"WordPress API error: HTTP {response.status_code}"
            publish_logger.error(f"   {log_prefix} ❌ Unexpected status code: {response.status_code}")
            publish_logger.error(f"      {log_prefix} Response: {response.text[:500]}")
            
            api_logger.error(f"{log_prefix} API ERROR: {error_msg}")
            api_logger.error(f"   {log_prefix} Full response: {response.text}")
            
            # Log failure event
            duration_ms = int((time.time() - start_time) * 1000)
            SyncEvent.objects.create(
                integration=site_integration,
                site=content.site,
                account=content.account,
                event_type='error',
                action='content_publish',
                description=f"Failed to publish content '{content.title}' to WordPress",
                success=False,
                content_id=content.id,
                error_message=error_msg,
                details={
                    'status_code': response.status_code,
                    'response_text': response.text[:500],
                },
                duration_ms=duration_ms
            )
            
            # Retry logic
            if self.request.retries < self.max_retries:
                countdown = 60 * (5 ** self.request.retries)
                publish_logger.warning(f"   {log_prefix} 🔄 Scheduling retry (attempt {self.request.retries + 1}/{self.max_retries}) in {countdown}s")
                raise self.retry(countdown=countdown, exc=Exception(error_msg))
            else:
                publish_logger.error(f"   {log_prefix} ❌ Max retries reached, giving up")
                publish_logger.info(f"="*80)
                publish_logger.error(f"{log_prefix} ❌ PUBLISH WORKFLOW FAILED")
                publish_logger.info(f"   {log_prefix} Duration: {duration_ms}ms")
                publish_logger.info("="*80)
                return {"success": False, "error": error_msg}
                
    except Exception as e:
        duration_ms = int((time.time() - start_time) * 1000)
        # Try to use log_prefix if available
        try:
            prefix = log_prefix
        except:
            prefix = "[unknown-site]"
        
        publish_logger.error(f"="*80)
        publish_logger.error(f"{prefix} 💥 PUBLISH WORKFLOW EXCEPTION")
        publish_logger.error(f"   {prefix} Exception type: {type(e).__name__}")
        publish_logger.error(f"   {prefix} Exception message: {str(e)}")
        publish_logger.error(f"   {prefix} Duration: {duration_ms}ms")
        publish_logger.error("="*80, exc_info=True)
        
        # Try to log sync event
        try:
            from igny8_core.business.integration.models import SyncEvent
            SyncEvent.objects.create(
                integration=site_integration,
                site=content.site,
                account=content.account,
                event_type='error',
                action='content_publish',
                description=f"Exception publishing '{content.title}' to WordPress",
                success=False,
                content_id=content.id,
                error_message=str(e),
                details={'exception_type': type(e).__name__},
                duration_ms=duration_ms
            )
        except Exception as log_error:
            publish_logger.error(f"Failed to log sync event: {str(log_error)}")
        
        return {"success": False, "error": str(e)}


@shared_task
def process_pending_wordpress_publications() -> Dict[str, Any]:
    """
    Process all content items pending WordPress publication
    """
    try:
        from igny8_core.business.content.models import Content
        from igny8_core.business.integration.models import SiteIntegration
        
        pending_content = Content.objects.filter(
            status='published',
            external_id__isnull=True
        ).select_related('site', 'sector', 'cluster')
        
        if not pending_content.exists():
            publish_logger.info("No content pending WordPress publication")
            return {"success": True, "processed": 0}
        
        active_integrations = SiteIntegration.objects.filter(
            platform='wordpress',
            is_active=True
        )
        
        if not active_integrations.exists():
            publish_logger.warning("No active WordPress integrations found")
            return {"success": False, "error": "No active WordPress integrations"}
        
        processed = 0
        for content in pending_content[:50]:
            for integration in active_integrations.filter(site=content.site):
                publish_content_to_wordpress.delay(content.id, integration.id)
                processed += 1
                break
        
        publish_logger.info(f"Queued {processed} content items for WordPress publication")
        return {"success": True, "processed": processed}
        
    except Exception as e:
        publish_logger.error(f"Error processing pending publications: {str(e)}", exc_info=True)
        return {"success": False, "error": str(e)}
