"""
Celery Tasks for Instagram Data Processing

This module contains background tasks that orchestrate the data processing workflow:
1. Fetch Instagram data (delegates to DataService)
2. Calculate metrics (delegates to DataService)
3. Predict niche (delegates to NicheService)

Architecture:
- Tasks are thin orchestration layers
- Business logic is in service classes
- This makes the code testable and maintainable
"""

from celery import shared_task
from django.utils import timezone
import logging

from .models import InfluencerProfile
from .services import DataService, NicheService
from .instagram_api import InstagramAPIError
from .constants import ProcessingStatus

logger = logging.getLogger(__name__)


# ============================================================================
# MAIN DATA PROCESSING TASK
# ============================================================================

@shared_task(bind=True, max_retries=3)
def process_influencer_data(self, profile_id: int):
    """
    Main task for fetching and processing Instagram data.

    This is the CORE ORCHESTRATION TASK that coordinates the entire data pipeline:

    Step 1: Fetch basic account info (followers, media count)
    Step 2: Fetch account insights (profile views, follower growth)
    Step 3: Fetch audience demographics (age, gender, location)
    Step 4: Fetch media posts and their insights (last 100 posts)
    Step 5: Calculate aggregate metrics (averages, engagement rate)
    Step 6: Trigger AI niche prediction

    All business logic is delegated to service classes for better separation of concerns.

    Args:
        profile_id: InfluencerProfile ID

    Returns:
        dict: Status and processing results
    """
    try:
        # ====================================================================
        # INITIALIZATION
        # ====================================================================
        profile = InfluencerProfile.objects.get(id=profile_id)
        profile.data_processing_status = ProcessingStatus.PROCESSING
        profile.save()

        # Get decrypted access token
        access_token = profile.get_access_token()
        if not access_token:
            raise InstagramAPIError("No access token found")

        if not profile.instagram_business_id:
            raise InstagramAPIError("No Instagram Business Account ID")

        logger.info(f"Starting data processing for {profile.instagram_handle}")
        
        # ====================================================================
        # STEP 1: FETCH BASIC ACCOUNT INFO
        # ====================================================================
        DataService.fetch_account_basic_info(profile, access_token)
        
        # ====================================================================
        # STEP 2: FETCH ACCOUNT-LEVEL INSIGHTS
        # ====================================================================
        DataService.fetch_account_insights(profile, access_token)

        # ====================================================================
        # STEP 3: FETCH AUDIENCE DEMOGRAPHICS
        # ====================================================================
        DataService.fetch_audience_demographics(profile, access_token)
        
        # ====================================================================
        # STEP 4: FETCH MEDIA POSTS AND INSIGHTS
        # ====================================================================
        posts_processed, _posts_without_insights = DataService.fetch_media_posts(profile, access_token)

        # ====================================================================
        # STEP 5: CALCULATE AGGREGATE METRICS
        # ====================================================================
        DataService.calculate_averages(profile)

        # Mark as completed
        profile.data_processing_status = ProcessingStatus.COMPLETED
        profile.last_data_fetch = timezone.now()
        profile.verification_status = True
        profile.error_message = None
        profile.save()

        logger.info(f"Data processing completed for {profile.instagram_handle}")

        # ====================================================================
        # STEP 6: TRIGGER AI NICHE PREDICTION
        # ====================================================================
        predict_niche.delay(profile_id)
        
        return {
            'status': 'success',
            'profile_id': profile_id,
            'posts_processed': posts_processed
        }
        
    except InfluencerProfile.DoesNotExist:
        logger.error(f"InfluencerProfile {profile_id} not found")
        return {'status': 'error', 'message': 'Profile not found'}
    
    except Exception as e:
        logger.error(f"Error processing influencer data: {str(e)}")
        
        # Update profile with error
        try:
            profile = InfluencerProfile.objects.get(id=profile_id)
            profile.data_processing_status = ProcessingStatus.FAILED
            profile.error_message = str(e)
            profile.save()
        except:
            pass

        # Retry the task
        raise self.retry(exc=e, countdown=60)



# ============================================================================
# LEGACY TASK (kept for backwards compatibility)
# ============================================================================

@shared_task
def prepare_data_for_model(profile_id: int):
    """
    Legacy task name - redirects to predict_niche.
    Kept for backwards compatibility with existing queued tasks.
    """
    return predict_niche(profile_id)


# Note: All helper functions have been moved to services/data_helpers.py
# for better code organization and reusability.


@shared_task
def predict_niche(profile_id: int):
    """
    Predict influencer niche using AI/ML model.

    This task delegates to NicheService for the actual prediction logic.

    Args:
        profile_id: InfluencerProfile ID

    Returns:
        dict: Status and predicted niche
    """
    try:
        profile = InfluencerProfile.objects.get(id=profile_id)

        # Delegate to NicheService
        predicted_niche = NicheService.predict_niche(profile)

        # Ensure we have a value (fallback to default if somehow None)
        if not predicted_niche:
            predicted_niche = 'lifestyle'

        # Save to profile
        profile.ai_predicted_niche = predicted_niche
        profile.save()

        logger.info(f"Successfully saved niche '{predicted_niche}' for {profile.instagram_handle}")

        return {
            'status': 'success',
            'profile_id': profile_id,
            'predicted_niche': predicted_niche
        }

    except Exception as e:
        logger.error(f"Error predicting niche: {e}", exc_info=True)
        return {'status': 'error', 'message': str(e)}







