from __future__ import annotations

from urllib.parse import urljoin

from .client import GggClient
from .decoder import super_decode
from .models import ResolvedTrack, Track
from .parser import extract_album, extract_legacy_aplayer_track, extract_lyrics, extract_music_tags


def resolve_thread_url(thread_url: str) -> ResolvedTrack:
    with GggClient() as client:
        html = client.fetch_text(thread_url)
        return resolve_thread(html, thread_url, client=client)


def resolve_thread(source: str | GggClient, thread: str | Track, client: GggClient | None = None) -> ResolvedTrack:
    if isinstance(source, GggClient):
        active_client = source
        thread_url = thread.url if isinstance(thread, Track) else str(thread)
        html = active_client.fetch_text(thread_url)
        return resolve_thread(html, thread_url, client=active_client)

    html = source
    thread_url = thread.url if isinstance(thread, Track) else str(thread)
    active_client = client or GggClient()
    close_client = client is None
    try:
        try:
            music_tags = extract_music_tags(html)
        except ValueError as exc:
            if str(exc) != "musicTags not found":
                raise
            return extract_legacy_aplayer_track(html, thread_url)
        parse_url = urljoin(thread_url, "/plugin/clih_music/api/parse_music.php")
        payload = active_client.post_json(parse_url, music_tags, referer=thread_url)
        if not isinstance(payload, dict) or payload.get("code") != 0:
            raise ValueError(str(payload.get("msg") if isinstance(payload, dict) else "music parse failed"))
        data = payload.get("data") or []
        if not data:
            raise ValueError("parse_music returned no tracks")
        item = data[0]
        return ResolvedTrack(
            title=str(item.get("title") or ""),
            artist=str(item.get("author") or ""),
            url=super_decode(str(item.get("url") or "")),
            cover=super_decode(str(item.get("pic") or "")) if item.get("pic") else None,
            album=extract_album(html),
            lyrics=extract_lyrics(html),
        )
    finally:
        if close_client:
            active_client.close()