"""
Profile Service for Influencer Profile Management

This service handles all business logic related to influencer profiles:
1. Profile retrieval and filtering
2. Profile updates and data refresh
3. Access control and permissions
4. Profile search and discovery

Separation of Concerns:
- This service focuses on profile management business logic
- OAuth is handled by OAuthService
- Data fetching is handled by DataService
- Views only handle HTTP request/response
"""

import logging
from typing import Optional, Dict, Any, List
from django.db.models import QuerySet
from django.contrib.auth import get_user_model

from ..models import InfluencerProfile, MediaPost
from ..constants import ErrorMessages

User = get_user_model()
logger = logging.getLogger(__name__)


class ProfileService:
    """
    Service class for managing influencer profiles.
    
    This class encapsulates all profile-related business logic,
    making it reusable and testable independent of Django views.
    """
    
    @staticmethod
    def get_profile_for_user(user) -> Optional[InfluencerProfile]:
        """
        Get the influencer profile for a specific user.
        
        Args:
            user: User instance
            
        Returns:
            InfluencerProfile or None if not found
        """
        try:
            return InfluencerProfile.objects.get(user=user)
        except InfluencerProfile.DoesNotExist:
            logger.warning(f"No profile found for user {user.id}")
            return None
    
    @staticmethod
    def get_profiles_for_business(
        niche: Optional[str] = None,
        min_followers: Optional[int] = None,
        min_engagement: Optional[float] = None
    ) -> QuerySet:
        """
        Get filtered list of influencer profiles for business users.
        
        Only returns verified influencers with completed data processing.
        
        Args:
            niche: Filter by AI-generated niche
            min_followers: Minimum follower count
            min_engagement: Minimum engagement rate percentage
            
        Returns:
            QuerySet of InfluencerProfile objects
        """
        queryset = InfluencerProfile.objects.filter(
            verification_status=True,
            data_processing_status='COMPLETED'
        )
        
        if niche:
            queryset = queryset.filter(ai_predicted_niche__iexact=niche)
            logger.info(f"Filtering profiles by niche: {niche}")
        
        if min_followers:
            queryset = queryset.filter(followers_count__gte=min_followers)
            logger.info(f"Filtering profiles by min followers: {min_followers}")
        
        if min_engagement:
            queryset = queryset.filter(engagement_rate_percent__gte=min_engagement)
            logger.info(f"Filtering profiles by min engagement: {min_engagement}")
        
        return queryset
    
    @staticmethod
    def can_refresh_profile(profile: InfluencerProfile) -> tuple[bool, Optional[str]]:
        """
        Check if a profile can be refreshed.
        
        Args:
            profile: InfluencerProfile instance
            
        Returns:
            Tuple of (can_refresh: bool, error_message: str or None)
        """
        if profile.data_processing_status == 'PROCESSING':
            return False, ErrorMessages.DATA_ALREADY_PROCESSING
        
        return True, None
    
    @staticmethod
    def mark_profile_for_refresh(profile: InfluencerProfile) -> None:
        """
        Mark a profile as pending for data refresh.
        
        Args:
            profile: InfluencerProfile instance
        """
        profile.data_processing_status = 'PENDING'
        profile.save(update_fields=['data_processing_status'])
        logger.info(f"Marked profile {profile.id} for data refresh")
    
    @staticmethod
    def get_available_niches() -> List[str]:
        """
        Get list of all available niches from existing profiles.
        
        Returns:
            List of unique niche names
        """
        niches = InfluencerProfile.objects.filter(
            ai_predicted_niche__isnull=False
        ).values_list('ai_predicted_niche', flat=True).distinct()
        
        return list(niches)
    
    @staticmethod
    def get_media_posts_for_profile(profile_id: int) -> QuerySet:
        """
        Get all media posts for a specific profile.
        
        Args:
            profile_id: ID of the influencer profile
            
        Returns:
            QuerySet of MediaPost objects
        """
        return MediaPost.objects.filter(influencer_id=profile_id)
    
    @staticmethod
    def get_media_posts_for_user(user) -> QuerySet:
        """
        Get all media posts for a user's profile.
        
        Args:
            user: User instance
            
        Returns:
            QuerySet of MediaPost objects, or empty queryset if no profile
        """
        try:
            profile = InfluencerProfile.objects.get(user=user)
            return MediaPost.objects.filter(influencer=profile)
        except InfluencerProfile.DoesNotExist:
            return MediaPost.objects.none()

