from __future__ import annotations

from pathlib import Path
from types import SimpleNamespace

import pytest

from worai.core import canonicals as mod
from worai.errors import UsageError


def test_run_dedupe_with_service_account(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    captured: dict[str, object] = {}

    def _sdk(**kwargs):
        captured.update(kwargs)
        return [1, 2]

    monkeypatch.setattr(mod, "_load_oauth_credentials", lambda *_a, **_k: (_ for _ in ()).throw(AssertionError()))
    monkeypatch.setattr(mod, "_load_service_account_credentials", lambda *_a, **_k: object())
    monkeypatch.setitem(
        __import__("sys").modules,
        "wordlift_sdk.google_search_console",
        SimpleNamespace(create_canonical_csv_from_gsc_impressions=_sdk),
    )

    out = mod.run_dedupe(
        mod.CanonicalsDedupeOptions(
            input_csv=str(tmp_path / "in.csv"),
            output_csv=str(tmp_path / "out.csv"),
            site_url="sc-domain:example.com",
            service_account="sa.json",
        )
    )
    assert out == [1, 2]
    assert "credentials" in captured


def test_load_oauth_credentials_uses_existing_token(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    token = tmp_path / "oauth.json"
    token.write_text("{}", encoding="utf-8")

    class _Creds:
        expired = False
        refresh_token = None
        valid = True

    monkeypatch.setitem(
        __import__("sys").modules,
        "wordlift_sdk.google_search_console",
        SimpleNamespace(load_authorized_user_credentials=lambda _p: _Creds()),
    )
    monkeypatch.setattr(mod, "load_credentials", lambda *_a, **_k: (_ for _ in ()).throw(AssertionError()))

    creds = mod._load_oauth_credentials(str(token), None, 8080)
    assert creds.valid is True


def test_load_oauth_credentials_requires_client_secrets_without_valid_token(tmp_path: Path) -> None:
    with pytest.raises(UsageError, match="Authentication is missing"):
        mod._load_oauth_credentials(str(tmp_path / "missing.json"), None, 8080)


def test_load_service_account_credentials_accepts_inline_json(monkeypatch: pytest.MonkeyPatch) -> None:
    seen = {}

    class _ServiceAccountCreds:
        @staticmethod
        def from_service_account_info(info, scopes):
            seen["info"] = info
            seen["scopes"] = scopes
            return object()

    monkeypatch.setattr(mod.service_account, "Credentials", _ServiceAccountCreds)
    creds = mod._load_service_account_credentials('{"client_email":"x@example.com"}')
    assert creds is not None
    assert seen["info"]["client_email"] == "x@example.com"


def test_load_service_account_credentials_rejects_invalid_value() -> None:
    with pytest.raises(UsageError, match="valid file path or a JSON body"):
        mod._load_service_account_credentials("not-a-path-and-not-json")
