# youtube/services.py
# ... imports ...
import json
import logging
import datetime
import time
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.auth.transport.requests import Request
# CHANGE: Import install/uninstall if we want to suppress warnings, but better to fix via pip
import warnings 

from django.conf import settings
from django.utils import timezone
from apps.social.utils.youtube import YOUTUBE_SCOPES, YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION

logger = logging.getLogger(__name__)

class YouTubeAPIError(Exception): pass
class RateLimitError(Exception): pass

class YouTubeService:

    # --- AUTH ---

    @staticmethod
    def _get_flow():
        return Flow.from_client_secrets_file(
            settings.YOUTUBE_CLIENT_SECRETS_FILE,
            scopes=YOUTUBE_SCOPES,
            redirect_uri=settings.YOUTUBE_REDIRECT_URI
        )

    @staticmethod
    def get_auth_url(state=None):
        flow = YouTubeService._get_flow()
        auth_url, generated_state = flow.authorization_url(
            access_type='offline', prompt='consent', state=state
        )
        return auth_url, generated_state

    @staticmethod
    def exchange_code_for_token(code):
        flow = YouTubeService._get_flow()
        flow.fetch_token(code=code)
        creds = flow.credentials
        return json.loads(creds.to_json())

    @staticmethod
    def _get_credentials(account):
        if not account.credentials_json:
            raise YouTubeAPIError("No token found.")
        
        # FIX 1: Suppress noisy library warnings if necessary
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            creds = Credentials.from_authorized_user_info(account.credentials_json)
            
        if not creds.valid:
            if creds.expired and creds.refresh_token:
                try:
                    logger.info(f"Refreshing token for {account.name}...")
                    # FIX 2: Ensure Request object is correct
                    creds.refresh(Request())
                    # Save refreshed token
                    account.credentials_json = json.loads(creds.to_json())
                    # Recalculate expiration
                    account.expires_at = timezone.now() + datetime.timedelta(hours=1) # Conservative buffer
                    account.save()
                except Exception as e:
                    logger.error(f"Token refresh failed: {e}")
                    account.is_active = False
                    account.save()
                    raise YouTubeAPIError("Token refresh failed")
            elif creds.expired and not creds.refresh_token:
                 logger.error("Token expired and no refresh token found.")
                 account.is_active = False
                 account.save()
                 raise YouTubeAPIError("No refresh token")
        return creds

    @staticmethod
    def _build_client(account):
        try:
            return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, credentials=YouTubeService._get_credentials(account))
        except Exception as e:
            logger.error("Build client failed", exc_info=True)
            raise YouTubeAPIError(str(e))


    # --- FETCHING LOGIC ---

    @staticmethod
    def fetch_user_videos(account):
        """Fetch all videos for a user"""
        youtube = YouTubeService._build_client(account)
        videos = []
        next_page_token = None
        
        # FIX 3: Check if playlist ID exists
        playlist_id = account.credentials_json.get('uploads_playlist_id')
        if not playlist_id:
            logger.error(f"No 'uploads_playlist_id' found in account credentials for {account.name}. Cannot sync videos.")
            return []

        while True:
            try:
                request = youtube.playlistItems().list(
                    part="snippet,contentDetails",
                    playlistId=playlist_id,
                    maxResults=50,
                    pageToken=next_page_token
                )
                response = request.execute()
                
                for item in response.get('items', []):
                    videos.append({
                        'id': item['contentDetails']['videoId'],
                        'snippet': {
                            'title': item['snippet']['title'],
                            'description': item['snippet'].get('description', ''),
                            'publishedAt': item['contentDetails']['videoPublishedAt']
                        }
                    })
                
                next_page_token = response.get('nextPageToken')
                if not next_page_token: break
                time.sleep(0.5)
                
            except HttpError as e:
                # FIX 4: LOG THE ERROR! Don't just return empty.
                logger.error(f"API Error fetching videos for {account.name}: {e.resp.status} {e.content}")
                if e.resp.status == 429: 
                    raise RateLimitError("Quota limit")
                if e.resp.status in [401, 403]:
                    raise YouTubeAPIError(f"Authentication Failed: {e}")
                break
        return videos

    

    @staticmethod
    def fetch_activities_incremental(account):
        youtube = YouTubeService._build_client(account)
        published_after = (timezone.now() - datetime.timedelta(days=2)).isoformat() + 'Z'
        comment_ids = []
        next_page_token = None
        
        try:
            while True:
                request = youtube.activities().list(
                    part='snippet,contentDetails',
                    mine=True, 
                    publishedAfter=published_after,
                    maxResults=50,
                    pageToken=next_page_token
                )
                response = request.execute()
                
                for item in response.get('items', []):
                    if item['snippet']['type'] == 'comment':
                        c_id = item.get('contentDetails', {}).get('comment', {}).get('id')
                        if c_id: comment_ids.append(c_id)
                
                next_page_token = response.get('nextPageToken')
                if not next_page_token: break
                time.sleep(0.5)
                
        except HttpError as e:
            if e.resp.status == 429: raise RateLimitError("Quota limit")
            
        return comment_ids


    @staticmethod
    def fetch_video_comments(account, video_id):
        """Fetch comments for a video"""
        youtube = YouTubeService._build_client(account)
        comments = []
        next_page_token = None
        
        while True:
            try:
                request = youtube.commentThreads().list(
                    part="snippet", 
                    videoId=video_id, 
                    maxResults=100, 
                    order="time", 
                    pageToken=next_page_token
                )
                response = request.execute()
                comments.extend(response.get('items', []))
                next_page_token = response.get('nextPageToken')
                if not next_page_token: break
                time.sleep(1)
                
            except HttpError as e:
                if e.resp.status == 429: raise RateLimitError("Quota limit")
                break
        return comments

    @staticmethod
    def post_reply(account, parent_id, text):
        youtube = YouTubeService._build_client(account)
        request = youtube.comments().insert(
            part="snippet",
            body={"snippet": {"parentId": parent_id, "textOriginal": text}}
        )
        return request.execute()