"""Unit tests for activation threshold configuration."""

from __future__ import annotations

import pytest
from sqlalchemy.ext.asyncio import AsyncSession

from app.exceptions import ValidationError
from app.services.admin_service import (
    get_activation_config,
    update_activation_config,
)


@pytest.fixture
async def session() -> AsyncSession:
    """DB session compatible with services that commit."""
    from tests.conftest import _test_session_factory

    async with _test_session_factory() as session:
        yield session


class TestActivationConfig:
    async def test_defaults_when_unset(self, session: AsyncSession):
        config = await get_activation_config(session)
        assert config == {
            "min_momentum_percentile": 80.0,
            "min_rr": 1.2,
            "min_confidence": 0.0,  # off — the July 2026 ablation showed it adds nothing
            "require_high_conviction": False,
            "exclude_conflicts": False,
            "exclude_neutral": True,
        }

    async def test_update_and_read_back(self, session: AsyncSession):
        updated = await update_activation_config(
            session, {"min_momentum_percentile": 70.0, "min_confidence": 60.0}
        )
        assert updated["min_momentum_percentile"] == 70.0
        assert updated["min_confidence"] == 60.0

        config = await get_activation_config(session)
        assert config["min_momentum_percentile"] == 70.0
        assert config["min_confidence"] == 60.0

    async def test_partial_update_keeps_other_value(self, session: AsyncSession):
        await update_activation_config(session, {"min_confidence": 80.0})
        config = await get_activation_config(session)
        assert config["min_rr"] == 1.2  # default untouched
        assert config["min_confidence"] == 80.0

    async def test_rejects_out_of_range_momentum_percentile(self, session: AsyncSession):
        with pytest.raises(ValidationError):
            await update_activation_config(session, {"min_momentum_percentile": 150.0})

    async def test_conviction_flags_round_trip(self, session: AsyncSession):
        await update_activation_config(
            session,
            {"require_high_conviction": True, "exclude_conflicts": True},
        )
        config = await get_activation_config(session)
        assert config["require_high_conviction"] is True
        assert config["exclude_conflicts"] is True

    async def test_exclude_neutral_round_trip(self, session: AsyncSession):
        # On by default; can be turned off.
        assert (await get_activation_config(session))["exclude_neutral"] is True
        await update_activation_config(session, {"exclude_neutral": False})
        assert (await get_activation_config(session))["exclude_neutral"] is False

    async def test_rejects_negative_rr(self, session: AsyncSession):
        with pytest.raises(ValidationError):
            await update_activation_config(session, {"min_rr": -1.0})

    async def test_rejects_out_of_range_confidence(self, session: AsyncSession):
        with pytest.raises(ValidationError):
            await update_activation_config(session, {"min_confidence": 120.0})
