import random
from datetime import timedelta

import pytest
from dateutil.parser import isoparse
from libretime_api_client.v2 import ApiClient

from libretime_playout.player.events import EventKind
from libretime_playout.player.schedule import (
    generate_file_events,
    generate_live_events,
    generate_webstream_events,
    get_schedule,
)


@pytest.fixture(name="api_client")
def _api_client_fixture():
    base_url = "http://localhost"
    return ApiClient(base_url=base_url, api_key="test_key")


SHOW_1 = {"id": 1, "name": "Show 1", "live_enabled": False}
SHOW_2 = {"id": 2, "name": "Show 2", "live_enabled": False}
SHOW_3 = {"id": 3, "name": "Show 3", "live_enabled": True}
SHOW_4 = {"id": 4, "name": "Show 4", "live_enabled": False}

SHOW_INSTANCE_1 = {
    "id": 1,
    "starts_at": "2022-09-05T11:00:00Z",
    "ends_at": "2022-09-05T11:10:00Z",
    "show": 1,
}
SHOW_INSTANCE_2 = {
    "id": 2,
    "starts_at": "2022-09-05T11:10:00Z",
    "ends_at": "2022-09-05T12:10:00Z",
    "show": 2,
}
SHOW_INSTANCE_3 = {
    "id": 3,
    "starts_at": "2022-09-05T12:10:00Z",
    "ends_at": "2022-09-05T13:00:00Z",
    "show": 3,
}
SHOW_INSTANCE_4 = {
    "id": 4,
    "starts_at": "2022-09-05T13:00:00Z",
    "ends_at": "2022-09-05T14:10:00Z",
    "show": 4,
}

FILE_1 = {
    "id": 1,
    "mime": "audio/flac",
    "length": "00:03:41.041723",
    "replay_gain": "4.52",
    "cue_in": "00:00:08.252450",
    "cue_out": "00:03:27.208000",
    "artist_name": "Nils Frahm",
    "album_title": "Tripping with Nils Frahm",
    "track_title": "The Dane",
    "url": None,
    "size": 10000,
}
FILE_2 = {
    "id": 2,
    "mime": "audio/flac",
    "length": "00:06:08.668798",
    "replay_gain": "11.46",
    "cue_in": "00:00:13.700800",
    "cue_out": "00:05:15.845000",
    "artist_name": "Nils Frahm",
    "album_title": "Tripping with Nils Frahm",
    "track_title": "My Friend the Forest",
    "url": None,
    "size": 10000,
}
FILE_3 = {
    "id": 3,
    "mime": "audio/flac",
    "length": "00:14:18.400000",
    "replay_gain": "-2.13",
    "cue_in": "00:00:55.121100",
    "cue_out": "00:14:18.400000",
    "artist_name": "Nils Frahm",
    "album_title": "Tripping with Nils Frahm",
    "track_title": "All Melody",
    "url": None,
    "size": 10000,
}
FILE_4 = {
    "id": 4,
    "mime": "audio/flac",
    "length": "00:10:45.472200",
    "replay_gain": "-1.65",
    "cue_in": "00:00:00",
    "cue_out": "00:10:26.891000",
    "artist_name": "Nils Frahm",
    "album_title": "Tripping with Nils Frahm",
    "track_title": "#2",
    "url": None,
    "size": 10000,
}
FILE_5 = {
    "id": 5,
    "mime": "audio/mp3",
    "length": "00:59:04.989000",
    "replay_gain": "-1.39",
    "cue_in": "00:00:00",
    "cue_out": "00:58:59.130000",
    "artist_name": "Democracy Now! Audio",
    "album_title": "Democracy Now! Audio",
    "track_title": "Democracy Now! 2022-09-05 Monday",
    "url": None,
    "size": 10000,
}

WEBSTREAM_1 = {
    "id": 1,
    "name": "External radio",
    "url": "http://stream.radio.org/main.ogg",
}

SCHEDULE_1 = {
    "id": 1,
    "starts_at": "2022-09-05T11:00:00Z",
    "ends_at": "2022-09-05T11:05:02.144200Z",
    "cue_in": "00:00:13.700800",
    "cue_out": "00:05:15.845000",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 2,
    "instance": 1,
    "length": "00:05:02.144200",
    "stream": None,
}
SCHEDULE_2 = {
    "id": 2,
    "starts_at": "2022-09-05T11:05:02.144200Z",
    "ends_at": "2022-09-05T11:10:00Z",
    "cue_in": "00:00:00",
    "cue_out": "00:04:57.855800",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 4,
    "instance": 1,
    "length": "00:10:26.891000",
    "stream": None,
}
SCHEDULE_3 = {
    "id": 3,
    "starts_at": "2022-09-05T11:10:00Z",
    "ends_at": "2022-09-05T12:08:59Z",
    "cue_in": "00:00:00",
    "cue_out": "00:58:59.130000",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 5,
    "instance": 2,
    "length": "00:58:59.130000",
    "stream": None,
}
SCHEDULE_4 = {
    "id": 4,
    "starts_at": "2022-09-05T12:08:59Z",
    "ends_at": "2022-09-05T12:10:00Z",
    "cue_in": "00:00:00",
    "cue_out": "00:01:01",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 4,
    "instance": 2,
    "length": "00:10:26.891000",
    "stream": None,
}
SCHEDULE_5 = {
    "id": 5,
    "starts_at": "2022-09-05T12:10:00Z",
    "ends_at": "2022-09-05T12:40:00Z",
    "cue_in": "00:00:00",
    "cue_out": "00:30:00",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": None,
    "instance": 3,
    "length": "00:30:00",
    "stream": 1,
}
SCHEDULE_6 = {
    "id": 6,
    "starts_at": "2022-09-05T12:40:00Z",
    "ends_at": "2022-09-05T12:53:23Z",
    "cue_in": "00:00:55.121100",
    "cue_out": "00:14:18.400000",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 3,
    "instance": 3,
    "length": "00:13:23.278900",
    "stream": None,
}
SCHEDULE_7 = {
    "id": 7,
    "starts_at": "2022-09-05T12:53:23Z",
    "ends_at": "2022-09-05T12:58:25Z",
    "cue_in": "00:00:13.700800",
    "cue_out": "00:05:15.845000",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 2,
    "instance": 3,
    "length": "00:05:02.144200",
    "stream": None,
}
SCHEDULE_8 = {
    "id": 8,
    "starts_at": "2022-09-05T12:58:25Z",
    "ends_at": "2022-09-05T13:00:00Z",
    "cue_in": "00:00:08.252450",
    "cue_out": "00:01:35",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 1,
    "instance": 3,
    "length": "00:03:18.955550",
    "stream": None,
}
SCHEDULE_9 = {
    "id": 9,
    "starts_at": "2022-09-05T13:00:00Z",
    "ends_at": "2022-09-05T13:05:02.144200Z",
    "cue_in": "00:00:13.700800",
    "cue_out": "00:05:15.845000",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 2,
    "instance": 4,
    "length": "00:05:02.144200",
    "stream": None,
}
SCHEDULE_10 = {
    "id": 10,
    "starts_at": "2022-09-05T13:05:02.144200Z",
    "ends_at": "2022-09-05T13:10:00Z",
    "cue_in": "00:00:00",
    "cue_out": "00:04:57.855800",
    "fade_in": "00:00:00.500000",
    "fade_out": "00:00:00.500000",
    "file": 4,
    "instance": 4,
    "length": "00:10:26.891000",
    "stream": None,
}
SCHEDULE = [
    SCHEDULE_1,
    SCHEDULE_2,
    SCHEDULE_3,
    SCHEDULE_4,
    SCHEDULE_5,
    SCHEDULE_6,
    SCHEDULE_7,
    SCHEDULE_8,
    SCHEDULE_9,
    SCHEDULE_10,
]


def test_generate_live_events():
    show_instance_3 = SHOW_INSTANCE_3.copy()
    show_instance_3["starts_at"] = isoparse(show_instance_3["starts_at"])
    show_instance_3["ends_at"] = isoparse(show_instance_3["ends_at"])

    result = {}
    generate_live_events(result, show_instance_3, 0.0)
    assert result == {
        "2022-09-05-13-00-00": {
            "type": EventKind.EVENT,
            "event_type": "kick_out",
            "start": "2022-09-05-13-00-00",
            "end": "2022-09-05-13-00-00",
        }
    }

    result = {}
    generate_live_events(result, show_instance_3, 2.0)
    assert result == {
        "2022-09-05-12-59-58": {
            "type": EventKind.EVENT,
            "event_type": "switch_off",
            "start": "2022-09-05-12-59-58",
            "end": "2022-09-05-12-59-58",
        },
        "2022-09-05-13-00-00": {
            "type": EventKind.EVENT,
            "event_type": "kick_out",
            "start": "2022-09-05-13-00-00",
            "end": "2022-09-05-13-00-00",
        },
    }


def test_generate_file_events():
    schedule_1 = SCHEDULE_1.copy()
    schedule_1["starts_at"] = isoparse(schedule_1["starts_at"])
    schedule_1["ends_at"] = isoparse(schedule_1["ends_at"])

    result = {}
    generate_file_events(result, schedule_1, FILE_2, SHOW_1)
    assert result == {
        "2022-09-05-11-00-00": {
            "type": EventKind.FILE,
            "row_id": 1,
            "start": "2022-09-05-11-00-00",
            "end": "2022-09-05-11-05-02",
            "uri": None,
            "id": 2,
            "show_name": "Show 1",
            "fade_in": 500.0,
            "fade_out": 500.0,
            "cue_in": 13.7008,
            "cue_out": 315.845,
            "metadata": {
                "track_title": "My Friend the Forest",
                "artist_name": "Nils Frahm",
                "mime": "audio/flac",
            },
            "replay_gain": "11.46",
            "filesize": 10000,
        }
    }


def test_generate_webstream_events():
    schedule_5 = SCHEDULE_5.copy()
    schedule_5["starts_at"] = isoparse(schedule_5["starts_at"])
    schedule_5["ends_at"] = isoparse(schedule_5["ends_at"])

    result = {}
    generate_webstream_events(result, schedule_5, WEBSTREAM_1, SHOW_3)
    assert result == {
        "2022-09-05-12-10-00": {
            "type": EventKind.STREAM_BUFFER_START,
            "row_id": 5,
            "start": "2022-09-05-12-09-55",
            "end": "2022-09-05-12-09-55",
            "uri": "http://stream.radio.org/main.ogg",
            "id": 1,
        },
        "2022-09-05-12-10-00_0": {
            "type": EventKind.STREAM_OUTPUT_START,
            "row_id": 5,
            "start": "2022-09-05-12-10-00",
            "end": "2022-09-05-12-40-00",
            "uri": "http://stream.radio.org/main.ogg",
            "id": 1,
            "show_name": "Show 3",
        },
        "2022-09-05-12-40-00": {
            "type": EventKind.STREAM_BUFFER_END,
            "row_id": 5,
            "start": "2022-09-05-12-40-00",
            "end": "2022-09-05-12-40-00",
            "uri": "http://stream.radio.org/main.ogg",
            "id": 1,
        },
        "2022-09-05-12-40-00_0": {
            "type": EventKind.STREAM_OUTPUT_END,
            "row_id": 5,
            "start": "2022-09-05-12-40-00",
            "end": "2022-09-05-12-40-00",
            "uri": "http://stream.radio.org/main.ogg",
            "id": 1,
        },
    }


@pytest.mark.parametrize(
    "schedule",
    [
        (SCHEDULE),
        (random.sample(SCHEDULE, len(SCHEDULE))),
    ],
)
def test_get_schedule(schedule, requests_mock, api_client: ApiClient):
    base_url = api_client.base_url

    requests_mock.get(
        f"{base_url}/api/v2/stream/preferences",
        json={
            "input_fade_transition": 2.0,
            "message_format": 0,
            "message_offline": "",
        },
    )

    requests_mock.get(f"{base_url}/api/v2/schedule", json=schedule)

    requests_mock.get(f"{base_url}/api/v2/shows/1", json=SHOW_1)
    requests_mock.get(f"{base_url}/api/v2/shows/2", json=SHOW_2)
    requests_mock.get(f"{base_url}/api/v2/shows/3", json=SHOW_3)
    requests_mock.get(f"{base_url}/api/v2/shows/4", json=SHOW_4)
    requests_mock.get(f"{base_url}/api/v2/show-instances/1", json=SHOW_INSTANCE_1)
    requests_mock.get(f"{base_url}/api/v2/show-instances/2", json=SHOW_INSTANCE_2)
    requests_mock.get(f"{base_url}/api/v2/show-instances/3", json=SHOW_INSTANCE_3)
    requests_mock.get(f"{base_url}/api/v2/show-instances/4", json=SHOW_INSTANCE_4)
    requests_mock.get(f"{base_url}/api/v2/files/1", json=FILE_1)
    requests_mock.get(f"{base_url}/api/v2/files/2", json=FILE_2)
    requests_mock.get(f"{base_url}/api/v2/files/3", json=FILE_3)
    requests_mock.get(f"{base_url}/api/v2/files/4", json=FILE_4)
    requests_mock.get(f"{base_url}/api/v2/files/5", json=FILE_5)
    requests_mock.get(f"{base_url}/api/v2/webstreams/1", json=WEBSTREAM_1)

    assert get_schedule(api_client) == {
        "media": {
            "2022-09-05-11-00-00": {
                "type": EventKind.FILE,
                "row_id": 1,
                "start": "2022-09-05-11-00-00",
                "end": "2022-09-05-11-05-02",
                "uri": None,
                "id": 2,
                "show_name": "Show 1",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 13.7008,
                "cue_out": 315.845,
                "metadata": {
                    "track_title": "My Friend the Forest",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "11.46",
                "filesize": 10000,
            },
            "2022-09-05-11-05-02": {
                "type": EventKind.FILE,
                "row_id": 2,
                "start": "2022-09-05-11-05-02",
                "end": "2022-09-05-11-10-00",
                "uri": None,
                "id": 4,
                "show_name": "Show 1",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 0.0,
                "cue_out": 297.8558,
                "metadata": {
                    "track_title": "#2",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "-1.65",
                "filesize": 10000,
            },
            "2022-09-05-11-10-00": {
                "type": EventKind.FILE,
                "row_id": 3,
                "start": "2022-09-05-11-10-00",
                "end": "2022-09-05-12-08-59",
                "uri": None,
                "id": 5,
                "show_name": "Show 2",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 0.0,
                "cue_out": 3539.13,
                "metadata": {
                    "track_title": "Democracy Now! 2022-09-05 Monday",
                    "artist_name": "Democracy Now! Audio",
                    "mime": "audio/mp3",
                },
                "replay_gain": "-1.39",
                "filesize": 10000,
            },
            "2022-09-05-12-08-59": {
                "type": EventKind.FILE,
                "row_id": 4,
                "start": "2022-09-05-12-08-59",
                "end": "2022-09-05-12-10-00",
                "uri": None,
                "id": 4,
                "show_name": "Show 2",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 0.0,
                "cue_out": 61.0,
                "metadata": {
                    "track_title": "#2",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "-1.65",
                "filesize": 10000,
            },
            "2022-09-05-12-10-00": {
                "type": EventKind.STREAM_BUFFER_START,
                "row_id": 5,
                "start": "2022-09-05-12-09-55",
                "end": "2022-09-05-12-09-55",
                "uri": "http://stream.radio.org/main.ogg",
                "id": 1,
            },
            "2022-09-05-12-10-00_0": {
                "type": EventKind.STREAM_OUTPUT_START,
                "row_id": 5,
                "start": "2022-09-05-12-10-00",
                "end": "2022-09-05-12-40-00",
                "uri": "http://stream.radio.org/main.ogg",
                "id": 1,
                "show_name": "Show 3",
            },
            "2022-09-05-12-40-00": {
                "type": EventKind.STREAM_BUFFER_END,
                "row_id": 5,
                "start": "2022-09-05-12-40-00",
                "end": "2022-09-05-12-40-00",
                "uri": "http://stream.radio.org/main.ogg",
                "id": 1,
            },
            "2022-09-05-12-40-00_0": {
                "type": EventKind.STREAM_OUTPUT_END,
                "row_id": 5,
                "start": "2022-09-05-12-40-00",
                "end": "2022-09-05-12-40-00",
                "uri": "http://stream.radio.org/main.ogg",
                "id": 1,
            },
            "2022-09-05-12-40-00_1": {
                "type": EventKind.FILE,
                "row_id": 6,
                "start": "2022-09-05-12-40-00",
                "end": "2022-09-05-12-53-23",
                "uri": None,
                "id": 3,
                "show_name": "Show 3",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 55.1211,
                "cue_out": 858.4,
                "metadata": {
                    "track_title": "All Melody",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "-2.13",
                "filesize": 10000,
            },
            "2022-09-05-12-53-23": {
                "type": EventKind.FILE,
                "row_id": 7,
                "start": "2022-09-05-12-53-23",
                "end": "2022-09-05-12-58-25",
                "uri": None,
                "id": 2,
                "show_name": "Show 3",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 13.7008,
                "cue_out": 315.845,
                "metadata": {
                    "track_title": "My Friend the Forest",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "11.46",
                "filesize": 10000,
            },
            "2022-09-05-12-58-25": {
                "type": EventKind.FILE,
                "row_id": 8,
                "start": "2022-09-05-12-58-25",
                "end": "2022-09-05-13-00-00",
                "uri": None,
                "id": 1,
                "show_name": "Show 3",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 8.25245,
                "cue_out": 95.0,
                "metadata": {
                    "track_title": "The Dane",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "4.52",
                "filesize": 10000,
            },
            "2022-09-05-12-59-58": {
                "type": EventKind.EVENT,
                "event_type": "switch_off",
                "start": "2022-09-05-12-59-58",
                "end": "2022-09-05-12-59-58",
            },
            "2022-09-05-13-00-00": {
                "type": EventKind.EVENT,
                "event_type": "kick_out",
                "start": "2022-09-05-13-00-00",
                "end": "2022-09-05-13-00-00",
            },
            "2022-09-05-13-00-00_0": {
                "type": EventKind.FILE,
                "row_id": 9,
                "start": "2022-09-05-13-00-00",
                "end": "2022-09-05-13-05-02",
                "uri": None,
                "id": 2,
                "show_name": "Show 4",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 13.7008,
                "cue_out": 315.845,
                "metadata": {
                    "track_title": "My Friend the Forest",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "11.46",
                "filesize": 10000,
            },
            "2022-09-05-13-05-02": {
                "type": EventKind.FILE,
                "row_id": 10,
                "start": "2022-09-05-13-05-02",
                "end": "2022-09-05-13-10-00",
                "uri": None,
                "id": 4,
                "show_name": "Show 4",
                "fade_in": 500.0,
                "fade_out": 500.0,
                "cue_in": 0.0,
                "cue_out": 297.8558,
                "metadata": {
                    "track_title": "#2",
                    "artist_name": "Nils Frahm",
                    "mime": "audio/flac",
                },
                "replay_gain": "-1.65",
                "filesize": 10000,
            },
        }
    }