"""Save-time credential checks follow each provider, not a shared /health URL."""

from __future__ import annotations

import httpx
import pytest
from src.core.exceptions import ValidationError
from src.domain.connectors.catalog import get_connector
from src.domain.connectors.credential_check import verify_connector_credentials
from src.domain.provider_auth.manifests import authorization_manifest


def test_tracking_connectors_are_not_platform_oauth() -> None:
    assert authorization_manifest("google_analytics") is None
    assert authorization_manifest("google_tag_manager") is None
    assert authorization_manifest("microsoft_clarity") is None
    assert authorization_manifest("google_ads")["grant_family"] == "ads"


def test_connectors_only_ask_for_fields_the_runtime_uses() -> None:
    x_ads = get_connector("x_ads")
    slack = get_connector("slack")
    make = get_connector("make_com")
    n8n = get_connector("n8n")
    assert x_ads is not None and set(x_ads.secret_fields) == {"access_token"}
    assert slack is not None and slack.secret_fields == ("bot_token",)
    assert slack.config_fields == ("default_channel_id",)
    assert make is not None and "api_key" not in make.secret_fields
    assert "api_base_url" not in make.config_fields
    assert n8n is not None and "api_key" not in n8n.secret_fields
    assert "instance_base_url" not in n8n.config_fields


@pytest.mark.anyio
async def test_google_analytics_checks_measurement_id_shape_without_http() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        raise AssertionError(f"Google Analytics must not be probed via {request.url}")

    transport = httpx.MockTransport(handler)
    async with httpx.AsyncClient(transport=transport) as client:
        with pytest.raises(ValidationError, match="Measurement ID"):
            await verify_connector_credentials(
                "google_analytics",
                {"measurement_id": "UA-123"},
                {"api_secret": "secret"},
                client=client,
            )
        await verify_connector_credentials(
            "google_analytics",
            {"measurement_id": "G-ABC123XYZ"},
            {"api_secret": "secret"},
            client=client,
        )


@pytest.mark.anyio
async def test_google_tag_manager_checks_container_id_without_http() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        raise AssertionError(request.url)

    async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
        with pytest.raises(ValidationError, match="Container ID"):
            await verify_connector_credentials(
                "google_tag_manager",
                {"container_id": "G-XXXX"},
                {},
                client=client,
            )


@pytest.mark.anyio
async def test_make_webhook_is_not_called_on_save() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        raise AssertionError(request.url)

    async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
        with pytest.raises(ValidationError, match="https"):
            await verify_connector_credentials(
                "make_com",
                {"webhook_url": "http://hook.example/scenario"},
                {},
                client=client,
            )
        await verify_connector_credentials(
            "make_com",
            {"webhook_url": "https://hook.us1.make.com/abc"},
            {},
            client=client,
        )


@pytest.mark.anyio
async def test_stripe_save_reads_the_account_not_a_health_url() -> None:
    seen: list[str] = []

    def handler(request: httpx.Request) -> httpx.Response:
        seen.append(str(request.url))
        if request.url.path == "/v1/account":
            return httpx.Response(200, json={"id": "acct_123"})
        return httpx.Response(404, json={"error": "missing"})

    async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
        await verify_connector_credentials(
            "stripe",
            {},
            {"secret_key": "sk_test_123"},
            client=client,
        )
    assert seen == ["https://api.stripe.com/v1/account"]


@pytest.mark.anyio
async def test_stripe_rejects_a_bad_secret_key() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(401, json={"error": {"message": "invalid"}})

    async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
        with pytest.raises(ValidationError, match="Stripe rejected"):
            await verify_connector_credentials(
                "stripe",
                {},
                {"secret_key": "sk_bad"},
                client=client,
            )


@pytest.mark.anyio
async def test_slack_uses_auth_test() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        assert request.url.path == "/api/auth.test"
        return httpx.Response(200, json={"ok": False, "error": "invalid_auth"})

    async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
        with pytest.raises(ValidationError, match="Slack rejected"):
            await verify_connector_credentials(
                "slack",
                {},
                {"bot_token": "xoxb-nope"},
                client=client,
            )
