"""Tests for SynupClient."""

import pytest
import requests_mock

from synup import SynupAPIError, SynupClient


@pytest.fixture
def client():
    return SynupClient(api_key="test-api-key")


@pytest.fixture
def locations_response():
    return {
        "data": {
            "allLocations": {
                "edges": [
                    {
                        "cursor": "TG9jYXRpb246MTQwMjQ=",
                        "node": {
                            "id": "TG9jYXRpb246MTQwMjQ=",
                            "accountId": 100,
                            "name": "Stumptown",
                            "city": "New York",
                            "countryIso": "US",
                        },
                    },
                    {
                        "cursor": "TG9jYXRpb246MTQwMjM=",
                        "node": {
                            "id": "TG9jYXRpb246MTQwMjM=",
                            "accountId": 100,
                            "name": "S2nicetestinky",
                            "city": "Miami",
                            "countryIso": "US",
                        },
                    },
                ],
                "pageInfo": {
                    "hasNextPage": True,
                    "hasPreviousPage": False,
                },
            }
        }
    }


@pytest.fixture
def locations_response_last_page():
    return {
        "data": {
            "allLocations": {
                "edges": [
                    {
                        "cursor": "TG9jYXRpb246MTQwMjI=",
                        "node": {
                            "id": "TG9jYXRpb246MTQwMjI=",
                            "accountId": 100,
                            "name": "Last Location",
                            "city": "Boston",
                            "countryIso": "US",
                        },
                    },
                ],
                "pageInfo": {
                    "hasNextPage": False,
                    "hasPreviousPage": True,
                },
            }
        }
    }


def test_client_uses_default_base_url():
    client = SynupClient(api_key="key")
    assert client._base_url == "https://api.synup.com"


def test_client_uses_custom_base_url():
    client = SynupClient(api_key="key", base_url="https://custom.synup.com")
    assert client._base_url == "https://custom.synup.com"


def test_client_strips_trailing_slash_from_base_url():
    client = SynupClient(api_key="key", base_url="https://api.synup.com/")
    assert client._base_url == "https://api.synup.com"


def test_client_sets_auth_headers():
    client = SynupClient(api_key="my-key")
    assert client._session.headers["Authorization"] == "API my-key"
    assert client._session.headers["Content-Type"] == "application/json"


def test_fetch_all_locations_single_page(client, locations_response):
    with requests_mock.Mocker() as m:
        m.get(
            "https://api.synup.com/api/v4/locations",
            json=locations_response,
        )
        result = client.fetch_all_locations(first=2)

    assert isinstance(result, dict)
    assert "locations" in result
    assert "page_info" in result
    assert "raw" in result
    assert len(result["locations"]) == 2
    assert result["locations"][0]["name"] == "Stumptown"
    assert result["locations"][1]["name"] == "S2nicetestinky"
    assert result["page_info"]["has_next_page"] is True
    assert result["page_info"]["has_previous_page"] is False
    assert result["page_info"]["start_cursor"] == "TG9jYXRpb246MTQwMjQ="
    assert result["page_info"]["end_cursor"] == "TG9jYXRpb246MTQwMjM="
    assert m.call_count == 1
    assert m.last_request.query == "first=2"


def test_fetch_all_locations_with_after(client, locations_response):
    with requests_mock.Mocker() as m:
        m.get(
            "https://api.synup.com/api/v4/locations",
            json=locations_response,
        )
        client.fetch_all_locations(first=2, after="TG9jYXRpb246MTQwMjQ=")

    query = m.last_request.query
    assert "first=2" in query
    assert "after=" in query
    assert "TG9jYXRpb246MTQwMjQ" in query or "tg9jyxrpb246mtqwmjq" in query.lower()


def test_fetch_all_locations_raises_on_error(client):
    with requests_mock.Mocker() as m:
        m.get(
            "https://api.synup.com/api/v4/locations",
            status_code=401,
            text="Unauthorized",
        )
        with pytest.raises(SynupAPIError) as exc_info:
            client.fetch_all_locations()

    assert exc_info.value.status_code == 401
    assert exc_info.value.response_body == "Unauthorized"


def test_fetch_all_locations_fetch_all_true(
    client, locations_response, locations_response_last_page
):
    with requests_mock.Mocker() as m:
        m.get(
            "https://api.synup.com/api/v4/locations",
            [
                {"json": locations_response},
                {"json": locations_response_last_page},
            ],
        )
        result = client.fetch_all_locations(fetch_all=True, page_size=2)

    assert isinstance(result, list)
    assert len(result) == 3
    assert result[0]["name"] == "Stumptown"
    assert result[1]["name"] == "S2nicetestinky"
    assert result[2]["name"] == "Last Location"
    assert m.call_count == 2
    # First call: first=2 only
    assert "first=2" in m.request_history[0].query
    assert "after" not in m.request_history[0].query
    # Second call: first=2&after=<cursor>
    assert "first=2" in m.request_history[1].query
    assert "after=" in m.request_history[1].query


def test_fetch_all_locations_fetch_all_single_page(client, locations_response_last_page):
    with requests_mock.Mocker() as m:
        m.get(
            "https://api.synup.com/api/v4/locations",
            json=locations_response_last_page,
        )
        result = client.fetch_all_locations(fetch_all=True, page_size=10)

    assert isinstance(result, list)
    assert len(result) == 1
    assert result[0]["name"] == "Last Location"
    assert m.call_count == 1


def test_fetch_all_locations_empty_response(client):
    empty_response = {
        "data": {
            "allLocations": {
                "edges": [],
                "pageInfo": {"hasNextPage": False, "hasPreviousPage": False},
            }
        }
    }
    with requests_mock.Mocker() as m:
        m.get("https://api.synup.com/api/v4/locations", json=empty_response)
        result = client.fetch_all_locations()

    assert result["locations"] == []
    assert result["page_info"]["has_next_page"] is False
    assert result["page_info"]["start_cursor"] is None
    assert result["page_info"]["end_cursor"] is None
