"""Tests for ASR DTO validation and properties."""

from __future__ import annotations

from dataclasses import FrozenInstanceError

import pytest

from noteflow.infrastructure.asr.dto import (
    AsrResult,
    PartialUpdate,
    VadEvent,
    VadEventType,
    WordTiming,
)


class TestWordTimingDto:
    """Tests for WordTiming DTO."""

    @pytest.mark.parametrize(
        "attr,expected",
        [("word", "hello"), ("start", 0.0), ("end", 0.5), ("probability", 0.75)],
    )
    def test_word_timing_dto_attributes(self, attr: str, expected: object) -> None:
        """Test WordTiming DTO stores attributes correctly."""
        word = WordTiming(word="hello", start=0.0, end=0.5, probability=0.75)
        assert getattr(word, attr) == expected, f"WordTiming.{attr} should equal {expected!r}"

    def test_word_timing_dto_invalid_times_raises(self) -> None:
        with pytest.raises(ValueError, match=r"Word end .* < start"):
            WordTiming(word="bad", start=1.0, end=0.5, probability=0.5)

    @pytest.mark.parametrize("prob", [-0.1, 1.1])
    def test_word_timing_dto_invalid_probability_raises(self, prob: float) -> None:
        with pytest.raises(ValueError, match=r"Probability must be 0\.0-1\.0"):
            WordTiming(word="bad", start=0.0, end=0.1, probability=prob)

    def test_word_timing_frozen(self) -> None:
        word = WordTiming(word="hello", start=0.0, end=0.5, probability=0.9)
        with pytest.raises(FrozenInstanceError, match="cannot assign"):
            word.word = "mutate"


class TestAsrResultDto:
    """Tests for AsrResult DTO."""

    def test_asr_result_duration(self) -> None:
        result = AsrResult(text="hello", start=1.0, end=3.5)
        assert result.duration == 2.5, "AsrResult.duration should be end - start (3.5 - 1.0)"

    def test_asr_result_invalid_times_raises(self) -> None:
        with pytest.raises(ValueError, match=r"Segment end .* < start"):
            AsrResult(text="bad", start=2.0, end=1.0)


class TestPartialUpdateDto:
    """Tests for PartialUpdate DTO."""

    def test_partial_update_invalid_times_raises(self) -> None:
        with pytest.raises(ValueError, match=r"Partial end .* < start"):
            PartialUpdate(text="partial", start=2.0, end=1.0)


class TestVadEventDto:
    """Tests for VadEvent DTO."""

    def test_vad_event_invalid_timestamp_raises(self) -> None:
        with pytest.raises(ValueError, match="Timestamp must be non-negative"):
            VadEvent(event_type=VadEventType.SPEECH_START, timestamp=-1.0)

    @pytest.mark.parametrize("confidence", [-0.1, 1.1])
    def test_vad_event_invalid_confidence_raises(self, confidence: float) -> None:
        with pytest.raises(ValueError, match=r"Confidence must be 0\.0-1\.0"):
            VadEvent(event_type=VadEventType.SPEECH_END, timestamp=0.5, confidence=confidence)
