from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock

import pytest

from src.core.errors import AccessDeniedException
from src.db.models.role import UserRoleEnum
from src.services.auditlog_service import AuditLogService


@pytest.fixture
def service_with_mock_repo(monkeypatch):
    mock_repo = MagicMock()
    mock_repo.get = AsyncMock()
    mock_repo.get_all = AsyncMock()

    repo_cls = MagicMock(return_value=mock_repo)
    monkeypatch.setattr("src.services.auditlog_service.AuditLogRepository", repo_cls)

    service = AuditLogService(AsyncMock())
    return service, mock_repo


@pytest.fixture
def admin_user():
    return SimpleNamespace(
        id=1,
        role_id=UserRoleEnum.ADMIN.value,
        email="admin@example.com",
    )


@pytest.fixture
def non_admin_user():
    return SimpleNamespace(
        id=2,
        role_id=UserRoleEnum.EXECUTOR_DFIP.value,
        email="executor@example.com",
    )


@pytest.mark.asyncio
async def test_get_all_allowed_for_admin(service_with_mock_repo, admin_user):
    service, mock_repo = service_with_mock_repo
    mock_row = SimpleNamespace(id=10)
    mock_repo.get_all.return_value = [mock_row]

    result = await service.get_all(admin_user, org_unit_id=77, event_type="form")

    assert result == [mock_row]
    mock_repo.get_all.assert_awaited_once_with(
        limit=None,
        offset=None,
        user_id=None,
        org_unit_id=77,
        task_id=None,
        form_id=None,
        event_type="form",
        date_from=None,
        date_to=None,
        event=None,
    )


@pytest.mark.asyncio
async def test_get_all_denied_for_non_admin(service_with_mock_repo, non_admin_user):
    service, mock_repo = service_with_mock_repo

    with pytest.raises(AccessDeniedException):
        await service.get_all(non_admin_user)

    mock_repo.get_all.assert_not_called()


def test_orm_log_to_response_maps_entity_and_entity_id(service_with_mock_repo):
    service, _ = service_with_mock_repo
    log = SimpleNamespace(
        id=55,
        user_id=7,
        event="UPDATE",
        event_type="fallback_entity",
        event_dt="2026-05-19T12:00:00Z",
        event_data={"entity_type": "form_line", "entity_id": "42", "x": 1},
        user=None,
    )

    dto = service.orm_log_to_response(log)

    assert dto.entity == "form_line"
    assert dto.entity_id == 42
    assert dto.action == "UPDATE"
    assert dto.user_id == 7
