"""Tests validating auth middleware documentation accuracy.

Ensures docs/auth-middleware.md stays in sync with the actual auth
middleware implementation, token format, configuration, and error responses.
"""
from __future__ import annotations

import re
from pathlib import Path

import pytest

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
DOCS_PATH = PROJECT_ROOT / "docs" / "auth-middleware.md"
MIDDLEWARE_PATH = PROJECT_ROOT / "core" / "src" / "greymatter_core" / "security" / "middleware.py"
TOKENS_PATH = PROJECT_ROOT / "core" / "src" / "greymatter_core" / "security" / "tokens.py"
UNIT_TESTS_PATH = PROJECT_ROOT / "core" / "tests" / "test_auth_middleware.py"
INTEGRATION_TESTS_PATH = PROJECT_ROOT / "core" / "tests" / "test_auth_middleware_integration.py"


@pytest.fixture
def doc_content() -> str:
    """Load the auth middleware documentation."""
    assert DOCS_PATH.exists(), f"Documentation file missing: {DOCS_PATH}"
    return DOCS_PATH.read_text()


@pytest.fixture
def middleware_source() -> str:
    """Load the middleware source code."""
    assert MIDDLEWARE_PATH.exists(), f"Middleware source missing: {MIDDLEWARE_PATH}"
    return MIDDLEWARE_PATH.read_text()


@pytest.fixture
def tokens_source() -> str:
    """Load the tokens source code."""
    assert TOKENS_PATH.exists(), f"Tokens source missing: {TOKENS_PATH}"
    return TOKENS_PATH.read_text()


# =========================================================================
# Documentation file exists
# =========================================================================


class TestDocumentationExists:
    """Verify documentation and source files exist."""

    def test_docs_file_exists(self):
        assert DOCS_PATH.exists()

    def test_middleware_source_exists(self):
        assert MIDDLEWARE_PATH.exists()

    def test_tokens_source_exists(self):
        assert TOKENS_PATH.exists()

    def test_unit_tests_exist(self):
        assert UNIT_TESTS_PATH.exists()

    def test_integration_tests_exist(self):
        assert INTEGRATION_TESTS_PATH.exists()


# =========================================================================
# PUBLIC_PATHS documented accurately
# =========================================================================


class TestPublicPathsDocumented:
    """Documented public paths match the code."""

    def test_all_public_paths_in_docs(self, doc_content, middleware_source):
        """Every path in PUBLIC_PATHS should appear in docs."""
        from greymatter_core.security.middleware import PUBLIC_PATHS

        for path in PUBLIC_PATHS:
            assert path in doc_content, (
                f"PUBLIC_PATHS entry '{path}' not found in documentation"
            )

    def test_public_paths_count_matches(self, doc_content):
        """Docs should list the same number of public paths as code."""
        from greymatter_core.security.middleware import PUBLIC_PATHS

        # Count rows in the public paths table (exclude header and separator)
        table_rows = re.findall(r"\| `(/\S+)` \|", doc_content)
        public_path_rows = [r for r in table_rows if r in PUBLIC_PATHS]
        assert len(public_path_rows) == len(PUBLIC_PATHS), (
            f"Docs list {len(public_path_rows)} public paths, "
            f"code has {len(PUBLIC_PATHS)}"
        )


# =========================================================================
# Environment variables documented
# =========================================================================


class TestEnvVarsDocumented:
    """Configuration environment variables match between docs and code."""

    def test_gm_cluster_secret_in_docs(self, doc_content, tokens_source):
        assert "GM_CLUSTER_SECRET" in tokens_source
        assert "GM_CLUSTER_SECRET" in doc_content

    def test_gm_cluster_secret_path_in_docs(self, doc_content, tokens_source):
        assert "GM_CLUSTER_SECRET_PATH" in tokens_source
        assert "GM_CLUSTER_SECRET_PATH" in doc_content

    def test_gm_token_ttl_in_docs(self, doc_content, tokens_source):
        assert "GM_TOKEN_TTL" in tokens_source
        assert "GM_TOKEN_TTL" in doc_content

    def test_default_ttl_documented(self, doc_content, tokens_source):
        """Default TTL value should match between code and docs."""
        # Code default: "86400"
        assert "86400" in tokens_source
        assert "86400" in doc_content


# =========================================================================
# Token format documented
# =========================================================================


class TestTokenFormatDocumented:
    """Token format description matches implementation."""

    def test_four_part_format_documented(self, doc_content):
        """Docs describe the 4-part token format."""
        assert "<node_id>.<timestamp>.<nonce>.<hmac_signature>" in doc_content

    def test_token_format_matches_code(self, tokens_source, doc_content):
        """Verify token parts count matches code validation."""
        # Code checks: len(parts) != 4
        assert "len(parts) != 4" in tokens_source
        # Docs should mention 4 parts
        assert "4 dot-separated parts" in doc_content

    def test_hmac_sha256_documented(self, doc_content):
        """HMAC-SHA256 algorithm is documented."""
        assert "HMAC-SHA256" in doc_content

    def test_timing_safe_comparison_documented(self, doc_content):
        """Timing-safe comparison is documented."""
        assert "compare_digest" in doc_content


# =========================================================================
# Error responses documented
# =========================================================================


class TestErrorResponsesDocumented:
    """Error response messages match between code and docs."""

    def test_missing_auth_message_matches(self, doc_content, middleware_source):
        """Missing auth error detail matches code and docs."""
        assert "Missing authorization header" in middleware_source
        assert "Missing authorization header" in doc_content

    def test_invalid_token_message_matches(self, doc_content, middleware_source):
        """Invalid token error detail matches code and docs."""
        assert "Invalid or expired token" in middleware_source
        assert "Invalid or expired token" in doc_content

    def test_www_authenticate_header_documented(self, doc_content):
        """WWW-Authenticate: Bearer header is documented."""
        assert "WWW-Authenticate" in doc_content
        assert "Bearer" in doc_content


# =========================================================================
# API surface documented
# =========================================================================


class TestAPISurfaceDocumented:
    """Public API functions and classes are documented."""

    def test_auth_middleware_class_documented(self, doc_content):
        assert "AuthMiddleware" in doc_content

    def test_require_auth_documented(self, doc_content):
        assert "require_auth" in doc_content

    def test_generate_node_token_documented(self, doc_content):
        assert "generate_node_token" in doc_content

    def test_verify_node_token_documented(self, doc_content):
        assert "verify_node_token" in doc_content

    def test_token_store_documented(self, doc_content):
        assert "TokenStore" in doc_content

    def test_token_store_methods_documented(self, doc_content):
        """All TokenStore public methods are mentioned."""
        for method in ("issue", "verify", "revoke", "list_nodes", "close"):
            assert method in doc_content, (
                f"TokenStore method '{method}' not in documentation"
            )


# =========================================================================
# Test class names documented
# =========================================================================


class TestTestClassesDocumented:
    """All test classes are referenced in the documentation."""

    def test_unit_test_classes_documented(self, doc_content):
        """Unit test class names appear in docs."""
        unit_test_source = UNIT_TESTS_PATH.read_text()
        class_names = re.findall(r"^class (Test\w+)", unit_test_source, re.MULTILINE)
        for cls in class_names:
            assert cls in doc_content, (
                f"Unit test class '{cls}' not found in documentation"
            )

    def test_integration_test_classes_documented(self, doc_content):
        """Integration test class names appear in docs."""
        integration_source = INTEGRATION_TESTS_PATH.read_text()
        class_names = re.findall(r"^class (Test\w+)", integration_source, re.MULTILINE)
        for cls in class_names:
            assert cls in doc_content, (
                f"Integration test class '{cls}' not found in documentation"
            )


# =========================================================================
# Security layers cross-referenced
# =========================================================================


class TestSecurityLayersCrossReferenced:
    """Docs reference related security modules."""

    def test_teams_auth_referenced(self, doc_content):
        assert "teams/auth.py" in doc_content

    def test_tls_module_referenced(self, doc_content):
        assert "security/tls.py" in doc_content

    def test_control_plane_referenced(self, doc_content):
        assert "control_plane/security.py" in doc_content

    def test_security_layer_model_documented(self, doc_content):
        """Security layers are documented with Layer 0 for auth."""
        assert "Layer 0" in doc_content
        assert "API Auth" in doc_content or "Auth Middleware" in doc_content
        assert "TLS" in doc_content
        assert "Encrypted" in doc_content or "SQLCipher" in doc_content
        assert "SECURITY.md" in doc_content


# =========================================================================
# Source code docstrings match documentation
# =========================================================================


SECURITY_MD_PATH = PROJECT_ROOT / "SECURITY.md"


class TestSourceDocstringsAccurate:
    """Source code docstrings agree with the documentation."""

    def test_tokens_docstring_mentions_nonce(self, tokens_source):
        """tokens.py module docstring includes 4-part format with nonce."""
        assert "<nonce>" in tokens_source or "nonce" in tokens_source

    def test_tokens_docstring_four_part_format(self, tokens_source):
        """tokens.py docstring describes the 4-part token format."""
        assert "<node_id>.<timestamp>.<nonce>.<hmac_signature>" in tokens_source

    def test_generate_node_token_return_doc(self, tokens_source):
        """generate_node_token docstring documents the correct return format."""
        assert "<node_id>.<timestamp>.<nonce>.<hmac_signature>" in tokens_source

    def test_generate_node_token_dot_warning(self, tokens_source):
        """generate_node_token warns about dots in node_id."""
        assert "dot" in tokens_source.lower()


class TestSecurityMdCrossReference:
    """SECURITY.md references the auth middleware."""

    @pytest.fixture
    def security_content(self) -> str:
        assert SECURITY_MD_PATH.exists(), f"SECURITY.md missing: {SECURITY_MD_PATH}"
        return SECURITY_MD_PATH.read_text()

    def test_auth_middleware_in_security_md(self, security_content):
        """SECURITY.md references the auth middleware."""
        assert "Auth Middleware" in security_content

    def test_hmac_token_format_in_security_md(self, security_content):
        """SECURITY.md documents the token format."""
        assert "<node_id>.<timestamp>.<nonce>.<hmac_signature>" in security_content

    def test_security_md_links_to_docs(self, security_content):
        """SECURITY.md links to the full auth middleware docs."""
        assert "docs/auth-middleware.md" in security_content

    def test_security_md_mentions_public_paths(self, security_content):
        """SECURITY.md mentions public path bypass."""
        assert "/health" in security_content

    def test_security_md_env_vars(self, security_content):
        """SECURITY.md lists key configuration variables."""
        assert "GM_CLUSTER_SECRET" in security_content
        assert "GM_TOKEN_TTL" in security_content

    def test_security_md_related_auth_systems(self, security_content):
        """SECURITY.md references all auth subsystems."""
        assert "teams/auth.py" in security_content
        assert "coordinator/app.py" in security_content
        assert "control_plane/security.py" in security_content
