import os
from unittest.mock import MagicMock, patch

import pytest

from lib.clients.jackett import Jackett
from lib.domain.torrent import TorrentStream

# Load fixture data
FIXTURE_PATH = os.path.join(os.path.dirname(__file__), "../fixtures/jackett_response.xml")
with open(FIXTURE_PATH) as f:
    XML_RESPONSE = f.read()


@pytest.fixture
def jackett_client():
    # Mock notification function
    mock_notification = MagicMock()
    mock_session = MagicMock()
    # Mock settings
    with patch("lib.clients.jackett.get_jackett_timeout", return_value=10):
        client = Jackett(
            host="http://localhost",
            apikey="testapikey",
            port="9117",
            notification=mock_notification,
            session=mock_session,
        )
    return client


def test_jackett_initialization(jackett_client):
    assert jackett_client.host == "http://localhost"
    assert jackett_client.apikey == "testapikey"
    assert "9117" in jackett_client.base_url


@patch("lib.clients.jackett.get_setting", return_value=False)  # Disable season packs
@patch("lib.clients.jackett.get_jackett_timeout", return_value=10)
def test_search_movie(mock_timeout, mock_get_setting, jackett_client):
    # Setup mock response
    mock_response = MagicMock()
    mock_response.status_code = 200
    mock_response.content = XML_RESPONSE.encode("utf-8")

    # Configure injected mock session
    jackett_client.session.get.return_value = mock_response

    results = jackett_client.search("Big Buck Bunny", "movies")

    assert results is not None
    assert len(results) == 2

    # Verify first result
    res1 = results[0]
    assert isinstance(res1, TorrentStream)
    assert res1.title == "Big Buck Bunny 1080p"
    assert res1.seeders == 100
    assert res1.peers == 200
    assert res1.size == "1073741824"
    assert res1.indexer == "Jackett"
    assert res1.infoHash == "1234567890abcdef1234567890abcdef12345678"


@patch("lib.clients.jackett.get_setting", return_value=True)  # Enable season packs
@patch("lib.clients.jackett.get_jackett_timeout", return_value=10)
def test_search_tv_show(mock_timeout, mock_get_setting, jackett_client):
    # Setup mock response
    mock_response = MagicMock()
    mock_response.status_code = 200
    mock_response.content = XML_RESPONSE.encode("utf-8")

    # Configure injected mock session
    jackett_client.session.get.return_value = mock_response

    # Search for S01E01
    results = jackett_client.search("Big Buck Bunny", "tv", season=1, episode=1)

    assert results is not None
    # Should call twice: once for episode, once for season pack
    assert jackett_client.session.get.call_count == 2
    # Results are extended from both calls (duplicate xml used for simplicity)
    assert len(results) == 4


def test_parse_response_error(jackett_client):
    mock_response = MagicMock()
    mock_response.content = b"Invalid XML"

    results = jackett_client.parse_response(mock_response)
    assert results is None


def test_extract_result(jackett_client):
    item = {
        "title": "Test Title",
        "link": "magnet:?xt=urn:btih:hash",
        "size": "100",
        "pubDate": "2023-01-01",
        "jackettindexer": {"#text": "Tracker"},
        "torznab:attr": [
            {"@name": "seeders", "@value": "10"},
            {"@name": "peers", "@value": "5"},
            {"@name": "infohash", "@value": "hash"},
        ],
    }

    results = []
    jackett_client.extract_result(results, item)

    assert len(results) == 1
    res = results[0]
    assert res.title == "Test Title"
    assert res.seeders == 10
    assert res.peers == 5


def test_jackett_url_with_year_parameter(jackett_client):
    url = jackett_client._build_url(
        "http://localhost:9117/api/v2.0/indexers/all/results/torznab/api?apikey=test",
        "Inception",
        "movies",
        year=2010,
    )

    assert "&year=2010" in url
    assert "&t=movie" in url
    assert "&q=Inception" in url


def test_jackett_url_without_year_parameter(jackett_client):
    url = jackett_client._build_url(
        "http://localhost:9117/api/v2.0/indexers/all/results/torznab/api?apikey=test",
        "Inception",
        "movies",
    )

    assert "&year=" not in url
    assert "&t=movie" in url
    assert "&q=Inception" in url


def test_jackett_search_with_year_passes_to_indexer(jackett_client):
    mock_response = MagicMock()
    mock_response.status_code = 200
    mock_response.content = b"""<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0" xmlns:torznab="http://torznab.com/schemas/2015/feed">
        <channel>
            <item>
                <title>Test</title>
                <size>100</size>
                <pubDate>2023-01-01</pubDate>
            </item>
        </channel>
    </rss>"""

    jackett_client.session.get.return_value = mock_response

    with patch("lib.clients.jackett.get_jackett_timeout", return_value=10):
        jackett_client.search("Inception", "movies", year=2010)

    call_args = jackett_client.session.get.call_args
    url = call_args[0][0]
    assert "&year=2010" in url
