"""
Security tests for transfer JSON-RPC and chunk HTTP.

Author: Vasiliy Zdanovskiy
email: vasilyvz@gmail.com
"""

from __future__ import annotations

import hashlib
import json
from pathlib import Path

import pytest
from fastapi.testclient import TestClient

import mcp_proxy_adapter.api.handlers as handlers
from mcp_proxy_adapter.api.app import create_app

TEST_API_KEY = "test-transfer-security-key"


def _load_secure_app_config() -> dict:
    base = Path(__file__).resolve().parents[1]
    path = base / "mcp_proxy_adapter/examples/full_application/configs/http_basic.json"
    cfg = json.loads(path.read_text(encoding="utf-8"))
    cfg["security"] = {
        "enabled": True,
        "tokens": {"test-token-label": TEST_API_KEY},
    }
    return cfg


@pytest.fixture
def transfer_client_secured(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> TestClient:
    # Inline app_config triggers SimpleConfig certificate checks that expect a file path;
    # skip only certificate startup validation so UnifiedSecurityMiddleware still runs.
    monkeypatch.setattr(
        "mcp_proxy_adapter.api.core.app_factory.validate_certificates",
        lambda *args, **kwargs: None,
    )
    monkeypatch.setattr(
        "mcp_proxy_adapter.api.handlers.DEFAULT_STORAGE_DIR",
        str(tmp_path / "tstore"),
        raising=False,
    )
    handlers._CACHED_TRANSFER_STORE = None
    app = create_app(
        title="sec",
        description="sec",
        version="1.0.0",
        app_config=_load_secure_app_config(),
    )
    return TestClient(app)


def test_transfer_upload_begin_jsonrpc_denied_without_api_key(
    transfer_client_secured: TestClient,
) -> None:
    digest = "c" * 64
    r = transfer_client_secured.post(
        "/api/jsonrpc",
        json={
            "jsonrpc": "2.0",
            "method": "transfer_upload_begin",
            "params": {
                "filename": "x.bin",
                "size_bytes": 1,
                "checksum_value": digest,
                "compression": "identity",
            },
            "id": 1,
        },
    )
    assert r.status_code == 401
    body = r.json()
    assert "error" in body


def test_transfer_upload_chunk_put_denied_without_api_key_after_authenticated_begin(
    transfer_client_secured: TestClient,
) -> None:
    content = b"z"
    digest = hashlib.sha256(content).hexdigest()
    r = transfer_client_secured.post(
        "/api/jsonrpc",
        json={
            "jsonrpc": "2.0",
            "method": "transfer_upload_begin",
            "params": {
                "filename": "sec.bin",
                "size_bytes": len(content),
                "checksum_value": digest,
                "compression": "identity",
            },
            "id": 1,
        },
        headers={"X-API-Key": TEST_API_KEY},
    )
    assert r.status_code == 200, r.text
    assert r.json()["result"]["success"] is True, r.text
    tid = r.json()["result"]["data"]["transfer_id"]
    put = transfer_client_secured.put(
        f"/api/transfer/uploads/{tid}/chunks?offset=0",
        content=content,
        headers={},
    )
    assert put.status_code in (401, 403)


def test_transfer_upload_begin_succeeds_with_valid_api_key(
    transfer_client_secured: TestClient,
) -> None:
    digest = "d" * 64
    r = transfer_client_secured.post(
        "/api/jsonrpc",
        json={
            "jsonrpc": "2.0",
            "method": "transfer_upload_begin",
            "params": {
                "filename": "ok.bin",
                "size_bytes": 5,
                "checksum_value": digest,
                "compression": "identity",
            },
            "id": 1,
        },
        headers={"X-API-Key": TEST_API_KEY},
    )
    assert r.status_code == 200
    assert r.json()["result"]["success"] is True
