"""
Tests for Admin Document Routes.
"""

import pytest
from datetime import datetime
from io import BytesIO
from pathlib import Path
from unittest.mock import MagicMock, patch
from uuid import UUID

from fastapi import HTTPException
from fastapi.testclient import TestClient

from backend.data.admin_models import AdminDocument, AdminToken
from backend.web.api.v1.admin.documents import _validate_uuid, create_documents_router
from backend.web.config import StorageConfig


# Test UUID
TEST_DOC_UUID = "550e8400-e29b-41d4-a716-446655440000"
TEST_TOKEN = "test-admin-token-12345"


class TestValidateUUID:
    """Tests for UUID validation."""

    def test_valid_uuid(self):
        """Test valid UUID passes validation."""
        _validate_uuid(TEST_DOC_UUID, "test")  # Should not raise

    def test_invalid_uuid_raises_400(self):
        """Test invalid UUID raises 400."""
        with pytest.raises(HTTPException) as exc_info:
            _validate_uuid("not-a-uuid", "document_id")

        assert exc_info.value.status_code == 400
        assert "Invalid document_id format" in exc_info.value.detail


class TestAdminRouter:
    """Tests for admin router creation."""

    def test_creates_router_with_endpoints(self):
        """Test router is created with expected endpoints."""
        router = create_documents_router(StorageConfig())

        # Get route paths (include prefix from router)
        paths = [route.path for route in router.routes]

        # Paths include the /admin/documents prefix
        assert any("/documents" in p for p in paths)
        assert any("/documents/stats" in p for p in paths)
        assert any("{document_id}" in p for p in paths)


class TestCreateTokenEndpoint:
    """Tests for POST /admin/auth/token endpoint."""

    @pytest.fixture
    def mock_db(self):
        """Create mock AdminDB."""
        db = MagicMock()
        db.is_valid_admin_token.return_value = True
        return db

    def test_create_token_success(self, mock_db):
        """Test successful token creation."""
        from backend.web.schemas.admin import AdminTokenCreate

        request = AdminTokenCreate(name="Test Token", expires_in_days=30)

        # The actual endpoint would generate a token
        # This tests the schema validation
        assert request.name == "Test Token"
        assert request.expires_in_days == 30


class TestDocumentUploadEndpoint:
    """Tests for POST /admin/documents endpoint."""

    @pytest.fixture
    def sample_pdf_bytes(self):
        """Create sample PDF-like bytes."""
        # Minimal PDF header
        return b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n"

    @pytest.fixture
    def mock_admin_db(self):
        """Create mock AdminDB."""
        db = MagicMock()
        db.is_valid_admin_token.return_value = True
        db.create_document.return_value = TEST_DOC_UUID
        return db

    def test_rejects_invalid_extension(self):
        """Test that invalid file extensions are rejected."""
        # Schema validation would happen at the route level
        allowed = (".pdf", ".png", ".jpg")
        file_ext = ".exe"

        assert file_ext not in allowed


class TestDocumentListEndpoint:
    """Tests for GET /admin/documents endpoint."""

    @pytest.fixture
    def sample_documents(self):
        """Create sample documents."""
        return [
            AdminDocument(
                document_id=UUID(TEST_DOC_UUID),
                admin_token=TEST_TOKEN,
                filename="test.pdf",
                file_size=1024,
                content_type="application/pdf",
                file_path="/tmp/test.pdf",
                page_count=1,
                status="pending",
            ),
        ]

    def test_validates_status_filter(self):
        """Test that invalid status filter is rejected."""
        valid_statuses = ("pending", "auto_labeling", "labeled", "exported")

        assert "invalid_status" not in valid_statuses
        assert "pending" in valid_statuses


class TestDocumentDetailEndpoint:
    """Tests for GET /admin/documents/{document_id} endpoint."""

    def test_requires_valid_uuid(self):
        """Test that invalid UUID is rejected."""
        with pytest.raises(HTTPException) as exc_info:
            _validate_uuid("invalid", "document_id")

        assert exc_info.value.status_code == 400


class TestDocumentDeleteEndpoint:
    """Tests for DELETE /admin/documents/{document_id} endpoint."""

    def test_validates_document_id(self):
        """Test that document_id is validated."""
        # Valid UUID should not raise
        _validate_uuid(TEST_DOC_UUID, "document_id")

        # Invalid should raise
        with pytest.raises(HTTPException):
            _validate_uuid("bad-id", "document_id")


class TestDocumentStatusUpdateEndpoint:
    """Tests for PATCH /admin/documents/{document_id}/status endpoint."""

    def test_validates_status_values(self):
        """Test that only valid statuses are accepted."""
        valid_statuses = ("pending", "labeled", "exported")

        assert "pending" in valid_statuses
        assert "invalid" not in valid_statuses
