"""End-to-end tests — full startup -> tool invocation with mocked HTTP."""

from __future__ import annotations

import httpx
import respx

from synology_mcp.core.client import DsmClient
from synology_mcp.modules.filestation.listing import list_shares
from synology_mcp.modules.filestation.operations import move_files
from synology_mcp.modules.filestation.search import search_files
from synology_mcp.server import create_server
from tests.conftest import BASE_URL, make_api_cache, make_test_config


class TestEndToEnd:
    def test_server_creates_with_all_tools(self) -> None:
        """Verify server creates with all 12 File Station tools at WRITE tier."""
        config = make_test_config()
        server = create_server(config)
        assert server is not None

    @respx.mock
    async def test_list_then_search_workflow(self) -> None:
        """Simulate: list_shares -> search_files workflow."""
        call_count = 0

        def side_effect(request: httpx.Request) -> httpx.Response:
            nonlocal call_count
            call_count += 1
            params = dict(request.url.params)
            method = params.get("method", "")

            if method == "list_share":
                return httpx.Response(
                    200,
                    json={
                        "success": True,
                        "data": {
                            "shares": [
                                {
                                    "name": "video",
                                    "path": "/video",
                                    "isdir": True,
                                    "additional": {
                                        "size": {"total_size": 5000000000000},
                                        "owner": {"user": "admin"},
                                    },
                                }
                            ],
                            "total": 1,
                        },
                    },
                )
            if method == "start":
                return httpx.Response(200, json={"success": True, "data": {"taskid": "e2e-1"}})
            if method == "list" and "taskid" in params:
                return httpx.Response(
                    200,
                    json={
                        "success": True,
                        "data": {
                            "files": [
                                {
                                    "name": "episode.mkv",
                                    "path": "/video/Downloads/episode.mkv",
                                    "isdir": False,
                                    "additional": {
                                        "size": 1500000000,
                                        "time": {"mtime": 1710000000},
                                    },
                                }
                            ],
                            "finished": True,
                            "total": 1,
                        },
                    },
                )
            # stop/clean
            return httpx.Response(200, json={"success": True, "data": {}})

        respx.get(f"{BASE_URL}/webapi/entry.cgi").mock(side_effect=side_effect)

        client = DsmClient(base_url=BASE_URL)
        client._api_cache = make_api_cache()
        async with client:
            # Step 1: List shares
            shares_result = await list_shares(client)
            assert "video" in shares_result

            # Step 2: Search files
            search_result = await search_files(client, folder_path="/video", pattern="*.mkv")
            assert "episode.mkv" in search_result

    @respx.mock
    async def test_search_and_move_workflow(self) -> None:
        """Simulate: search -> move workflow."""
        call_count = 0

        def side_effect(request: httpx.Request) -> httpx.Response:
            nonlocal call_count
            call_count += 1
            params = dict(request.url.params)
            method = params.get("method", "")
            api = params.get("api", "")

            if method == "start" and "Search" in api:
                return httpx.Response(200, json={"success": True, "data": {"taskid": "search-e2e"}})
            if method == "list" and "taskid" in params:
                return httpx.Response(
                    200,
                    json={
                        "success": True,
                        "data": {
                            "files": [
                                {
                                    "name": "ep.mkv",
                                    "path": "/video/Downloads/ep.mkv",
                                    "isdir": False,
                                    "additional": {
                                        "size": 1800000000,
                                        "time": {"mtime": 1710000000},
                                    },
                                }
                            ],
                            "finished": True,
                            "total": 1,
                        },
                    },
                )
            if method == "start" and "CopyMove" in api:
                return httpx.Response(200, json={"success": True, "data": {"taskid": "move-e2e"}})
            if method == "status":
                return httpx.Response(200, json={"success": True, "data": {"finished": True}})
            return httpx.Response(200, json={"success": True, "data": {}})

        respx.get(f"{BASE_URL}/webapi/entry.cgi").mock(side_effect=side_effect)

        client = DsmClient(base_url=BASE_URL)
        client._api_cache = make_api_cache()
        async with client:
            search_result = await search_files(
                client, folder_path="/video/Downloads", pattern="*.mkv"
            )
            assert "ep.mkv" in search_result

            move_result = await move_files(
                client,
                paths=["/video/Downloads/ep.mkv"],
                dest_folder="/video/TV Shows/Show/Season 1",
            )
            assert "[+]" in move_result
            assert "Moved" in move_result

    @respx.mock
    async def test_read_only_tier_limits_tools(self) -> None:
        """Verify READ tier only registers 6 tools."""
        config = make_test_config(modules={"filestation": {"enabled": True, "permission": "read"}})
        server = create_server(config)
        assert server is not None
        # The server was created — WRITE tools should not be registered
        # We can verify by checking that create_folder etc. are not in the tools
