"""
Tests for WebDAVBackend and NextcloudBackend (Plan 05-04).

TDD RED phase — all tests fail until backend/storage/webdav_backend.py and
backend/storage/nextcloud_backend.py are implemented.

Covers:
  - WebDAVBackend subclasses StorageBackend (all 7 abstract methods present)
  - All 7 methods are async coroutines
  - SSRF guard: construction with private/localhost URL raises ValueError
  - presigned_get_url and generate_presigned_put_url raise NotImplementedError
  - _make_path constructs correct WebDAV path
  - NextcloudBackend subclasses WebDAVBackend
  - NextcloudBackend inherits SSRF guard
  - NextcloudBackend has list_folder (async)
"""
from __future__ import annotations

import inspect

import pytest

pytestmark = pytest.mark.asyncio


class TestWebDAVBackendStructure:
    """Static structure tests — no network calls required."""

    def test_webdav_backend_importable(self):
        from storage.webdav_backend import WebDAVBackend  # noqa: F401

    def test_webdav_backend_is_storage_backend_subclass(self):
        from storage.base import StorageBackend
        from storage.webdav_backend import WebDAVBackend

        assert issubclass(WebDAVBackend, StorageBackend)

    @pytest.mark.parametrize(
        "method",
        [
            "put_object",
            "get_object",
            "delete_object",
            "presigned_get_url",
            "health_check",
            "generate_presigned_put_url",
            "stat_object",
        ],
    )
    def test_all_7_methods_are_async(self, method):
        from storage.webdav_backend import WebDAVBackend

        fn = getattr(WebDAVBackend, method)
        assert inspect.iscoroutinefunction(fn), f"{method} is not async"


class TestWebDAVBackendSSRF:
    """SSRF guard tests — construction with blocked URL must raise ValueError."""

    def test_localhost_raises(self):
        from storage.webdav_backend import WebDAVBackend

        with pytest.raises(ValueError):
            WebDAVBackend("http://localhost/dav", "user", "pass")

    def test_127_x_raises(self):
        from storage.webdav_backend import WebDAVBackend

        with pytest.raises(ValueError):
            WebDAVBackend("http://127.0.0.1/dav", "user", "pass")

    def test_10_x_raises(self):
        from storage.webdav_backend import WebDAVBackend

        with pytest.raises(ValueError):
            WebDAVBackend("http://10.0.0.1/dav", "user", "pass")

    def test_192_168_raises(self):
        from storage.webdav_backend import WebDAVBackend

        with pytest.raises(ValueError):
            WebDAVBackend("http://192.168.1.1/dav", "user", "pass")

    def test_169_254_raises(self):
        from storage.webdav_backend import WebDAVBackend

        with pytest.raises(ValueError):
            WebDAVBackend("http://169.254.169.254/dav", "user", "pass")


class TestWebDAVBackendNotImplemented:
    """presigned methods must raise NotImplementedError (D-14)."""

    async def test_presigned_get_url_raises(self):
        from storage.webdav_backend import WebDAVBackend

        backend = WebDAVBackend.__new__(WebDAVBackend)
        backend._server_url = "https://8.8.8.8/dav"
        with pytest.raises(NotImplementedError):
            await backend.presigned_get_url("some/key")

    async def test_generate_presigned_put_url_raises(self):
        from storage.webdav_backend import WebDAVBackend

        backend = WebDAVBackend.__new__(WebDAVBackend)
        backend._server_url = "https://8.8.8.8/dav"
        with pytest.raises(NotImplementedError):
            await backend.generate_presigned_put_url("some/key")


class TestWebDAVMakePath:
    """_make_path must produce percent-encoded WebDAV paths (Pitfall 2)."""

    def test_make_path_basic(self):
        from storage.webdav_backend import WebDAVBackend

        backend = WebDAVBackend.__new__(WebDAVBackend)
        path = backend._make_path("user-uuid", "doc-uuid", ".pdf")
        assert path == "docuvault/user-uuid/doc-uuid.pdf"

    def test_make_path_encodes_special_chars(self):
        from storage.webdav_backend import WebDAVBackend

        backend = WebDAVBackend.__new__(WebDAVBackend)
        # UUIDs are alphanumeric and hyphens — no encoding needed for typical values
        # This test ensures the encoding is applied (result should not contain raw spaces)
        path = backend._make_path("user id", "doc id", ".pdf")
        assert " " not in path
        assert "user%20id" in path or "user+id" in path or "user%2520id" in path


class TestNextcloudBackendStructure:
    """NextcloudBackend structure tests."""

    def test_nextcloud_importable(self):
        from storage.nextcloud_backend import NextcloudBackend  # noqa: F401

    def test_nextcloud_is_webdav_subclass(self):
        from storage.nextcloud_backend import NextcloudBackend
        from storage.webdav_backend import WebDAVBackend

        assert issubclass(NextcloudBackend, WebDAVBackend)

    def test_nextcloud_is_storage_backend_subclass(self):
        from storage.base import StorageBackend
        from storage.nextcloud_backend import NextcloudBackend

        assert issubclass(NextcloudBackend, StorageBackend)

    @pytest.mark.parametrize(
        "method",
        [
            "put_object",
            "get_object",
            "delete_object",
            "presigned_get_url",
            "health_check",
            "generate_presigned_put_url",
            "stat_object",
        ],
    )
    def test_all_7_methods_async_on_nextcloud(self, method):
        from storage.nextcloud_backend import NextcloudBackend

        fn = getattr(NextcloudBackend, method)
        assert inspect.iscoroutinefunction(fn), f"{method} is not async"

    def test_list_folder_present_and_async(self):
        from storage.nextcloud_backend import NextcloudBackend

        assert hasattr(NextcloudBackend, "list_folder")
        assert inspect.iscoroutinefunction(NextcloudBackend.list_folder)


class TestNextcloudBackendSSRF:
    """SSRF guard inherited from WebDAVBackend.__init__."""

    def test_10_x_raises_inherited(self):
        from storage.nextcloud_backend import NextcloudBackend

        with pytest.raises(ValueError):
            NextcloudBackend("http://10.0.0.1/dav", "user", "pass")

    def test_localhost_raises_inherited(self):
        from storage.nextcloud_backend import NextcloudBackend

        with pytest.raises(ValueError):
            NextcloudBackend("http://localhost/dav", "user", "pass")
