import numpy as np

from sentence_api.processing import (
    MOSS_ALGORITHM_VERSION,
    document_from_transcript,
    split_sentence_text,
)
from sentence_api.models import SentenceBoundary
from sentence_api.transcription import (
    Transcript,
    TranscriptionSegment,
    WordTimestamp,
    _wav_bytes,
)


SAMPLE_RATE = 16000
VIDEO_HASH = "a" * 64


class WordTimestampTranscriber:
    def __init__(self, transcript):
        self.transcript = transcript

    @property
    def available(self):
        return True

    def transcribe(self, audio_path, language=None):
        return self.transcript


def _speech(seconds: float) -> np.ndarray:
    t = np.arange(int(seconds * SAMPLE_RATE)) / SAMPLE_RATE
    return 0.25 * np.sin(2 * np.pi * 220 * t)


def _silence(seconds: float) -> np.ndarray:
    return np.zeros(int(seconds * SAMPLE_RATE))


def test_document_from_transcript_splits_sentences_at_punctuation(tmp_path):
    samples = np.concatenate(
        [
            _speech(8.0),
            _speech(1.5),
            _speech(10.5),
            _speech(4.0),
        ]
    ).astype(np.float32)
    wav = tmp_path / "audio.wav"
    wav.write_bytes(_wav_bytes(samples, SAMPLE_RATE))
    transcript = Transcript(
        text=(
            "So I've been single for about four years now and I find it hard to meet "
            "a guy especially in California. I've tried dating apps, I've met friends "
            "through friends, I've done online dating and I just feel like most of the "
            "guys that I meet aren't serious about a relationship."
        ),
        segments=[
            TranscriptionSegment(
                start_seconds=0.0,
                end_seconds=8.0,
                text=(
                    "So I've been single for about four years now and I find it hard "
                    "to meet a guy especially in"
                ),
            ),
            TranscriptionSegment(
                start_seconds=8.0,
                end_seconds=9.5,
                text="California.",
                words=[WordTimestamp(8.0, 9.5, "California.")],
            ),
            TranscriptionSegment(
                start_seconds=9.5,
                end_seconds=20.0,
                text=(
                    "I've tried dating apps, I've met friends through friends, "
                    "I've done online dating"
                ),
            ),
            TranscriptionSegment(
                start_seconds=20.0,
                end_seconds=24.0,
                text=(
                    "and I just feel like most of the guys that I meet aren't serious "
                    "about a relationship."
                ),
            ),
        ],
    )

    document = document_from_transcript(
        video_hash=VIDEO_HASH,
        duration_ms=24000,
        transcript=transcript,
        language="en",
        audio_path=wav,
    )

    assert document.algorithm_version == MOSS_ALGORITHM_VERSION
    assert [sentence.text for sentence in document.sentences] == [
        (
            "So I've been single for about four years now and I find it hard to meet "
            "a guy especially in California."
        ),
        (
            "I've tried dating apps, I've met friends through friends, I've done "
            "online dating and I just feel like most of the guys that I meet aren't "
            "serious about a relationship."
        ),
    ]
    assert document.sentences[0].start_ms == 0
    assert document.sentences[0].end_ms == 9500
    assert document.sentences[1].start_ms == 9500
    assert document.sentences[1].end_ms == 24000
    assert all(sentence.reference_speech_duration_ms > 0 for sentence in document.sentences)


def test_split_sentence_text_uses_whisper_word_timestamps(tmp_path):
    transcript = Transcript(
        text="Alpha beta. Gamma delta.",
        segments=[
            TranscriptionSegment(
                start_seconds=0.0,
                end_seconds=1.0,
                text="Alpha beta. Gamma delta.",
                words=[
                    WordTimestamp(0.0, 0.25, "Alpha"),
                    WordTimestamp(0.25, 0.5, "beta."),
                    WordTimestamp(0.5, 0.75, "Gamma"),
                    WordTimestamp(0.75, 1.0, "delta."),
                ],
            )
        ],
    )
    audio_path = tmp_path / "sentence.wav"
    audio_path.write_bytes(_wav_bytes(_speech(1.0), SAMPLE_RATE))
    source = SentenceBoundary(
        index=2,
        start_ms=1000,
        end_ms=5000,
        text="Alpha beta Gamma delta",
        language="en",
        reference_speech_duration_ms=3800,
    )

    replacements = split_sentence_text(
        transcriber=WordTimestampTranscriber(transcript),
        media_path=audio_path,
        sentence=source,
        text="Alpha beta\nGamma delta",
        language="en",
    )

    assert [(item.text, item.start_ms, item.end_ms) for item in replacements] == [
        ("Alpha beta", 1000, 3000),
        ("Gamma delta", 3000, 5000),
    ]
