"""Typed transfer error responses from HTTP handlers.

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

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.commands.builtin_commands import register_builtin_commands
from mcp_proxy_adapter.transfer.server_store import TransferServerStore

PAYLOAD = b"hello world!"
EXPECTED_SHA256 = (
    "7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9"
)


@pytest.fixture
def transfer_app_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 / "estore"),
        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)
    return TestClient(app)


def test_upload_chunk_resume_conflict_returns_structured_error(
    transfer_app_client: TestClient,
) -> None:
    c = transfer_app_client.post(
        "/api/transfer/uploads",
        json={
            "filename": "blob.bin",
            "size_bytes": len(PAYLOAD),
            "checksum_algorithm": "sha256",
            "checksum_value": EXPECTED_SHA256,
            "compression": "identity",
            "chunk_size": 4,
        },
    )
    tid = c.json()["transfer_id"]
    transfer_app_client.put(
        f"/api/transfer/uploads/{tid}/chunks?offset=0",
        content=PAYLOAD[0:4],
    )
    r = transfer_app_client.put(
        f"/api/transfer/uploads/{tid}/chunks?offset=0",
        content=PAYLOAD[0:4],
    )
    assert r.status_code == 409
    body = r.json()
    assert body["success"] is False
    assert body["error_type"] == "TransferResumeConflictError"
    assert body["details"]["expected_offset"] == 4
    assert body["details"]["actual_offset"] == 0


def test_complete_upload_checksum_failure_returns_structured_error(
    transfer_app_client: TestClient,
) -> None:
    bad_checksum = "a" * 64
    c = transfer_app_client.post(
        "/api/transfer/uploads",
        json={
            "filename": "blob.bin",
            "size_bytes": len(PAYLOAD),
            "checksum_algorithm": "sha256",
            "checksum_value": bad_checksum,
            "compression": "identity",
            "chunk_size": 512,
        },
    )
    tid = c.json()["transfer_id"]
    transfer_app_client.put(
        f"/api/transfer/uploads/{tid}/chunks?offset=0",
        content=PAYLOAD,
    )
    fin = transfer_app_client.post(f"/api/transfer/uploads/{tid}/complete")
    assert fin.status_code == 422
    err = fin.json()
    assert err["success"] is False
    assert err["error_type"] == "TransferChecksumMismatchError"


def test_missing_transfer_id_returns_session_not_found_error(
    transfer_app_client: TestClient,
) -> None:
    r = transfer_app_client.get("/api/transfer/uploads/tr_nonexistent_zzzz")
    assert r.status_code == 404
    body = r.json()
    assert body["success"] is False
    assert body["error_type"] == "TransferSessionNotFoundError"


def test_download_range_error_returns_structured_error(
    tmp_path: Any,
    transfer_app_client: TestClient,
) -> None:
    src = tmp_path / "small.bin"
    src.write_bytes(b"ab")

    c = transfer_app_client.post(
        "/api/transfer/downloads",
        json={
            "source_path": str(src),
            "filename": "small.bin",
            "compression": "identity",
        },
    )
    tid = c.json()["transfer_id"]
    r = transfer_app_client.get(
        f"/api/transfer/downloads/{tid}/chunks",
        params={"offset": 10, "limit": 1},
    )
    assert r.status_code == 416
    body = r.json()
    assert body["success"] is False
    assert body["error_type"] == "TransferRangeNotSatisfiableError"
