from datetime import datetime, timedelta
from unittest.mock import patch

import pytest
import time_machine
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils import timezone
from music.aggregators import live_charts, scrobble_counts, week_of_scrobbles
from scrobbles.models import Scrobble


def build_scrobbles(client, request_json, num=7, spacing=2, auth_token=None):
    import pytz
    from rest_framework.authtoken.models import Token

    url = reverse("scrobbles:mopidy-webhook")
    user = get_user_model().objects.create(username="Test User")
    user.profile.timezone = "US/Eastern"
    user.profile.save()
    headers = {}
    if auth_token:
        headers = {"Authorization": f"Token {auth_token}"}
        user = Token.objects.get(key=auth_token).user

    client.post(url, request_json, content_type="application/json", headers=headers)
    track = Scrobble.objects.last().track

    est = pytz.timezone("US/Eastern")
    for i in range(num):
        naive_time = timezone.now().replace(tzinfo=None) - timedelta(days=i * spacing)
        aware_time = est.localize(naive_time)
        Scrobble.objects.create(
            user=user,
            track=track,
            timestamp=aware_time,
            played_to_completion=True,
            source="Mopidy",
        )
    return user


@pytest.mark.django_db
@patch("music.models.get_album_metadata_with_artist", return_value={})
@patch("music.models.get_track_metadata_with_artist", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={})
@time_machine.travel(datetime(2022, 3, 4, 1, 24))
def test_scrobble_counts_data(
    mock_lookup_album_tadb,
    mock_lookup_artist_tadb,
    mock_get_track,
    mock_get_album,
    client,
    mopidy_track,
    valid_auth_token,
):
    user = build_scrobbles(
        client, mopidy_track.request_json, auth_token=valid_auth_token
    )
    count_dict = scrobble_counts(user)
    assert count_dict == {
        "alltime": 7,
        "month": 2,
        "today": 1,
        "week": 3,
        "year": 7,
    }


@pytest.mark.django_db
@patch("music.models.get_album_metadata_with_artist", return_value={})
@patch("music.models.get_track_metadata_with_artist", return_value={})
@patch("music.models.lookup_artist_from_tadb", return_value={})
@patch("music.models.lookup_album_from_tadb", return_value={})
@time_machine.travel(datetime(2022, 3, 4, 1, 24))
def test_live_charts(
    mock_lookup_album_tadb,
    mock_lookup_artist_tadb,
    mock_get_track,
    mock_get_album,
    client,
    mopidy_track,
    valid_auth_token,
):
    user = build_scrobbles(
        client, mopidy_track.request_json, 7, 1, auth_token=valid_auth_token
    )

    week = week_of_scrobbles(user)
    assert list(week.values()) == [1, 1, 1, 1, 1, 1, 1]

    tops = live_charts(user)
    assert tops[0].title == "Same in the End"

    tops = live_charts(user, chart_period="week")
    assert tops[0].title == "Same in the End"

    tops = live_charts(user, chart_period="month")
    assert tops[0].title == "Same in the End"

    tops = live_charts(user, chart_period="year")
    assert tops[0].title == "Same in the End"

    tops = live_charts(user, chart_period="week", media_type="Artist")
    assert tops[0].name == "Sublime"

    tops = live_charts(user, chart_period="month", media_type="Artist")
    assert tops[0].name == "Sublime"

    tops = live_charts(user, chart_period="year", media_type="Artist")
    assert tops[0].name == "Sublime"
