from __future__ import annotations

import datetime as dt

import pytest

import worai.seoreport.analytics as ga


def test_payload_and_filters_helpers() -> None:
    payload = ga._build_report_payload(
        dt.date(2026, 1, 1),
        dt.date(2026, 1, 2),
        ["sessions"],
        dimensions=["date"],
        keep_empty_rows=True,
        order_by_dimension="date",
    )
    assert payload["metrics"][0]["name"] == "sessions"
    assert payload["dimensions"][0]["name"] == "date"
    assert ga._starts_with("field", "Org")["filter"]["stringFilter"]["matchType"] == "BEGINS_WITH"
    assert "orGroup" in ga._or_filter([{"x": 1}])


def test_parse_and_normalize_helpers() -> None:
    row = {"metricValues": [{"value": "3"}, {"value": "2.5"}]}
    parsed = ga._parse_metrics_row(row, ["sessions", "engagementRate"])
    assert parsed["sessions"] == 3.0
    assert parsed["engagementRate"] == 2.5

    daily = ga._parse_daily(
        {"rows": [{"dimensionValues": [{"value": "20260101"}], "metricValues": [{"value": "4"}]}]},
        ["sessions"],
    )
    assert daily["20260101"]["sessions"] == 4.0

    norm = ga._normalize_metrics(
        {
            "sessions": 10,
            "totalUsers": 9,
            "engagedSessions": 8,
            "averageSessionDuration": 7,
            "screenPageViews": 6,
        }
    )
    assert norm["users"] == 9

    final = ga._finalize({"sessions": 2, "users": 2, "engaged_sessions": 1, "views": 3, "total_duration": 10})
    assert final["engagement_rate"] == 0.5
    assert final["avg_session_duration"] == 5


def test_channel_group_resolution(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(ga, "ga_get_metadata", lambda *_a, **_k: {"dimensions": [{"uiName": "AI", "apiName": "sessionCustomChannelGroup:123"}]})
    assert ga.resolve_channel_group_api_name(object(), "p", "AI", None) == "sessionCustomChannelGroup:123"
    assert ga.resolve_channel_group_api_name(object(), "p", "AI", "999") == "sessionCustomChannelGroup:999"


def test_fetch_breakdowns_and_daily(monkeypatch: pytest.MonkeyPatch) -> None:
    calls = {"n": 0}

    def _stub(_session, _pid, payload):
        calls["n"] += 1
        if payload.get("dimensions") and payload["dimensions"][0]["name"] == "sessionSource":
            return {"rows": [{"dimensionValues": [{"value": "chatgpt.com"}], "metricValues": [{"value": "11"}]}]}
        return {"rows": [{"dimensionValues": [{"value": "20260101"}], "metricValues": [{"value": "5"}]}]}

    monkeypatch.setattr(ga, "ga_post", _stub)
    breakdown = ga.fetch_ai_source_breakdown(object(), "p", dt.date(2026, 1, 1), dt.date(2026, 1, 2), "chatgpt")
    assert breakdown["chatgpt.com"]["sessions"] == 11

    daily = ga.fetch_ga_daily_sessions(
        object(), "p", dt.date(2026, 1, 1), dt.date(2026, 1, 2), "chatgpt", "AI", None
    )
    assert daily["method"] == "source_regex"
    assert "20260101" in daily["total"]


def test_build_analytics_period_and_build_analytics(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(
        ga,
        "fetch_ga_period",
        lambda *_a, **_k: {
            "method": "source_regex",
            "total_raw": {"sessions": 10, "totalUsers": 9, "engagedSessions": 8, "averageSessionDuration": 2, "screenPageViews": 5},
            "direct_raw": {"sessions": 2, "totalUsers": 2, "engagedSessions": 2, "averageSessionDuration": 1, "screenPageViews": 1},
            "ai_raw": {"sessions": 1, "totalUsers": 1, "engagedSessions": 1, "averageSessionDuration": 1, "screenPageViews": 1},
            "organic_raw": {"sessions": 3, "totalUsers": 3, "engagedSessions": 2, "averageSessionDuration": 1, "screenPageViews": 2},
        },
    )
    monkeypatch.setattr(ga, "fetch_ai_source_breakdown", lambda *_a, **_k: {"chatgpt.com": {"sessions": 1}})
    monkeypatch.setattr(
        ga,
        "fetch_ga_daily_sessions",
        lambda *_a, **_k: {
            "total": {"20260101": {"sessions": 10}},
            "ai": {"20260101": {"sessions": 1}},
            "direct": {"20260101": {"sessions": 2}},
            "organic": {"20260101": {"sessions": 3}},
        },
    )
    options = ga.GaOptions(
        property_id="p",
        client_secrets="c.json",
        token="t.json",
        port=0,
        direct_share=0.5,
        source_regex="chatgpt",
        channel_group_name="AI",
    )
    period = ga.build_analytics_period("Last 7 days", dt.date(2026, 1, 1), dt.date(2026, 1, 7), object(), options, None)
    assert period["name"] == "Last 7 days"
    assert period["trend"][0]["ai_sessions"] == 2

    monkeypatch.setattr(ga, "resolve_channel_group_api_name", lambda *_a, **_k: None)
    monkeypatch.setattr(ga, "AuthorizedSession", lambda _creds: object())
    monkeypatch.setattr(ga, "build_analytics_period", lambda name, *_a, **_k: {"name": name, "totals": {}, "organic_totals": {}})
    out = ga.build_analytics(object(), options, dt.date(2026, 1, 7), [7, 30], 2)
    assert len(out["periods"]) == 2
    assert out["method"] == "source_regex"


def test_ga_post_and_metadata_error() -> None:
    class _Resp:
        def __init__(self, code: int):
            self.status_code = code
            self.text = "bad"

        @staticmethod
        def json():
            return {}

    class _Session:
        @staticmethod
        def post(*_a, **_k):
            return _Resp(500)

        @staticmethod
        def get(*_a, **_k):
            return _Resp(500)

    with pytest.raises(RuntimeError):
        ga.ga_post(_Session(), "p", {})
    with pytest.raises(RuntimeError):
        ga.ga_get_metadata(_Session(), "p")
