"""IT-SRV-003 — notify toggle via settings API with audit."""

from __future__ import annotations

from unittest.mock import AsyncMock, patch

import pytest

from server.api.schemas import SettingUpdatePayload
from server.api.settings import set_setting
from server.domain.models import Setting
from server.infrastructure.database.audit_log_repo import AuditLogRepositoryImpl
from server.infrastructure.database.setting_repo import SettingRepositoryImpl


async def _sqlite_compatible_set(self, key: str, value: str) -> Setting:
    row = await self.session.get(Setting, key)
    if row is None:
        row = Setting(key=key, value=value)
        self.session.add(row)
    else:
        row.value = value
    await self.session.commit()
    await self.session.refresh(row)
    return row

pytestmark = pytest.mark.integration


@pytest.mark.asyncio
async def test_notify_alert_cpu_toggle_writes_audit(
    db_session,
    test_admin,
    mock_request,
    monkeypatch,
):
    db_session.add(Setting(key="notify_alert_cpu", value="true"))
    await db_session.commit()

    monkeypatch.setattr("server.config.settings.NOTIFY_ALERT_CPU", "true")
    monkeypatch.setattr(SettingRepositoryImpl, "set", _sqlite_compatible_set)

    with patch(
        "server.infrastructure.settings_broadcast.publish_setting_change",
        new_callable=AsyncMock,
    ) as mock_publish:
        result = await set_setting(
            "notify_alert_cpu",
            SettingUpdatePayload(value="false"),
            mock_request,
            test_admin["admin"],
            db_session,
        )

    assert result["key"] == "notify_alert_cpu"
    assert result["value"] == "false"
    mock_publish.assert_awaited_once_with("notify_alert_cpu", "false")

    setting = await db_session.get(Setting, "notify_alert_cpu")
    assert setting is not None
    assert setting.value == "false"

    audit_repo = AuditLogRepositoryImpl(db_session)
    logs, total = await audit_repo.query(action="update_setting", limit=5, offset=0)
    assert total >= 1
    assert any(
        log.action == "update_setting" and "notify_alert_cpu" in (log.detail or "")
        for log in logs
    )
