from datetime import datetime, timedelta
from unittest.mock import patch
from django.utils import timezone

import pytest
import time_machine
from django.urls import reverse
from music.models import Track
from podcasts.models import PodcastEpisode
from scrobbles.models import Scrobble


@pytest.mark.django_db
def test_get_not_allowed_from_mopidy(client, valid_auth_token):
    url = reverse("scrobbles:mopidy-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}
    response = client.get(url, headers=headers)
    assert response.status_code == 405


@pytest.mark.django_db
def test_bad_mopidy_request_data(client, valid_auth_token):
    url = reverse("scrobbles:mopidy-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}
    response = client.post(url, headers)
    assert response.status_code == 400
    assert (
        response.data["detail"]
        == "JSON parse error - Expecting value: line 1 column 1 (char 0)"
    )


@pytest.mark.skip("Need to refactor")
@pytest.mark.django_db
@patch("music.utils.lookup_artist_from_mb", return_value={})
@patch(
    "music.utils.lookup_album_dict_from_mb",
    return_value={"year": "1999", "mb_group_id": 1},
)
@patch("music.utils.lookup_track_from_mb", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
@patch("music.models.Album.fetch_artwork", return_value=None)
@patch("music.models.Album.scrape_allmusic", return_value=None)
def test_scrobble_mopidy_same_track_different_album(
    mock_lookup_artist,
    mock_lookup_album,
    mock_lookup_track,
    mock_lookup_artist_tadb,
    mock_lookup_album_tadb,
    mock_fetch_artwork,
    mock_scrape_allmusic,
    client,
    mopidy_track,
    mopidy_track_diff_album_request_data,
    valid_auth_token,
):
    url = reverse("scrobbles:mopidy-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}
    response = client.post(
        url,
        mopidy_track.request_data,
        content_type="application/json",
        headers=headers,
    )
    assert response.status_code == 200
    assert response.data == {"scrobble_id": 1}
    scrobble = Scrobble.objects.last()
    assert scrobble.media_obj.album.name == "Sublime"

    response = client.post(
        url,
        mopidy_track_diff_album_request_data,
        content_type="application/json",
    )

    assert response.status_code == 200
    assert response.data == {"scrobble_id": 2}
    scrobble = Scrobble.objects.last()
    assert scrobble.media_obj.__class__ == Track
    assert scrobble.media_obj.album.name == "Sublime"
    assert scrobble.media_obj.title == "Same in the End"


@pytest.mark.django_db
@patch(
    "podcasts.sources.podcastindex.lookup_podcast_from_podcastindex",
    return_value={},
)
def test_scrobble_mopidy_podcast(
    mock_lookup_podcast, client, mopidy_podcast_request_data, valid_auth_token
):
    url = reverse("scrobbles:mopidy-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}
    response = client.post(
        url,
        mopidy_podcast_request_data,
        content_type="application/json",
        headers=headers,
    )
    assert response.status_code == 200
    assert response.data == {"scrobble_id": 1}

    scrobble = Scrobble.objects.get(id=1)
    assert scrobble.media_obj.__class__ == PodcastEpisode
    assert scrobble.media_obj.title == "Up First"


@pytest.mark.skip("Need to refactor")
@pytest.mark.django_db
@patch("music.utils.lookup_artist_from_mb", return_value={})
@patch(
    "music.utils.lookup_album_dict_from_mb",
    return_value={"year": "1999", "mb_group_id": 1},
)
@patch("music.utils.lookup_track_from_mb", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
@patch("music.models.Album.fetch_artwork", return_value=None)
@patch("music.models.Album.scrape_allmusic", return_value=None)
def test_scrobble_jellyfin_track(
    mock_lookup_artist,
    mock_lookup_album,
    mock_lookup_track,
    mock_lookup_artist_tadb,
    mock_lookup_album_tadb,
    mock_fetch_artwork,
    mock_scrape_allmusic,
    client,
    jellyfin_track,
    valid_auth_token,
):
    url = reverse("scrobbles:jellyfin-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}

    with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
        jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
            "%Y-%m-%d %H:%M:%S"
        )
        response = client.post(
            url,
            jellyfin_track.request_json,
            content_type="application/json",
            headers=headers,
        )
        assert response.status_code == 200
        assert response.data == {"scrobble_id": 1}

        scrobble = Scrobble.objects.get(id=1)
        assert scrobble.media_obj.__class__ == Track
        assert scrobble.media_obj.title == "Emotion"


@pytest.mark.skip("Need to refactor")
@pytest.mark.django_db
@patch("music.utils.lookup_artist_from_mb", return_value={})
@patch(
    "music.utils.lookup_album_dict_from_mb",
    return_value={"year": "1999", "mb_group_id": 1},
)
@patch("music.utils.lookup_track_from_mb", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
@patch("music.models.Album.fetch_artwork", return_value=None)
@patch("music.models.Album.scrape_allmusic", return_value=None)
def test_scrobble_jellyfin_track_update(
    mock_lookup_artist,
    mock_lookup_album,
    mock_lookup_track,
    mock_lookup_artist_tadb,
    mock_lookup_album_tadb,
    mock_fetch_artwork,
    mock_scrape_allmusic,
    test_track,
    client,
    jellyfin_track,
    valid_auth_token,
):
    Scrobble.objects.create(
        timestamp=timezone.now() - timedelta(minutes=0.5),
        track=Track.objects.first(),
        user_id=1,
    )
    url = reverse("scrobbles:jellyfin-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}

    jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
        "%Y-%m-%d %H:%M:%S"
    )
    response = client.post(
        url,
        jellyfin_track.request_json,
        content_type="application/json",
        headers=headers,
    )

    assert response.status_code == 200
    assert response.data == {"scrobble_id": 1}

    scrobble = Scrobble.objects.get(id=1)
    assert scrobble.media_obj.__class__ == Track
    assert scrobble.media_obj.title == "Emotion"


@pytest.mark.skip("Need to refactor")
@pytest.mark.django_db
@patch("music.utils.lookup_artist_from_mb", return_value={})
@patch(
    "music.utils.lookup_album_dict_from_mb",
    return_value={"year": "1999", "mb_group_id": 1},
)
@patch("music.utils.lookup_track_from_mb", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
@patch("music.models.Album.fetch_artwork", return_value=None)
@patch("music.models.Album.scrape_allmusic", return_value=None)
def test_scrobble_jellyfin_track_create_new(
    mock_lookup_artist,
    mock_lookup_album,
    mock_lookup_track,
    mock_lookup_artist_tadb,
    mock_lookup_album_tadb,
    mock_fetch_artwork,
    mock_scrape_allmusic,
    test_track,
    client,
    jellyfin_track,
    valid_auth_token,
):
    url = reverse("scrobbles:jellyfin-webhook")
    headers = {"Authorization": f"Token {valid_auth_token}"}
    Scrobble.objects.create(
        timestamp=timezone.now() - timedelta(minutes=1),
        track=Track.objects.first(),
        user_id=1,
    )
    jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
        "%Y-%m-%d %H:%M:%S"
    )
    response = client.post(
        url,
        jellyfin_track.request_json,
        content_type="application/json",
        headers=headers,
    )

    assert response.status_code == 200
    assert response.data == {"scrobble_id": 2}

    scrobble = Scrobble.objects.get(id=1)
    assert scrobble.media_obj.__class__ == Track
    assert scrobble.media_obj.title == "Emotion"
