"""Tests for ``ilum.core.auth`` — provider registry, issuer resolution, flag generation."""

from __future__ import annotations

import pytest

from ilum.core.auth import (
    PROVIDER_REGISTRY,
    AuthMode,
    ProviderName,
    detect_auth_mode,
    generate_disable_flags,
    generate_enable_flags,
    get_provider,
    list_providers,
    resolve_issuer_uri,
)
from ilum.errors import AuthError


class TestProviderRegistry:
    def test_all_providers_registered(self) -> None:
        for name in ProviderName:
            assert name in PROVIDER_REGISTRY

    def test_correct_modes(self) -> None:
        assert PROVIDER_REGISTRY[ProviderName.HYDRA].auth_mode is AuthMode.HYDRA
        assert PROVIDER_REGISTRY[ProviderName.GOOGLE].auth_mode is AuthMode.EXTERNAL_OAUTH2
        assert PROVIDER_REGISTRY[ProviderName.OIDC].auth_mode is AuthMode.EXTERNAL_OAUTH2

    def test_all_have_client_id_param(self) -> None:
        for provider in PROVIDER_REGISTRY.values():
            param_names = [p.name for p in provider.params]
            assert "client-id" in param_names, f"{provider.name.value} missing client-id"

    def test_get_provider_valid(self) -> None:
        p = get_provider("google")
        assert p.name is ProviderName.GOOGLE

    def test_get_provider_invalid(self) -> None:
        with pytest.raises(AuthError, match="Unknown auth provider"):
            get_provider("nonexistent")

    def test_list_providers_returns_all(self) -> None:
        providers = list_providers()
        assert len(providers) == len(ProviderName)

    def test_hydra_has_postgresql_extra_flag(self) -> None:
        hydra = PROVIDER_REGISTRY[ProviderName.HYDRA]
        assert "postgresql.enabled=true" in hydra.extra_set_flags


class TestIssuerUriResolution:
    def test_google(self) -> None:
        p = get_provider("google")
        uri = resolve_issuer_uri(p, {})
        assert uri == "https://accounts.google.com"

    def test_keycloak(self) -> None:
        p = get_provider("keycloak")
        uri = resolve_issuer_uri(p, {"url": "https://keycloak.example.com", "realm": "myrealm"})
        assert uri == "https://keycloak.example.com/realms/myrealm"

    def test_cognito(self) -> None:
        p = get_provider("aws-cognito")
        uri = resolve_issuer_uri(p, {"region": "us-east-1", "user-pool-id": "us-east-1_abc123"})
        assert uri == "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_abc123"

    def test_azure_ad(self) -> None:
        p = get_provider("azure-ad")
        uri = resolve_issuer_uri(p, {"tenant-id": "my-tenant-id"})
        assert uri == "https://login.microsoftonline.com/my-tenant-id/v2.0"

    def test_okta(self) -> None:
        p = get_provider("okta")
        uri = resolve_issuer_uri(p, {"domain": "dev-123.okta.com"})
        assert uri == "https://dev-123.okta.com"

    def test_gitlab_default(self) -> None:
        p = get_provider("gitlab")
        uri = resolve_issuer_uri(p, {"url": "https://gitlab.com"})
        assert uri == "https://gitlab.com"

    def test_generic_oidc(self) -> None:
        p = get_provider("oidc")
        uri = resolve_issuer_uri(p, {"issuer-uri": "https://auth.example.com/realms/test"})
        assert uri == "https://auth.example.com/realms/test"

    def test_hydra_empty(self) -> None:
        p = get_provider("hydra")
        uri = resolve_issuer_uri(p, {})
        assert uri == ""

    def test_missing_param_raises(self) -> None:
        p = get_provider("keycloak")
        with pytest.raises(AuthError, match="Missing parameter"):
            resolve_issuer_uri(p, {"url": "https://kc.example.com"})


class TestFlagGeneration:
    def test_hydra_enable_flags(self) -> None:
        p = get_provider("hydra")
        flags = generate_enable_flags(
            p,
            {
                "domain": "ilum.example.com",
                "protocol": "https",
                "client-id": "my-client",
                "client-secret": "my-secret",
            },
        )
        assert "global.security.hydra.enabled=true" in flags
        assert "global.security.hydra.uiDomain=ilum.example.com" in flags
        assert "global.security.hydra.uiProtocol=https" in flags
        assert "global.security.hydra.clientId=my-client" in flags
        assert "global.security.hydra.clientSecret=my-secret" in flags
        assert "postgresql.enabled=true" in flags

    def test_google_enable_flags(self) -> None:
        p = get_provider("google")
        flags = generate_enable_flags(p, {"client-id": "goog-id", "client-secret": "goog-secret"})
        assert "ilum-core.security.type=oauth2" in flags
        assert "global.security.oauth2.issuerUri=https://accounts.google.com" in flags
        assert "global.security.oauth2.clientId=goog-id" in flags
        assert "global.security.oauth2.clientSecret=goog-secret" in flags

    def test_disable_flags(self) -> None:
        flags = generate_disable_flags()
        assert "ilum-core.security.type=internal" in flags
        assert "global.security.hydra.enabled=false" in flags

    def test_keycloak_enable_flags(self) -> None:
        p = get_provider("keycloak")
        flags = generate_enable_flags(
            p,
            {
                "client-id": "kc-id",
                "client-secret": "kc-secret",
                "url": "https://kc.example.com",
                "realm": "test",
            },
        )
        assert "ilum-core.security.type=oauth2" in flags
        assert "global.security.oauth2.issuerUri=https://kc.example.com/realms/test" in flags

    def test_scope_flag(self) -> None:
        p = get_provider("google")
        flags = generate_enable_flags(
            p,
            {"client-id": "id", "client-secret": "sec"},
            scope="openid email profile",
        )
        assert "global.security.oauth2.scope=openid email profile" in flags


class TestDetectAuthMode:
    def test_internal(self) -> None:
        mode, details = detect_auth_mode({"ilum-core": {"security": {"type": "internal"}}})
        assert mode is AuthMode.INTERNAL
        assert details["provider"] == "internal"

    def test_hydra(self) -> None:
        mode, details = detect_auth_mode(
            {
                "global": {
                    "security": {
                        "hydra": {
                            "enabled": True,
                            "uiDomain": "ilum.example.com",
                            "uiProtocol": "https",
                            "clientId": "my-client",
                        }
                    }
                }
            }
        )
        assert mode is AuthMode.HYDRA
        assert details["domain"] == "ilum.example.com"
        assert details["client_id"] == "my-client"

    def test_external_oauth2(self) -> None:
        mode, details = detect_auth_mode(
            {
                "ilum-core": {"security": {"type": "oauth2"}},
                "global": {
                    "security": {
                        "oauth2": {
                            "issuerUri": "https://accounts.google.com",
                            "clientId": "goog-id",
                        }
                    }
                },
            }
        )
        assert mode is AuthMode.EXTERNAL_OAUTH2
        assert details["issuer_uri"] == "https://accounts.google.com"

    def test_empty_values(self) -> None:
        mode, details = detect_auth_mode({})
        assert mode is AuthMode.INTERNAL
