"""Auth/access compatibility for dedicated transfer HTTP routes.

Author: Vasiliy Zdanovskiy
email: vasilyvz@gmail.com

When security.enabled, transfer routes follow UnifiedSecurityMiddleware like other
protected HTTP routes (tech spec Decision 13). Normative paths match registered
routes: /api/transfer/uploads, /api/transfer/downloads, etc.
"""

from __future__ import annotations

from typing import Any

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

from mcp_proxy_adapter.api.core.app_factory_routes import setup_routes
from mcp_proxy_adapter.api.middleware.unified_security import (
    UnifiedSecurityMiddleware,
    _DEFAULT_PUBLIC_PATHS,
    _resolve_public_paths,
)
from mcp_proxy_adapter.commands.builtin_commands import register_builtin_commands
from mcp_proxy_adapter.transfer.server_store import TransferServerStore

_VALID_TOKEN = "test-transfer-auth-token"
_SHA = "7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9"


@pytest.fixture
def secured_transfer_client(
    tmp_path: Any, monkeypatch: pytest.MonkeyPatch
) -> TestClient:
    from mcp_proxy_adapter.api import handlers as handlers_mod

    store = TransferServerStore(
        storage_dir=str(tmp_path / "tstore"),
        session_ttl_seconds=3600,
        max_file_size_bytes=10737418240,
        default_chunk_size_bytes=1048576,
        max_chunk_size_bytes=8388608,
    )
    monkeypatch.setattr(handlers_mod, "_CACHED_TRANSFER_STORE", None)
    monkeypatch.setattr(handlers_mod, "get_transfer_store", lambda: store)

    app = FastAPI()
    register_builtin_commands()
    setup_routes(app)
    app.add_middleware(
        UnifiedSecurityMiddleware,
        config={
            "security": {
                "enabled": True,
                "tokens": {"primary": _VALID_TOKEN},
            }
        },
    )
    return TestClient(app)


def test_transfer_routes_require_auth_when_security_enabled(
    secured_transfer_client: TestClient,
) -> None:
    r = secured_transfer_client.post(
        "/api/transfer/uploads",
        json={
            "filename": "x.bin",
            "size_bytes": 1,
            "checksum_algorithm": "sha256",
            "checksum_value": _SHA,
            "compression": "identity",
            "chunk_size": 1,
        },
    )
    assert r.status_code == 401


def test_transfer_routes_accept_api_key_auth(
    secured_transfer_client: TestClient,
) -> None:
    r = secured_transfer_client.post(
        "/api/transfer/uploads",
        headers={"X-API-Key": _VALID_TOKEN},
        json={
            "filename": "x.bin",
            "size_bytes": 1,
            "checksum_algorithm": "sha256",
            "checksum_value": _SHA,
            "compression": "identity",
            "chunk_size": 1,
        },
    )
    assert r.status_code == 201
    assert r.json().get("transfer_id")


def test_transfer_routes_accept_bearer_auth(
    secured_transfer_client: TestClient,
) -> None:
    r = secured_transfer_client.post(
        "/api/transfer/uploads",
        headers={"Authorization": f"Bearer {_VALID_TOKEN}"},
        json={
            "filename": "x.bin",
            "size_bytes": 1,
            "checksum_algorithm": "sha256",
            "checksum_value": _SHA,
            "compression": "identity",
            "chunk_size": 1,
        },
    )
    assert r.status_code == 201
    assert r.json().get("transfer_id")


def test_transfer_routes_remain_non_public_by_default() -> None:
    assert "/api/transfer/uploads" not in _DEFAULT_PUBLIC_PATHS
    assert "/api/transfer/downloads" not in _DEFAULT_PUBLIC_PATHS
    resolved = _resolve_public_paths({})
    assert "/api/transfer/uploads" not in resolved
    assert "/api/transfer/downloads" not in resolved


def test_transfer_routes_respect_explicit_public_path_override(
    tmp_path: Any, monkeypatch: pytest.MonkeyPatch
) -> None:
    from mcp_proxy_adapter.api import handlers as handlers_mod

    store = TransferServerStore(
        storage_dir=str(tmp_path / "tstore2"),
        session_ttl_seconds=3600,
        max_file_size_bytes=10737418240,
        default_chunk_size_bytes=1048576,
        max_chunk_size_bytes=8388608,
    )
    monkeypatch.setattr(handlers_mod, "_CACHED_TRANSFER_STORE", None)
    monkeypatch.setattr(handlers_mod, "get_transfer_store", lambda: store)

    app = FastAPI()
    register_builtin_commands()
    setup_routes(app)
    app.add_middleware(
        UnifiedSecurityMiddleware,
        config={
            "security": {
                "enabled": True,
                "tokens": {"primary": _VALID_TOKEN},
                "public_paths": ["/api/transfer/uploads"],
            }
        },
    )
    client = TestClient(app)

    unauth_upload = client.post(
        "/api/transfer/uploads",
        json={
            "filename": "x.bin",
            "size_bytes": 1,
            "checksum_algorithm": "sha256",
            "checksum_value": _SHA,
            "compression": "identity",
            "chunk_size": 1,
        },
    )
    assert unauth_upload.status_code == 201

    unauth_download = client.post(
        "/api/transfer/downloads",
        json={
            "source_path": str(tmp_path / "missing.bin"),
            "filename": "out.bin",
            "checksum_algorithm": "sha256",
            "compression": "identity",
        },
    )
    assert unauth_download.status_code == 401
