"""Tests for domain value objects."""

from __future__ import annotations

from uuid import UUID

import pytest

from noteflow.domain.value_objects import MeetingId, MeetingState


class TestMeetingState:
    """Tests for MeetingState enum."""

    @pytest.mark.parametrize(
        ("current", "target", "expected"),
        [
            # UNSPECIFIED transitions
            (MeetingState.UNSPECIFIED, MeetingState.CREATED, True),
            (MeetingState.UNSPECIFIED, MeetingState.RECORDING, False),
            # CREATED transitions
            (MeetingState.CREATED, MeetingState.RECORDING, True),
            (MeetingState.CREATED, MeetingState.ERROR, True),
            (MeetingState.CREATED, MeetingState.STOPPED, False),
            # RECORDING transitions (must go through STOPPING)
            (MeetingState.RECORDING, MeetingState.STOPPING, True),
            (MeetingState.RECORDING, MeetingState.STOPPED, False),
            (MeetingState.RECORDING, MeetingState.ERROR, True),
            (MeetingState.RECORDING, MeetingState.CREATED, False),
            # STOPPING transitions
            (MeetingState.STOPPING, MeetingState.STOPPED, True),
            (MeetingState.STOPPING, MeetingState.ERROR, True),
            (MeetingState.STOPPING, MeetingState.RECORDING, False),
            (MeetingState.STOPPING, MeetingState.CREATED, False),
            # STOPPED transitions
            (MeetingState.STOPPED, MeetingState.COMPLETED, True),
            (MeetingState.STOPPED, MeetingState.ERROR, True),
            (MeetingState.STOPPED, MeetingState.RECORDING, False),
            # COMPLETED transitions
            (MeetingState.COMPLETED, MeetingState.ERROR, True),
            (MeetingState.COMPLETED, MeetingState.RECORDING, False),
            # ERROR is terminal
            (MeetingState.ERROR, MeetingState.CREATED, False),
            (MeetingState.ERROR, MeetingState.RECORDING, False),
        ],
    )
    def test_can_transition_to(
        self,
        current: MeetingState,
        target: MeetingState,
        expected: bool,
    ) -> None:
        """Test state transition validation."""
        result = current.can_transition_to(target)
        assert result == expected, (
            f"transition {current.name} -> {target.name}: "
            f"expected {expected}, got {result}"
        )

    @pytest.mark.parametrize(
        ("value", "expected"),
        [
            (0, MeetingState.UNSPECIFIED),
            (1, MeetingState.CREATED),
            (2, MeetingState.RECORDING),
            (3, MeetingState.STOPPED),
            (4, MeetingState.COMPLETED),
            (5, MeetingState.ERROR),
            (6, MeetingState.STOPPING),
        ],
    )
    def test_from_int_valid(self, value: int, expected: MeetingState) -> None:
        """Test conversion from valid integers."""
        result = MeetingState.from_int(value)
        assert result == expected, (
            f"from_int({value}): expected {expected.name}, got {result.name}"
        )

    def test_from_int_invalid_raises(self) -> None:
        """Test conversion from invalid integer raises ValueError."""
        with pytest.raises(ValueError, match="Invalid meeting state"):
            MeetingState.from_int(99)


class TestMeetingId:
    """Tests for MeetingId NewType."""

    def test_meeting_id_is_uuid(self) -> None:
        """Test MeetingId wraps UUID."""
        uuid = UUID("12345678-1234-5678-1234-567812345678")
        meeting_id = MeetingId(uuid)
        assert meeting_id == uuid, (
            f"MeetingId should equal underlying UUID: expected {uuid}, got {meeting_id}"
        )

    def test_meeting_id_string_conversion(self) -> None:
        """Test MeetingId can be converted to string."""
        uuid = UUID("12345678-1234-5678-1234-567812345678")
        meeting_id = MeetingId(uuid)
        expected_str = "12345678-1234-5678-1234-567812345678"
        result_str = str(meeting_id)
        assert result_str == expected_str, (
            f"MeetingId string conversion failed: expected {expected_str!r}, got {result_str!r}"
        )
