import numpy as np

from sentence_api.audio_metrics import AudioMetrics, analyze_samples
from sentence_api.scoring import align_text, duration_similarity_score, score_attempt, tokenize


def test_tokenize_supports_mixed_chinese_and_english():
    assert tokenize("你好，World! Don't stop.") == ["你", "好", "world", "don't", "stop"]


def test_identical_reading_with_matching_duration_scores_100():
    result = score_attempt(
        reference_text="The meeting starts at nine.",
        recognized_text="The meeting starts at nine",
        reference_speech_duration_ms=2000,
        student_metrics=AudioMetrics(
            recording_duration_ms=2400,
            speech_duration_ms=2000,
            internal_silence_ms=0,
            internal_pause_ratio=0.0,
        ),
    )

    assert result.overall_score == 100
    assert result.duration_score == 100
    assert result.missing_tokens == []


def test_alignment_reports_missing_extra_and_substituted_tokens():
    result = align_text(
        "The meeting starts at nine",
        "The lesson start at nine today",
    )

    assert result.content_score < 70
    assert result.extra_tokens == ["today"]
    assert ("meeting", "lesson") in result.substitutions
    assert ("starts", "start") in result.substitutions


def test_duration_score_allows_students_to_read_more_slowly():
    assert duration_similarity_score(0.8) == 100
    assert duration_similarity_score(1.3) == 100
    assert duration_similarity_score(1.5) == 60
    assert duration_similarity_score(1.8) == 20


def test_vad_excludes_leading_and_trailing_silence():
    sample_rate = 16_000
    silence = np.zeros(sample_rate // 2, dtype=np.float32)
    time = np.arange(sample_rate, dtype=np.float32) / sample_rate
    speech = (0.25 * np.sin(2 * np.pi * 220 * time)).astype(np.float32)
    metrics = analyze_samples(np.concatenate([silence, speech, silence]), sample_rate)

    assert metrics.recording_duration_ms == 2000
    assert 900 <= metrics.speech_duration_ms <= 1050
