"""
$description TikTok is a short-form video hosting service owned by ByteDance.
$url www.tiktok.com
$type live
$metadata id
$metadata author
$metadata title
"""

import logging
import re
from typing import Dict

from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.http import HTTPStream


log = logging.getLogger(__name__)


@pluginmatcher(
    re.compile(
        r"https?://(?:www\.)?tiktok\.com/@(?P<channel>[^/?]+)",
    ),
)
class TikTok(Plugin):
    QUALITY_WEIGHTS: Dict[str, int] = {}

    _URL_WEB_LIVE = "https://www.tiktok.com/@{channel}/live"
    _URL_API_LIVE_DETAIL = "https://www.tiktok.com/api/live/detail/?aid=1988&roomID={room_id}"
    _URL_WEBCAST_ROOM_INFO = "https://webcast.tiktok.com/webcast/room/info/?aid=1988&room_id={room_id}"

    _STATUS_OFFLINE = 4

    @classmethod
    def stream_weight(cls, key):
        weight = cls.QUALITY_WEIGHTS.get(key)
        if weight:
            return weight, key

        return super().stream_weight(key)

    def _get_streams(self):
        self.id = self.session.http.get(
            self._URL_WEB_LIVE.format(channel=self.match["channel"]),
            allow_redirects=False,
            schema=validate.Schema(
                validate.parse_html(),
                validate.xml_xpath_string(
                    ".//head/meta[@property='al:android:url'][contains(@content,'live?room_id=')]/@content",
                ),
                validate.none_or_all(
                    str,
                    re.compile(r"room_id=(\d+)"),
                    validate.get(1),
                ),
            ),
        )
        if not self.id:
            return

        live_detail = self.session.http.get(
            self._URL_API_LIVE_DETAIL.format(room_id=self.id),
            schema=validate.Schema(
                validate.parse_json(),
                {
                    "status_code": 0,
                    "LiveRoomInfo": {
                        "status": int,
                        "title": str,
                        "ownerInfo": {"nickname": str},
                    },
                },
                validate.get("LiveRoomInfo"),
                validate.union_get(
                    "status",
                    ("ownerInfo", "nickname"),
                    "title",
                ),
            ),
        )
        status, self.author, self.title = live_detail
        if status == self._STATUS_OFFLINE:
            log.info("The channel is currently offline")
            return

        streams = self.session.http.get(
            self._URL_WEBCAST_ROOM_INFO.format(room_id=self.id),
            schema=validate.Schema(
                validate.parse_json(),
                {"data": {"stream_url": {"live_core_sdk_data": {"pull_data": {"stream_data": str}}}}},
                validate.get(("data", "stream_url", "live_core_sdk_data", "pull_data", "stream_data")),
                validate.parse_json(),
                {
                    "data": {
                        str: validate.all(
                            {
                                "main": {
                                    "flv": validate.url(),
                                    "sdk_params": validate.all(
                                        validate.parse_json(),
                                        {
                                            "vbitrate": int,
                                        },
                                    ),
                                },
                            },
                            validate.union_get(
                                ("main", "flv"),
                                ("main", "sdk_params", "vbitrate"),
                            ),
                        ),
                    },
                },
                validate.get("data"),
            ),
        )
        for name, (url, vbitrate) in streams.items():
            self.QUALITY_WEIGHTS[name] = vbitrate
            yield name, HTTPStream(self.session, url)


__plugin__ = TikTok
