"""Tests for src/composer/converters.py — rhythm_to_midi, melodic_to_midi."""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parents[1]))

import pytest
from src.composer.converters import rhythm_to_midi, melodic_to_midi
from src.core.schema import MidiNote


class TestRhythmToMidi:
    """Tests for rhythm_to_midi() — channel → GM pitch mapping."""

    def test_rhythm_to_midi_kick_channel(self):
        """Channel 11 (kick) maps to pitch 36 with correct start/duration/velocity."""
        note_dict = {
            11: [
                {"pos": 0.0, "len": 0.25, "key": 36, "vel": 115},
                {"pos": 1.0, "len": 0.25, "key": 36, "vel": 100},
            ]
        }
        result = rhythm_to_midi(note_dict)

        assert len(result) == 2
        # Pitch is resolved from CHANNEL_PITCH, not from the dict's "key"
        assert result[0].pitch == 36
        assert result[0].start == 0.0
        assert result[0].duration == 0.25
        assert result[0].velocity == 115

        assert result[1].pitch == 36
        assert result[1].start == 1.0
        assert result[1].duration == 0.25
        assert result[1].velocity == 100

    def test_rhythm_to_midi_hihat_channel(self):
        """Channel 15 (hihat) maps to pitch 42."""
        note_dict = {15: [{"pos": 0.0, "len": 0.125, "key": 42, "vel": 90}]}
        result = rhythm_to_midi(note_dict)

        assert len(result) == 1
        assert result[0].pitch == 42
        assert result[0].start == 0.0
        assert result[0].duration == 0.125
        assert result[0].velocity == 90

    def test_rhythm_to_midi_unknown_channel(self):
        """Unknown channel (not in CHANNEL_PITCH) defaults to pitch 60."""
        note_dict = {99: [{"pos": 0.0, "len": 0.25, "key": 60, "vel": 100}]}
        result = rhythm_to_midi(note_dict)

        assert len(result) == 1
        assert result[0].pitch == 60  # default fallback
        assert result[0].start == 0.0

    def test_rhythm_to_midi_multi_channel(self):
        """3 different channels return a flat list with all notes combined."""
        note_dict = {
            11: [{"pos": 0.0, "len": 0.25, "key": 36, "vel": 115}],
            15: [{"pos": 0.5, "len": 0.125, "key": 42, "vel": 90}],
            10: [{"pos": 1.0, "len": 0.25, "key": 39, "vel": 80}],
        }
        result = rhythm_to_midi(note_dict)

        assert len(result) == 3
        pitches = {n.pitch for n in result}
        assert pitches == {36, 42, 39}


class TestMelodicToMidi:
    """Tests for melodic_to_midi() — key field used directly as pitch."""

    def test_melodic_to_midi_uses_key_as_pitch(self):
        """key=60 → pitch 60 (key field is used directly, not mapped)."""
        note_list = [
            {"pos": 0.0, "len": 0.5, "key": 60, "vel": 100},
            {"pos": 0.5, "len": 0.5, "key": 64, "vel": 90},
            {"pos": 1.0, "len": 0.5, "key": 67, "vel": 95},
        ]
        result = melodic_to_midi(note_list)

        assert len(result) == 3
        assert result[0].pitch == 60
        assert result[1].pitch == 64
        assert result[2].pitch == 67
        assert result[0].start == 0.0
        assert result[0].duration == 0.5
        assert result[0].velocity == 100

    def test_melodic_to_midi_empty_list(self):
        """Empty list returns empty list."""
        result = melodic_to_midi([])
        assert result == []
