from django.http import (
    HttpResponse,
    HttpResponseNotAllowed,
    HttpResponseServerError,
    JsonResponse,
)
from django.shortcuts import redirect, render

from gamechanger.models import Player as GamechangerPlayer
from teamsnap.views import get_teamsnap_client


def teamsnap_event_redirect(request, event_id, team_id):
    return redirect(f"https://go.teamsnap.com/{team_id}/schedule/view_game/{event_id}")


def edit_lineup(request, event_ids, team_id):
    import re

    from pyteamsnap.objects import (
        Availability,
        AvailabilitySummary,
        Event,
        EventLineup,
        EventLineupEntry,
        Member,
    )
    from teamsnap.forms import LineupEntryFormset

    client = get_teamsnap_client(request)

    event_ids = str(event_ids).split(",")

    ts_bulkload = client.bulk_load(
        team_id=team_id,
        types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
        event__id=",".join(event_ids),
    )
    event_ids = [int(i) for i in event_ids]

    contexts = []
    for event_id in event_ids:
        ts_event = [
            i for i in ts_bulkload if isinstance(i, Event) and i.data["id"] == event_id
        ][0]
        ts_availabilities = Availability.search(client, event_id=ts_event.data["id"])
        ts_lineup_entries = EventLineupEntry.search(client, event_id=event_id)
        ts_availability_summary = [
            i
            for i in ts_bulkload
            if isinstance(i, AvailabilitySummary) and i.data["event_id"] == event_id
        ][0]
        ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
        ts_member_lookup = {m.data["id"]: m for m in ts_members}
        gc_player_lookup = {
            m.data["id"]: getattr(
                GamechangerPlayer.objects.filter(
                    teamsnap_member_id=m.data["id"]
                ).first(),
                "id",
                None,
            )
            for m in ts_members
        }
        ts_availability_lookup = {m.data["member_id"]: m for m in ts_availabilities}
        ts_lineup_entries_lookup = {m.data["member_id"]: m for m in ts_lineup_entries}

        members = []

        for lineup_entry in ts_lineup_entries:
            members.append(
                {
                    "member": getattr(
                        ts_member_lookup[lineup_entry.data["member_id"]], "data"
                    ),
                    "availability": getattr(
                        ts_availability_lookup.get(lineup_entry.data["member_id"], {}),
                        "data",
                        {},
                    ),
                    "lineup_entry": getattr(lineup_entry, "data", {}),
                }
            )

        in_lineup_already = [m["member"] for m in members]

        for member in ts_members:
            if member.data not in in_lineup_already:
                members.append(
                    {
                        "member": getattr(member, "data"),
                        "availability": getattr(
                            ts_availability_lookup.get(member.data["id"], {}),
                            "data",
                            {},
                        ),
                        "lineup_entry": getattr(
                            ts_lineup_entries_lookup.get(member.data["id"], {}),
                            "data",
                            {},
                        ),
                    }
                )

        members = sorted(
            members,
            key=lambda d: (
                {None: 3, 0: 2, 2: 1, 1: 0}.get(  # No Response  # No  # Maybe  # Yes
                    d["availability"].get("status_code")
                ),
                d["member"].get("last_name"),
            ),
        )

        initial = []
        for member in members:
            if not member["member"]["is_non_player"]:
                if re.search(
                    r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
                    member["lineup_entry"].get("label", ""),
                ):
                    position, position_note = re.search(
                        r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
                        member["lineup_entry"].get("label", ""),
                    ).groups()
                else:
                    position, position_note = ("", "")
                position_only = position_note == "PO"
                initial.append(
                    {
                        "event_lineup_entry_id": member["lineup_entry"].get("id"),
                        "event_lineup_id": member["lineup_entry"].get(
                            "event_lineup_id"
                        ),
                        "event_id": event_id,
                        "position_only": position_only,
                        "member_id": member["member"]["id"],
                        "sequence": member["lineup_entry"].get("sequence"),
                        "label": position,
                        "gamechanger_player_id": gc_player_lookup.get(
                            member["member"]["id"]
                        ),
                    }
                )

        formset = LineupEntryFormset(initial=initial)

        for form in formset:
            form.member = ts_member_lookup.get(form["member_id"].initial)
            form.availability = ts_availability_lookup.get(form["member_id"].initial)

        formset_startinglineup = [
            form
            for form in formset
            if form.initial.get("event_lineup_entry_id")
            and not form.initial.get("position_only")
        ]
        formset_startinglineup = sorted(
            formset_startinglineup, key=lambda d: d.initial.get("sequence", 100)
        )
        formset_startingpositiononly = [
            form
            for form in formset
            if form.initial.get("event_lineup_entry_id")
            and form not in formset_startinglineup
        ]
        formset_startingpositiononly = sorted(
            formset_startingpositiononly, key=lambda d: d.initial.get("sequence", 100)
        )
        formset_bench = [
            form
            for form in formset
            if form not in formset_startinglineup
            and form not in formset_startingpositiononly
            and form.availability.data["status_code"] in [2, 1]
        ]
        formset_out = [
            form
            for form in formset
            if form not in formset_startinglineup
            and form not in formset_bench
            and form not in formset_startingpositiononly
            and not form.member.data["is_non_player"]
        ]

        contexts.append(
            {
                "event": ts_event,
                "availability_summary": ts_availability_summary,
                "formset": formset,
                "formset_bench": formset_bench,
                "formset_startinglineup": formset_startinglineup,
                "formset_startingpositionalonly": formset_startingpositiononly,
                "formset_out": formset_out,
            }
        )

    return render(request, "lineup/edit.html", context={"contexts": contexts})


def submit_lineup(request, team_id, event_id):
    from pyteamsnap.objects import Event, EventLineup, EventLineupEntry
    from teamsnap.forms import LineupEntryFormset

    client = get_teamsnap_client(request)
    ts_event = Event.get(client, event_id)
    ts_lineup = EventLineup.search(client, event_id=event_id)
    event_lineup_id = ts_lineup[0].data["id"]
    if request.GET:
        return HttpResponseNotAllowed()
    if request.POST:
        formset = LineupEntryFormset(request.POST)
        if formset.is_valid():
            r = []
            for form in formset:
                data = form.cleaned_data
                if data.get("event_lineup_entry_id"):
                    event_lineup_entry = EventLineupEntry.get(
                        client, id=data.get("event_lineup_entry_id")
                    )
                    if data.get("position_only"):
                        data["label"] = data["label"] + " [PO]"
                    event_lineup_entry.data.update(data)
                    if not data.get("sequence") and not data.get("label"):
                        try:
                            r.append(event_lineup_entry.delete())
                        except Exception as e:
                            raise e
                    else:
                        try:
                            r.append(event_lineup_entry.put())
                        except Exception as e:
                            e
                            pass
                    pass
                elif data.get("sequence") is not None and data.get("label"):
                    event_lineup_entry = EventLineupEntry.new(client)
                    if data.get("position_only"):
                        data["label"] = data["label"] + " [PO]"
                    event_lineup_entry.data.update(data)
                    event_lineup_entry.data.update({"event_lineup_id": event_lineup_id})
                    try:
                        r.append(event_lineup_entry.post())
                    except Exception as e:
                        raise e
                else:
                    pass
        else:
            pass
        return JsonResponse(ts_event.data)
    return HttpResponseServerError


def multi_lineup_choose(request, team_id=None):
    if not team_id:
        return redirect(
            "teamsnap_choose_multiple_lineups",
            team_id=request.user.teamsnap_preferences.managed_team_id,
        )
    from django.forms import formset_factory

    from pyteamsnap.objects import Event

    from .forms import EventChooseForm

    client = get_teamsnap_client(request)

    if request.method == "POST":
        ts_events = Event.search(client, team_id=team_id)
        EventChooseFormset = formset_factory(EventChooseForm)
        formset = EventChooseFormset(request.POST)
        choices = [(e.data["id"], e.data["formatted_title"]) for e in ts_events]

        for form in formset:
            form.fields["event_id"].choices = choices

        if formset.is_valid():
            event_ids = [f.cleaned_data["event_id"] for f in formset]
        else:
            event_ids = request.GET.get("event_ids").split(",")
        EventChooseFormset = formset_factory(EventChooseForm)
        formset = EventChooseFormset(request.POST)

        return redirect(
            "teamsnap_edit_lineup",
            team_id=team_id,
            event_ids=",".join(event_ids),
        )
    elif not request.GET.get("num"):
        return HttpResponse(500)
    else:
        num = int(request.GET.get("num"))
    TEAM_ID = team_id

    ts_events = Event.search(client, team_id=TEAM_ID)
    ts_events = {e.data["id"]: e for e in ts_events}

    EventChooseFormset = formset_factory(EventChooseForm, extra=num)
    formset = EventChooseFormset()

    choices = [(id, e.data["formatted_title"]) for id, e in ts_events.items()]

    for form in formset:
        form.fields["event_id"].choices = choices

    pass
    return render(
        request,
        "lineup/multiple_choose.html",
        context={"formset": formset, "team_id": team_id},
    )
