from datetime import datetime

import pytz
from django.contrib.auth import get_user_model
from django.utils import timezone
from music.models import Artist, Track
from scrobbles.models import Scrobble

from vrobbler.apps.scrobbles.utils import (
    deduplicate_scrobbles,
    timestamp_user_tz_to_utc,
)

User = get_user_model()


def test_timestamp_user_tz_to_utc():
    timestamp = timestamp_user_tz_to_utc(1685561082, pytz.timezone("US/Eastern"))
    assert timestamp == datetime(2023, 5, 31, 23, 24, 42, tzinfo=pytz.utc)


def _make_track():
    artist = Artist.objects.create(name="Carly Rae Jepsen")
    return Track.objects.create(
        title="Emotion",
        artist_fk=artist,
        base_run_time_seconds=60,
    )


def test_deduplicate_scrobbles_removes_exact_duplicates(db):
    user = User.objects.create(email="dup@example.com")
    track = _make_track()
    timestamp = timezone.now().replace(microsecond=0)
    stop_timestamp = timestamp + timezone.timedelta(seconds=60)
    for _ in range(3):
        Scrobble.objects.create(
            user=user,
            track=track,
            media_type="Track",
            timestamp=timestamp,
            stop_timestamp=stop_timestamp,
        )

    count = deduplicate_scrobbles(commit=True)

    assert count == 2
    assert Scrobble.objects.filter(user=user, track=track).count() == 1


def test_deduplicate_scrobbles_keeps_different_media(db):
    user = User.objects.create(email="media@example.com")
    track = _make_track()
    other_track = Track.objects.create(
        title="Other",
        artist_fk=Artist.objects.create(name="Someone Else"),
        base_run_time_seconds=60,
    )
    timestamp = timezone.now().replace(microsecond=0)
    stop_timestamp = timestamp + timezone.timedelta(seconds=60)
    Scrobble.objects.create(
        user=user,
        track=track,
        media_type="Track",
        timestamp=timestamp,
        stop_timestamp=stop_timestamp,
    )
    Scrobble.objects.create(
        user=user,
        track=other_track,
        media_type="Track",
        timestamp=timestamp,
        stop_timestamp=stop_timestamp,
    )

    count = deduplicate_scrobbles(commit=True)

    assert count == 0
    assert Scrobble.objects.count() == 2


def test_deduplicate_scrobbles_keeps_different_timestamps(db):
    user = User.objects.create(email="time@example.com")
    track = _make_track()
    timestamp = timezone.now().replace(microsecond=0)
    stop_timestamp = timestamp + timezone.timedelta(seconds=60)
    Scrobble.objects.create(
        user=user,
        track=track,
        media_type="Track",
        timestamp=timestamp,
        stop_timestamp=stop_timestamp,
    )
    Scrobble.objects.create(
        user=user,
        track=track,
        media_type="Track",
        timestamp=timestamp + timezone.timedelta(hours=1),
        stop_timestamp=stop_timestamp + timezone.timedelta(hours=1),
    )

    count = deduplicate_scrobbles(commit=True)

    assert count == 0
    assert Scrobble.objects.count() == 2


def test_deduplicate_scrobbles_dry_run_does_not_delete(db):
    user = User.objects.create(email="dry@example.com")
    track = _make_track()
    timestamp = timezone.now().replace(microsecond=0)
    stop_timestamp = timestamp + timezone.timedelta(seconds=60)
    for _ in range(2):
        Scrobble.objects.create(
            user=user,
            track=track,
            media_type="Track",
            timestamp=timestamp,
            stop_timestamp=stop_timestamp,
        )

    count = deduplicate_scrobbles(commit=False)

    assert count == 1
    assert Scrobble.objects.filter(user=user, track=track).count() == 2


def test_deduplicate_scrobbles_filters_by_media_type(db):
    user = User.objects.create(email="filter@example.com")
    track = _make_track()
    timestamp = timezone.now().replace(microsecond=0)
    stop_timestamp = timestamp + timezone.timedelta(seconds=60)
    for _ in range(2):
        Scrobble.objects.create(
            user=user,
            track=track,
            media_type="Track",
            timestamp=timestamp,
            stop_timestamp=stop_timestamp,
        )

    count = deduplicate_scrobbles(commit=True, media_type="Video")

    assert count == 0
    assert Scrobble.objects.filter(user=user, track=track).count() == 2
