# #region Test.Schemas.Settings [C:2] [TYPE Module] [SEMANTICS test,schema,settings]
# @BRIEF Tests for schemas/settings.py — NotificationChannel, ValidationPolicyBase,
#        ValidationPolicyCreate, ValidationPolicyUpdate, ValidationPolicyResponse,
#        TranslationScheduleItem.
# @RELATION BINDS_TO -> [SettingsSchemas]
# @TEST_EDGE: missing_field -> optional fields default correctly
# @TEST_EDGE: invalid_type -> validation rejects bad types
# @TEST_EDGE: serialization -> round-trip via model_dump/model_validate

from datetime import datetime, time, timezone
import pytest
from pydantic import ValidationError

from src.schemas.settings import (
    NotificationChannel,
    TranslationScheduleItem,
    ValidationPolicyBase,
    ValidationPolicyCreate,
    ValidationPolicyResponse,
    ValidationPolicyUpdate,
)


class TestNotificationChannel:
    """NotificationChannel — type and target."""

    def test_minimal(self):
        nc = NotificationChannel(type="SLACK", target="#alerts")
        assert nc.type == "SLACK"
        assert nc.target == "#alerts"

    def test_missing_field_raises(self):
        with pytest.raises(ValidationError):
            NotificationChannel(type="SLACK")
        with pytest.raises(ValidationError):
            NotificationChannel(target="#alerts")

    def test_serialize_roundtrip(self):
        nc = NotificationChannel(type="TELEGRAM", target="chat-1")
        data = nc.model_dump()
        restored = NotificationChannel.model_validate(data)
        assert restored.type == "TELEGRAM"
        assert restored.target == "chat-1"


class TestValidationPolicyBase:
    """ValidationPolicyBase — required fields and defaults."""

    def make_policy(self, **overrides):
        defaults = dict(
            name="Test Policy",
            environment_id="env-1",
            dashboard_ids=["1", "2"],
            schedule_days=[0, 2, 4],
            window_start=time(9, 0),
            window_end=time(18, 0),
        )
        defaults.update(overrides)
        return ValidationPolicyBase(**defaults)

    def test_minimal(self):
        p = self.make_policy()
        assert p.name == "Test Policy"
        assert p.is_active is True
        assert p.notify_owners is True
        assert p.alert_condition == "FAIL_ONLY"
        assert p.custom_channels is None

    def test_with_channels(self):
        channels = [NotificationChannel(type="SLACK", target="#alerts")]
        p = self.make_policy(custom_channels=channels)
        assert len(p.custom_channels) == 1
        assert p.custom_channels[0].type == "SLACK"

    def test_inactive(self):
        p = self.make_policy(is_active=False)
        assert p.is_active is False

    def test_alert_conditions(self):
        for condition in ["FAIL_ONLY", "WARN_AND_FAIL", "ALWAYS"]:
            p = self.make_policy(alert_condition=condition)
            assert p.alert_condition == condition

    def test_serialize_roundtrip(self):
        p = self.make_policy()
        data = p.model_dump()
        restored = ValidationPolicyBase.model_validate(data)
        assert restored.name == "Test Policy"
        assert restored.is_active is True


class TestValidationPolicyCreate:
    """ValidationPolicyCreate — inherits ValidationPolicyBase."""

    def test_create(self):
        p = ValidationPolicyCreate(
            name="New Policy",
            environment_id="env-1",
            dashboard_ids=["1"],
            schedule_days=[1],
            window_start=time(10, 0),
            window_end=time(20, 0),
        )
        assert p.name == "New Policy"

    def test_serialize_roundtrip(self):
        p = ValidationPolicyCreate(
            name="P", environment_id="e1", dashboard_ids=["1"],
            schedule_days=[1], window_start=time(9, 0), window_end=time(17, 0),
        )
        data = p.model_dump()
        restored = ValidationPolicyCreate.model_validate(data)
        assert restored.name == "P"


class TestValidationPolicyUpdate:
    """ValidationPolicyUpdate — all fields optional for partial update."""

    def test_empty(self):
        p = ValidationPolicyUpdate()
        assert p.name is None
        assert p.environment_id is None
        assert p.is_active is None
        assert p.dashboard_ids is None
        assert p.schedule_days is None
        assert p.window_start is None
        assert p.window_end is None
        assert p.notify_owners is None
        assert p.custom_channels is None
        assert p.alert_condition is None

    def test_partial(self):
        p = ValidationPolicyUpdate(name="Updated")
        assert p.name == "Updated"

    def test_serialize_roundtrip(self):
        p = ValidationPolicyUpdate(name="Updated", is_active=False)
        data = p.model_dump()
        restored = ValidationPolicyUpdate.model_validate(data)
        assert restored.name == "Updated"
        assert restored.is_active is False


class TestValidationPolicyResponse:
    """ValidationPolicyResponse — inherits ValidationPolicyBase with id + timestamps."""

    def test_minimal(self):
        ts = datetime.now(timezone.utc)
        p = ValidationPolicyResponse(
            id="pol-1",
            name="Policy",
            environment_id="env-1",
            dashboard_ids=["1"],
            schedule_days=[1],
            window_start=time(9, 0),
            window_end=time(17, 0),
            created_at=ts,
            updated_at=ts,
        )
        assert p.id == "pol-1"
        assert p.created_at == ts
        assert p.updated_at == ts

    def test_serialize_roundtrip(self):
        ts = datetime.now(timezone.utc)
        p = ValidationPolicyResponse(
            id="pol-1", name="P", environment_id="e1", dashboard_ids=["1"],
            schedule_days=[1], window_start=time(9, 0), window_end=time(17, 0),
            created_at=ts, updated_at=ts,
        )
        data = p.model_dump()
        restored = ValidationPolicyResponse.model_validate(data)
        assert restored.id == "pol-1"

    def test_defaults_from_base(self):
        ts = datetime.now(timezone.utc)
        p = ValidationPolicyResponse(
            id="pol-1", name="P", environment_id="e1", dashboard_ids=["1"],
            schedule_days=[1], window_start=time(9, 0), window_end=time(17, 0),
            created_at=ts, updated_at=ts,
        )
        assert p.is_active is True
        assert p.notify_owners is True
        assert p.alert_condition == "FAIL_ONLY"

    def test_from_attributes(self):
        ts = datetime.now(timezone.utc)
        class FakeORM:
            id = "pol-1"
            name = "P"
            environment_id = "e1"
            is_active = True
            dashboard_ids = ["1"]
            schedule_days = [1]
            window_start = time(9, 0)
            window_end = time(17, 0)
            notify_owners = False
            custom_channels = None
            alert_condition = "WARN_AND_FAIL"
            created_at = ts
            updated_at = ts
        p = ValidationPolicyResponse.model_validate(FakeORM())
        assert p.notify_owners is False


class TestTranslationScheduleItem:
    """TranslationScheduleItem — schedule with cron expression."""

    def test_minimal(self):
        s = TranslationScheduleItem(
            schedule_id="s-1", job_id="j-1",
            cron_expression="0 */6 * * *", timezone="UTC", is_active=True,
        )
        assert s.job_name is None
        assert s.execution_mode == "full"
        assert s.last_run_at is None
        assert s.next_run_at is None
        assert s.created_by is None
        assert s.created_at is None

    def test_with_all_fields(self):
        ts = datetime.now(timezone.utc)
        s = TranslationScheduleItem(
            schedule_id="s-1", job_id="j-1", job_name="Nightly Sync",
            cron_expression="0 0 * * *", timezone="America/New_York",
            is_active=False, execution_mode="incremental",
            last_run_at=ts, next_run_at=ts, created_by="admin", created_at=ts,
        )
        assert s.job_name == "Nightly Sync"
        assert s.execution_mode == "incremental"
        assert s.is_active is False

    def test_serialize_roundtrip(self):
        s = TranslationScheduleItem(
            schedule_id="s-1", job_id="j-1",
            cron_expression="0 0 * * *", timezone="UTC", is_active=True,
        )
        data = s.model_dump()
        restored = TranslationScheduleItem.model_validate(data)
        assert restored.schedule_id == "s-1"
        assert restored.is_active is True

    def test_from_attributes(self):
        ts = datetime.now(timezone.utc)
        class FakeORM:
            schedule_id = "s-1"
            job_id = "j-1"
            job_name = "Test"
            cron_expression = "*/5 * * * *"
            timezone = "UTC"
            is_active = True
            execution_mode = "full"
            last_run_at = ts
            next_run_at = ts
            created_by = "admin"
            created_at = ts
        s = TranslationScheduleItem.model_validate(FakeORM())
        assert s.cron_expression == "*/5 * * * *"
        assert s.execution_mode == "full"
# #endregion Test.Schemas.Settings
