import json

from django.db import migrations, models
import django.db.models.deletion


def canonical_key(event):
    if event.home_team_id and event.away_team_id:
        return ("teams", event.league_id, event.home_team_id, event.away_team_id)
    if event.player_one_id and event.player_two_id:
        return ("players", event.league_id, event.player_one_id, event.player_two_id)
    return ("title", event.league_id, event.event_type, (event.title or "").strip())


def build_logdata(event):
    logdata = {}
    if event.thesportsdb_id:
        logdata["thesportsdb_id"] = event.thesportsdb_id
    if event.start:
        logdata["start"] = (
            event.start.isoformat()
            if hasattr(event.start, "isoformat")
            else str(event.start)
        )
    if event.round:
        logdata["round_name"] = event.round.name or str(event.round)
        if event.round.season:
            logdata["season_name"] = event.round.season.name or str(event.round.season)
    return logdata


def merge_scrobble_logs(scrobble, logdata):
    existing_log = scrobble.log or {}
    if isinstance(existing_log, str):
        existing_log = json.loads(existing_log)
    existing_log.update(logdata)
    scrobble.log = existing_log
    scrobble.save(update_fields=["log"])


def populate_league(event):
    if event.league:
        return
    if event.round and event.round.season and event.round.season.league:
        event.league = event.round.season.league
        event.save(update_fields=["league"])


def populate_m2m(event):
    if event.home_team_id:
        event.teams.add(event.home_team_id)
    if event.away_team_id:
        event.teams.add(event.away_team_id)
    if event.player_one_id:
        event.players.add(event.player_one_id)
    if event.player_two_id:
        event.players.add(event.player_two_id)


def migrate_sport_event_data(apps, schema_editor):
    SportEvent = apps.get_model("sports", "SportEvent")
    Scrobble = apps.get_model("scrobbles", "Scrobble")
    db_alias = schema_editor.connection.alias

    canonical_events = {}

    for event in SportEvent.objects.using(db_alias).iterator():
        populate_league(event)
        key = canonical_key(event)

        canonical = canonical_events.get(key)
        if not canonical:
            canonical_events[key] = event
            populate_m2m(event)
            logdata = build_logdata(event)
            for scrobble in (
                Scrobble.objects.using(db_alias).filter(sport_event=event).iterator()
            ):
                merge_scrobble_logs(scrobble, logdata)
        else:
            logdata = build_logdata(event)
            for scrobble in (
                Scrobble.objects.using(db_alias).filter(sport_event=event).iterator()
            ):
                scrobble.sport_event = canonical
                merge_scrobble_logs(scrobble, logdata)
                scrobble.save(update_fields=["sport_event", "log"])
            event.delete()


class Migration(migrations.Migration):

    dependencies = [
        ("sports", "0019_sportevent_league_alter_sportevent_away_team_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="sportevent",
            name="teams",
            field=models.ManyToManyField(blank=True, to="sports.team"),
        ),
        migrations.AddField(
            model_name="sportevent",
            name="players",
            field=models.ManyToManyField(blank=True, to="sports.player"),
        ),
        migrations.RunPython(
            migrate_sport_event_data, reverse_code=migrations.RunPython.noop
        ),
    ]
