"""
Unit tests for Twitter scraper.
"""

import pytest
from datetime import datetime, timezone
from unittest.mock import Mock, patch, MagicMock

from app.scrapers.twitter_scraper import (
    TwitterScraper,
    RateLimitInfo,
    TweetData,
    create_twitter_scraper
)


@pytest.fixture
def mock_tweepy_client():
    """Mock tweepy Client."""
    with patch('app.scrapers.twitter_scraper.tweepy.Client') as mock:
        yield mock


@pytest.fixture
def test_bearer_token():
    """Test bearer token."""
    return "test_bearer_token_12345"


@pytest.fixture
def test_scraper(test_bearer_token):
    """Create test scraper instance."""
    with patch('app.scrapers.twitter_scraper.tweepy.Client'):
        scraper = TwitterScraper(
            bearer_token=test_bearer_token,
            max_tweets_per_hour=100,
            rate_limit_alert_threshold=0.9,
            vip_match_ids=[1, 2, 3]
        )
        return scraper


class TestRateLimitInfo:
    """Test RateLimitInfo dataclass."""
    
    def test_usage_percentage(self):
        """Test usage percentage calculation."""
        info = RateLimitInfo(remaining=100, limit=1000, reset_time=None)
        assert info.usage_percentage == 0.9
        
        info = RateLimitInfo(remaining=0, limit=1000, reset_time=None)
        assert info.usage_percentage == 1.0
        
        info = RateLimitInfo(remaining=1000, limit=1000, reset_time=None)
        assert info.usage_percentage == 0.0


class TestTweetData:
    """Test TweetData dataclass."""
    
    def test_tweet_data_creation(self):
        """Test creating TweetData instance."""
        tweet = TweetData(
            tweet_id="123456789",
            text="Test tweet content",
            created_at=datetime.now(timezone.utc),
            retweet_count=10,
            like_count=20,
            match_id=1
        )
        
        assert tweet.tweet_id == "123456789"
        assert tweet.source == "twitter"
        assert tweet.match_id == 1
        assert tweet.retweet_count == 10
        assert tweet.like_count == 20


class TestTwitterScraper:
    """Test TwitterScraper class."""
    
    def test_scraper_initialization(self, test_bearer_token):
        """Test scraper initialization."""
        with patch('app.scrapers.twitter_scraper.tweepy.Client'):
            scraper = TwitterScraper(
                bearer_token=test_bearer_token,
                max_tweets_per_hour=1000,
                rate_limit_alert_threshold=0.9,
                vip_match_ids=[1, 2, 3]
            )
            
            assert scraper.bearer_token == test_bearer_token
            assert scraper.max_tweets_per_hour == 1000
            assert scraper.rate_limit_alert_threshold == 0.9
            assert scraper.vip_match_ids == [1, 2, 3]
            assert scraper.vip_mode_only is False
            assert scraper.api_calls_made == 0
    
    def test_check_rate_limit_normal(self, test_scraper):
        """Test rate limit check under normal conditions."""
        test_scraper.api_calls_made = 800  # 80% usage
        assert test_scraper._check_rate_limit() is True
    
    def test_check_rate_limit_alert(self, test_scraper, caplog):
        """Test rate limit alert at threshold."""
        test_scraper.api_calls_made = 900  # 90% usage
        
        with caplog.at_level("WARNING"):
            result = test_scraper._check_rate_limit()
        
        assert result is True
        assert "Rate limit approaching" in caplog.text
    
    def test_check_rate_limit_exceeded(self, test_scraper, caplog):
        """Test rate limit exceeded."""
        test_scraper.api_calls_made = 1000  # 100% usage
        
        with caplog.at_level("ERROR"):
            result = test_scraper._check_rate_limit()
        
        assert result is False
        assert "Rate limit reached" in caplog.text
    
    def test_enable_vip_mode_only(self, test_scraper, caplog):
        """Test enabling VIP mode."""
        with caplog.at_level("WARNING"):
            test_scraper._enable_vip_mode_only()
        
        assert test_scraper.vip_mode_only is True
        assert "ENTERING DEGRADED MODE" in caplog.text
        assert "VIP match IDs:" in caplog.text
    
    def test_scrape_non_vip_in_vip_mode(self, test_scraper):
        """Test scraping non-VIP match when VIP mode is active."""
        test_scraper.vip_mode_only = True
        
        with pytest.raises(ValueError, match="Match 4 is not VIP"):
            test_scraper.scrape_twitter_match(
                match_id=4,
                keywords=["test"],
                max_results=10
            )
    
    def test_scrape_vip_in_vip_mode(self, test_scraper, mock_tweepy_client):
        """Test scraping VIP match when VIP mode is active."""
        test_scraper.vip_mode_only = True
        
        # Mock API response
        mock_response = Mock()
        mock_response.data = [
            Mock(
                id="123456789",
                text="Test tweet",
                created_at=datetime.now(timezone.utc),
                public_metrics={'retweet_count': 10, 'like_count': 20}
            )
        ]
        mock_tweepy_client.return_value.search_recent_tweets.return_value = mock_response
        
        result = test_scraper.scrape_twitter_match(
            match_id=1,
            keywords=["test"],
            max_results=10
        )
        
        assert len(result) == 1
        assert result[0].tweet_id == "123456789"
        assert test_scraper.api_calls_made == 1


class TestCreateTwitterScraper:
    """Test create_twitter_scraper factory function."""
    
    def test_factory_function(self, test_bearer_token):
        """Test factory function creates scraper."""
        with patch('app.scrapers.twitter_scraper.TwitterScraper') as MockScraper:
            mock_instance = Mock()
            MockScraper.return_value = mock_instance
            
            result = create_twitter_scraper(
                bearer_token=test_bearer_token,
                vip_match_ids=[1, 2, 3]
            )
            
            MockScraper.assert_called_once()
            assert result == mock_instance
