import os
import os.path
import sys
import urllib.parse
from dataclasses import dataclass

import requests

sys.path.append("/yt-dlp")
import yt_dlp


@dataclass
class SongInfo:
    artist: str
    title: str
    img_id: str
    tags: list[str]


def _lastfm_search(query: str) -> tuple[str, str] | None:
    response = requests.get(
        url="https://ws.audioscrobbler.com/2.0/?method=track.search&format=json",
        params={"limit": 5, "track": query, "api_key": os.environ["LASTFM_API_KEY"]},
    )

    assert response.status_code == 200

    tracks = response.json()["results"]["trackmatches"]["track"]
    if len(tracks) == 0:
        return None
    track_info = tracks[0]

    return track_info["name"], track_info["artist"]


def _lastfm_getinfo(name: str, artist: str) -> tuple[str, list[str]]:  # ( image_id, tags )
    response = requests.get(
        url="https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json",
        params={
            "track": name,
            "artist": artist,
            "api_key": os.environ["LASTFM_API_KEY"],
        },
    )

    track_info = response.json()["track"]

    image_id = ""
    if "album" in track_info:
        image_url = urllib.parse.urlparse(track_info["album"]["image"][0]["#text"])
        image_id = os.path.splitext(os.path.basename(image_url.path))[0]
    else:
        print("this song haas no image", flush=True)

    return (
        # track_info["mbid"],
        image_id,
        [t["name"] for t in track_info["toptags"]["tag"]],
    )


def _yt_search(query: str) -> tuple[str, str]:
    ydl_opts = {
        "format": "bestaudio",
        "default_search": "ytsearch1",
        "outtmpl": "%(title)s.%(ext)s",
        "skip_download": True,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(query, download=False)

    first = info["entries"][0]

    return first["track"], first["artists"][0]


def query_search(query: str) -> SongInfo | None:
    res = _lastfm_search(query)
    if res is None:
        return None

    name, artist = res
    img_id, tags = _lastfm_getinfo(name, artist)

    return SongInfo(artist=artist, title=name, img_id=img_id, tags=tags)


def yt_search_song(name: str, artist: str) -> str | None:  # video id
    ydl_opts = {
        "format": "bestaudio",
        "default_search": "ytsearch1",
        "outtmpl": "%(title)s.%(ext)s",
        "skip_download": True,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(f"{name!r} - {artist!r}", download=False)

    if len(info["entries"]) == 0:
        return None

    return info["entries"][0]["id"]


def yt_get_audio_url(video_id) -> str | None:  # audio url
    ydl_opts = {
        "format": "bestaudio",
        "default_search": "ytsearch1",
        "outtmpl": "%(title)s.%(ext)s",
        "skip_download": True,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        info = ydl.extract_info(video_id, download=False)

    if "entries" not in info:
        return info["url"]

    first_entry = info["entries"][0]

    for fmt in first_entry["formats"]:
        if "acodec" in fmt and fmt["acodec"] != "none":
            return fmt["url"]

    return None
