import csv
import json
import logging
from typing import TYPE_CHECKING, Optional

import requests
from bs4 import BeautifulSoup
from django.contrib.auth import get_user_model
from django.conf import settings

User = get_user_model()
if TYPE_CHECKING:
    from scrobbles.models import Scrobble

logger = logging.getLogger(__name__)

SEARCH_ID_URL = (
    "https://boardgamegeek.com/xmlapi/search?search={query}&exact=1"
)
GAME_ID_URL = "https://boardgamegeek.com/xmlapi/boardgame/{id}"
BGG_ACCESS_TOKEN = getattr(settings, "BGG_ACCESS_TOKEN", "")
BASE_HEADERS = {"User-Agent": "Vrobbler 31.0", "Authorization": f"Bearer {BGG_ACCESS_TOKEN}"}


def take_first(thing: Optional[list]) -> str:
    first = ""
    try:
        first = thing[0]
    except IndexError:
        pass

    if first:
        try:
            first = first.get_text()
        except:
            pass

    return first


def lookup_boardgame_id_from_bgg(title: str) -> Optional[int]:
    soup = None
    game_id = None
    url = SEARCH_ID_URL.format(query=title)
    r = requests.get(url, headers=BASE_HEADERS)
    if r.status_code == 200:
        soup = BeautifulSoup(r.text, "xml")

    if soup:
        result = soup.findAll("boardgame")
        if not result:
            return game_id

        game_id = result[0].get("objectid", None)

    return game_id


def lookup_boardgame_from_bgg(lookup_id: str) -> dict:
    soup = None
    game_dict = {}

    title = ""
    bgg_id = None

    try:
        bgg_id = int(lookup_id)
        logger.debug(f"Using BGG ID {bgg_id} to find board game")
    except ValueError:
        title = lookup_id
        logger.debug(f"Using title {title} to find board game")

    if not bgg_id:
        bgg_id = lookup_boardgame_id_from_bgg(title)

    url = GAME_ID_URL.format(id=bgg_id)
    r = requests.get(url, headers=BASE_HEADERS)
    if r.status_code == 200:
        soup = BeautifulSoup(r.text, "xml")

    if soup:
        seconds_to_play = None
        minutes = take_first(soup.findAll("playingtime"))
        if minutes:
            seconds_to_play = int(minutes) * 60

        game_dict = {
            "bggeek_id": bgg_id,
            "title": take_first(soup.findAll("name", primary="true")),
            "description": take_first(soup.findAll("description")),
            "year_published": take_first(soup.findAll("yearpublished")),
            "publisher_name": take_first(soup.findAll("boardgamepublisher")),
            "cover_url": take_first(soup.findAll("image")),
            "min_players": take_first(soup.findAll("minplayers")),
            "max_players": take_first(soup.findAll("maxplayers")),
            "recommended_age": take_first(soup.findAll("age")),
            "run_time_seconds": seconds_to_play,
        }

    return game_dict


def push_scrobble_to_bgg(scrobble: "Scrobble", user: User) -> Optional[bool]:
    bgg_username = "secstate"  # user.profile.bgg_username
    bgg_password = "yYFCKnfo8AK89lc68q0S"

    if not bgg_username or bgg_password:
        return

    login_payload = {
        "credentials": {"username": bgg_username, "password": bgg_password}
    }
    headers = BASE_HEADERS
    headers["content-type"] = "application/json"

    # TODO Look up past plays for scrobble.media_obj.bggeek_id, and make sure we haven't scrobbled this before

    with requests.Session() as s:
        p = s.post(
            "https://boardgamegeek.com/login/api/v1",
            data=json.dumps(login_payload),
            headers=headers,
        )
        players = []
        if scrobble.log:
            for player in scrobble.log.get("players"):
                player_person = Person.objects.filter(
                    id=player.get("person_id")
                ).first()
                if player_person.get("bgg_username"):
                    player["username"] = player_person.get("bgg_username")
                player["name"] = player_person.get("name")
                player["win"] = player.get("win")
                # player["role"] = player.get("role")
                player["new"] = player.get("new")
                player["score"] = player.get("score")
                players.append(player)

        play_payload = {
            "playdate": scrobble.timestamp.date.strftime("%Y-%m-%d"),
            "length": scrobble.playback_position_seconds / 60,
            "comments": "Uploaded from Vrobbler",
            "location": scrobble.log.location or None,
            "objectid": scrobble.media_obj.bggeek_id,
            "quantity": "1",
            "action": "save",
            "players": players,
            "objecttype": "thing",
            "ajax": 1,
        }
        r = s.post(
            "https://boardgamegeek.com/geekplay.php",
            data=json.dumps(play_payload),
            headers=headers,
        )
