"""
YouTube transcript çıkarımı modülü
"""
from youtube_transcript_api import YouTubeTranscriptApi
from typing import List, Dict, Optional
import time
import logging
import random
import os

# Logger oluştur
logger = logging.getLogger(__name__)

# Gerçek tarayıcı User-Agent'ları (rotasyon için)
USER_AGENTS = [
    # Chrome (Windows)
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    # Chrome (macOS)
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    # Chrome (Linux)
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    # Firefox (Windows)
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    # Firefox (macOS)
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
    # Safari (macOS)
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15',
    # Edge (Windows)
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
]


class TranscriptExtractor:
    """YouTube transcript çıkarıcı sınıfı"""
    
    def __init__(self, rate_limit: int = 1, time_window: int = 60):
        """
        Args:
            rate_limit: Zaman penceresi başına maksimum istek sayısı (YouTube IP blocking'i önlemek için çok düşük)
            time_window: Zaman penceresi (saniye) - daha uzun süre
        """
        self.rate_limit = rate_limit  # 1 istek/60 saniye (çok konservatif)
        self.time_window = time_window
        self.request_times = []
        self.last_blocked_time = 0
        self.block_count = 0  # Toplam blocking sayısı
        
        # Gerçek tarayıcı header'larını ayarla
        self._setup_browser_headers()
    
    def _setup_browser_headers(self):
        """Gerçek tarayıcı gibi HTTP header'larını ayarla"""
        try:
            import requests
            
            # requests.Session'ın get/post metodlarını patch et
            # Bu, youtube-transcript-api'nin yaptığı tüm isteklere header ekler
            original_get = requests.Session.get
            original_post = requests.Session.post
            
            def patched_get(self, url, **kwargs):
                """requests.Session.get'i patch et - header'ları ekle"""
                headers = kwargs.get('headers', {})
                browser_headers = TranscriptExtractor._get_browser_headers()
                # Mevcut header'ları koru, browser header'larını ekle
                merged_headers = {**browser_headers, **headers}
                kwargs['headers'] = merged_headers
                return original_get(self, url, **kwargs)
            
            def patched_post(self, url, **kwargs):
                """requests.Session.post'i patch et - header'ları ekle"""
                headers = kwargs.get('headers', {})
                browser_headers = TranscriptExtractor._get_browser_headers()
                # Mevcut header'ları koru, browser header'larını ekle
                merged_headers = {**browser_headers, **headers}
                kwargs['headers'] = merged_headers
                return original_post(self, url, **kwargs)
            
            # Patch'i uygula (sadece bir kez)
            if not hasattr(requests.Session, '_browser_headers_patched'):
                requests.Session.get = patched_get
                requests.Session.post = patched_post
                requests.Session._browser_headers_patched = True
                
                logger.info("[HEADERS] ✅ requests.Session patch edildi - Gerçek tarayıcı header'ları eklendi")
        except Exception as e:
            logger.warning(f"[HEADERS] ⚠️ Header patch edilemedi: {e}")
    
    @staticmethod
    def _get_browser_headers() -> Dict[str, str]:
        """Gerçek tarayıcı header'larını döndür"""
        user_agent = random.choice(USER_AGENTS)
        
        headers = {
            'User-Agent': user_agent,
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.9,tr;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'DNT': '1',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
            'Sec-Fetch-Dest': 'document',
            'Sec-Fetch-Mode': 'navigate',
            'Sec-Fetch-Site': 'none',
            'Sec-Fetch-User': '?1',
            'Cache-Control': 'max-age=0',
            'Referer': 'https://www.youtube.com/',
        }
        
        logger.debug(f"[HEADERS] Header'lar oluşturuldu - User-Agent: {user_agent[:50]}...")
        return headers
    
    def _check_rate_limit(self):
        """Rate limiting kontrolü (YouTube IP blocking'i önlemek için)"""
        now = time.time()
        
        # Eğer son 10 dakikada IP blocking hatası aldıysak, çok daha uzun bekle
        if self.last_blocked_time > 0 and (now - self.last_blocked_time) < 600:
            # Blocking sayısına göre bekleme süresini artır
            base_wait = 300  # 5 dakika base
            wait_time = base_wait + (self.block_count * 60)  # Her blocking'de +1 dakika
            wait_time = min(wait_time, 1800)  # Maksimum 30 dakika
            
            logger.warning(f"[RATE_LIMIT] IP blocking sonrası bekleme: {wait_time} saniye ({wait_time/60:.1f} dakika) - Blocking sayısı: {self.block_count}")
            logger.warning(f"[RATE_LIMIT] Son blocking: {int(now - self.last_blocked_time)} saniye önce")
            time.sleep(wait_time)
            # Reset etme, 10 dakika boyunca hatırla
        
        # Son time_window saniyesindeki istekleri filtrele
        self.request_times = [t for t in self.request_times if now - t < self.time_window]
        
        # Rate limit aşıldıysa bekle
        if len(self.request_times) >= self.rate_limit:
            sleep_time = self.time_window - (now - self.request_times[0])
            if sleep_time > 0:
                logger.info(f"[RATE_LIMIT] Rate limit aşıldı ({len(self.request_times)}/{self.rate_limit} istek), {sleep_time:.1f} saniye bekleniyor...")
                time.sleep(sleep_time)
                # Tekrar filtrele
                now = time.time()
                self.request_times = [t for t in self.request_times if now - t < self.time_window]
        
        # İstekler arasında minimum bekleme (YouTube blocking'i önlemek için)
        # Human-like behavior: Random bekleme (10-20 saniye arası)
        if self.request_times:
            time_since_last = now - self.request_times[-1]
            # Blocking varsa daha uzun bekle
            if self.block_count > 0:
                min_interval = 30 + random.uniform(0, 30)  # 30-60 saniye random
            else:
                min_interval = 10 + random.uniform(0, 10)  # 10-20 saniye random
            
            if time_since_last < min_interval:
                sleep_time = min_interval - time_since_last
                logger.info(f"[RATE_LIMIT] Human-like bekleme: {sleep_time:.1f} saniye (Son istek: {time_since_last:.1f} saniye önce, Blocking sayısı: {self.block_count})")
                time.sleep(sleep_time)
        
        # İstek zamanını kaydet
        self.request_times.append(time.time())
        logger.debug(f"[RATE_LIMIT] İstek kaydedildi (Toplam aktif istek: {len(self.request_times)})")
    
    def fetch_transcript(self, video_id: str, 
                        languages: List[str] = ['en']) -> Optional[List[Dict]]:
        """
        Transcript çıkar (sync)
        
        Args:
            video_id: YouTube video ID
            languages: Öncelik sırasına göre dil listesi
        
        Returns:
            Transcript listesi veya None
        """
        logger.info(f"[TRANSCRIPT] Video {video_id} için transcript çıkarımı başlatılıyor (Diller: {languages})")
        
        # Rate limiting kontrolü
        self._check_rate_limit()
        
        try:
            logger.debug(f"[TRANSCRIPT] YouTube Transcript API çağrısı yapılıyor: video_id={video_id}")
            
            # YouTube Transcript API kullanımı (yeni versiyon)
            # API instance oluştur ve fetch() metodunu kullan
            api = YouTubeTranscriptApi()
            fetched_transcript = api.fetch(video_id, languages=languages)
            
            # Eski formatı döndürmek için to_raw_data() kullan
            # Format: [{'text': '...', 'start': 1.36, 'duration': 1.68}, ...]
            transcript = fetched_transcript.to_raw_data()
            
            transcript_count = len(transcript) if transcript else 0
            logger.info(f"[TRANSCRIPT] ✅ Video {video_id} transcript'i başarıyla çıkarıldı ({transcript_count} segment)")
            
            return transcript
        except Exception as e:
            error_msg = str(e)
            error_type = type(e).__name__
            
            logger.error(f"[TRANSCRIPT] ❌ Video {video_id} transcript çıkarımı başarısız: {error_type} - {error_msg[:200]}")
            
            # IP blocking hatası tespit edilirse işaretle
            if "blocking" in error_msg.lower() or "blocked" in error_msg.lower() or "IP" in error_msg or "IpBlocked" in error_type:
                self.last_blocked_time = time.time()
                self.block_count += 1
                wait_time = 300 + (self.block_count * 60)  # 5 dakika + (blocking sayısı * 1 dakika)
                wait_time = min(wait_time, 1800)  # Maksimum 30 dakika
                
                logger.error(f"[TRANSCRIPT] 🚫 IP blocking tespit edildi! Video: {video_id}")
                logger.error(f"[TRANSCRIPT] Toplam blocking sayısı: {self.block_count}, Sonraki isteklerde {wait_time} saniye ({wait_time/60:.1f} dakika) bekleme yapılacak")
                logger.warning(f"[TRANSCRIPT] IP blocking detayları: {error_msg[:500]}")
                
                # Çok fazla blocking varsa uyar
                if self.block_count >= 3:
                    logger.error(f"[TRANSCRIPT] ⚠️ UYARI: {self.block_count} kez IP blocking alındı! YouTube IP'nizi geçici olarak engellemiş olabilir.")
                    logger.error(f"[TRANSCRIPT] Öneriler: 1) Daha uzun bekleme (30+ dakika), 2) Farklı IP kullan, 3) Proxy/VPN kullan")
            
            return None

