"""
Tests for GET /api/v1/admin/logs - Admin Error Logs Viewer (Story 5.7).
AC: auth required, pagination, filters, no original_filename or document content.
"""

import pytest
from pathlib import Path
from unittest.mock import patch, MagicMock
from datetime import datetime, timezone

ADMIN_LOGIN_URL = "/api/v1/admin/login"
ADMIN_LOGS_URL = "/api/v1/admin/logs"


@pytest.fixture
def users_file(tmp_path: Path) -> Path:
    return tmp_path / "users.json"


@pytest.fixture
def client(users_file: Path, monkeypatch):
    """TestClient with admin and rate limiting disabled."""
    import services.auth_service as auth_svc
    from middleware.rate_limiting import RateLimitManager

    monkeypatch.setattr(auth_svc, "USERS_FILE", users_file)
    monkeypatch.setattr(auth_svc, "USE_DATABASE", False)
    monkeypatch.setattr(auth_svc, "DATABASE_AVAILABLE", False)

    async def _check_request_allow(self, request):
        return True, "ok", "test"

    async def _check_translation_allow(self, request, file_size_mb=0):
        return True, "ok"

    monkeypatch.setattr(RateLimitManager, "check_request", _check_request_allow)
    monkeypatch.setattr(RateLimitManager, "check_translation", _check_translation_allow)

    from main import app
    from fastapi.testclient import TestClient

    return TestClient(app, raise_server_exceptions=True)


@pytest.fixture
def admin_password():
    return "admin-secret"


@pytest.fixture
def client_with_admin(client, admin_password, monkeypatch):
    import routes.admin_routes as admin_routes_mod

    monkeypatch.setattr(admin_routes_mod, "ADMIN_USERNAME", "admin")
    monkeypatch.setattr(admin_routes_mod, "ADMIN_PASSWORD", admin_password)
    monkeypatch.setattr(admin_routes_mod, "ADMIN_PASSWORD_HASH", None)
    return client


@pytest.fixture
def admin_token(client_with_admin, admin_password):
    r = client_with_admin.post(ADMIN_LOGIN_URL, json={"password": admin_password})
    assert r.status_code == 200, r.text
    return r.json()["access_token"]


def _make_mock_translation(
    user_id="usr_abc",
    error_message="Translation failed: PROVIDER_UNAVAILABLE",
    created_at=None,
    provider="google",
    file_type="xlsx",
    original_filename="secret.docx",
):
    """Build a mock Translation row. original_filename must never appear in API response."""
    m = MagicMock()
    m.user_id = user_id
    m.error_message = error_message
    m.created_at = created_at or datetime.now(timezone.utc)
    m.provider = provider
    m.file_type = file_type
    m.original_filename = original_filename  # must NOT be in response
    return m


# ---------------------------------------------------------------------------
# Auth: 401 without token / invalid token
# ---------------------------------------------------------------------------
def test_admin_logs_without_token_returns_401(client_with_admin):
    r = client_with_admin.get(ADMIN_LOGS_URL)
    assert r.status_code == 401


def test_admin_logs_with_invalid_token_returns_401(client_with_admin):
    r = client_with_admin.get(
        ADMIN_LOGS_URL,
        headers={"Authorization": "Bearer invalid-token"},
    )
    assert r.status_code == 401


# ---------------------------------------------------------------------------
# 200 + response shape; no sensitive data (NFR11, NFR16)
# ---------------------------------------------------------------------------
def test_admin_logs_returns_200_and_shape(client_with_admin, admin_token):
    """With empty DB or mocked empty list, response has data.logs, data.total, data.page, data.per_page, meta.generated_at."""
    r = client_with_admin.get(
        ADMIN_LOGS_URL,
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    assert r.status_code == 200, r.text
    body = r.json()
    assert "data" in body
    assert "logs" in body["data"]
    assert "total" in body["data"]
    assert "page" in body["data"]
    assert "per_page" in body["data"]
    assert "meta" in body
    assert "generated_at" in body["meta"]
    assert isinstance(body["data"]["logs"], list)


def test_admin_logs_no_original_filename_in_response(client_with_admin, admin_token):
    """NFR11/NFR16: response must never contain original_filename or document content."""
    row = _make_mock_translation(original_filename="sensitive.docx")
    with patch("database.connection.get_sync_session") as mock_get_session:
        session_mock = MagicMock()
        mock_get_session.return_value.__enter__.return_value = session_mock
        mock_get_session.return_value.__exit__.return_value = None

        q = MagicMock()
        q.filter.return_value = q
        q.count.return_value = 1
        q.order_by.return_value.offset.return_value.limit.return_value.all.return_value = [row]
        session_mock.query.return_value = q

        r = client_with_admin.get(
            ADMIN_LOGS_URL,
            headers={"Authorization": f"Bearer {admin_token}"},
        )
        assert r.status_code == 200
        data_str = str(r.json())
        assert "original_filename" not in data_str
        assert "sensitive.docx" not in data_str
        assert "data" in r.json()
        logs = r.json()["data"]["logs"]
        assert len(logs) == 1
        entry = logs[0]
        assert "timestamp" in entry
        assert "level" in entry
        assert entry["level"] == "error"
        assert "message" in entry
        assert "user_id" in entry
        assert "error_code" in entry


# ---------------------------------------------------------------------------
# level=warning and level=info return empty logs
# ---------------------------------------------------------------------------
def test_admin_logs_level_warning_returns_empty(client_with_admin, admin_token):
    r = client_with_admin.get(
        f"{ADMIN_LOGS_URL}?level=warning",
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    assert r.status_code == 200
    assert r.json()["data"]["logs"] == []
    assert r.json()["data"]["total"] == 0


def test_admin_logs_level_info_returns_empty(client_with_admin, admin_token):
    r = client_with_admin.get(
        f"{ADMIN_LOGS_URL}?level=info",
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    assert r.status_code == 200
    assert r.json()["data"]["logs"] == []
    assert r.json()["data"]["total"] == 0


# ---------------------------------------------------------------------------
# Query params: page, per_page
# ---------------------------------------------------------------------------
def test_admin_logs_accepts_page_and_per_page(client_with_admin, admin_token):
    r = client_with_admin.get(
        f"{ADMIN_LOGS_URL}?page=2&per_page=25",
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    assert r.status_code == 200
    assert r.json()["data"]["page"] == 2
    assert r.json()["data"]["per_page"] == 25
