"""
$description America-based television network centred towards business and capital market programming.
$url bloomberg.com
$type live, vod
$metadata title
"""

import re

from streamlink.logger import getLogger
from streamlink.plugin import Plugin, PluginError, pluginmatcher
from streamlink.plugin.api import useragents, validate
from streamlink.stream.hls import HLSStream


log = getLogger(__name__)


@pluginmatcher(
    name="live",
    pattern=re.compile(r"https?://(?:www\.)?bloomberg\.com/live(?:/(?P<channel>[^/]+))?"),
)
@pluginmatcher(
    name="vod",
    pattern=re.compile(r"https?://(?:www\.)?bloomberg\.com/news/videos/[^/]+/[^/]+"),
)
class Bloomberg(Plugin):
    LIVE_API_URL = "https://cdn.gotraffic.net/projector/latest/assets/config/config.min.json?v=1"
    VOD_API_URL = "https://www.bloomberg.com/api/embed?id={0}"
    DEFAULT_CHANNEL = "us"

    def _get_live_streams(self, data, channel):
        schema_live_ids = validate.Schema(
            {
                "live": {
                    "channels": {
                        "byChannelId": {
                            channel: validate.all(
                                {"liveId": str},
                                validate.get("liveId"),
                            ),
                        },
                    },
                },
            },
            validate.get(("live", "channels", "byChannelId", channel)),
        )
        try:
            live_id = schema_live_ids.validate(data)
        except PluginError:
            log.error(f"Could not find liveId for channel '{channel}'")
            return

        log.debug(f"Found liveId: {live_id}")
        return self.session.http.get(
            self.LIVE_API_URL,
            schema=validate.Schema(
                validate.parse_json(),
                {
                    "livestreams": {
                        live_id: {
                            validate.optional("cdns"): validate.all(
                                [
                                    {
                                        "streams": [
                                            {
                                                "url": validate.url(),
                                            },
                                        ],
                                    },
                                ],
                                validate.transform(lambda x: [urls["url"] for y in x for urls in y["streams"]]),
                            ),
                        },
                    },
                },
                validate.get(("livestreams", live_id, "cdns")),
            ),
        )

    def _get_vod_streams(self, data):
        schema_vod_list = validate.Schema(
            validate.any(
                validate.all(
                    {"video": {"videoStory": dict}},
                    validate.get(("video", "videoStory")),
                ),
                validate.all(
                    {"quicktakeVideo": {"videoStory": dict}},
                    validate.get(("quicktakeVideo", "videoStory")),
                ),
            ),
            {
                "video": {
                    "bmmrId": str,
                },
            },
            validate.get(("video", "bmmrId")),
        )
        schema_url = validate.all(
            {"url": validate.url()},
            validate.get("url"),
        )

        try:
            video_id = schema_vod_list.validate(data)
        except PluginError:
            log.error("Could not find videoId")
            return

        log.debug(f"Found videoId: {video_id}")
        vod_url = self.VOD_API_URL.format(video_id)
        secureStreams, streams, self.title = self.session.http.get(
            vod_url,
            schema=validate.Schema(
                validate.parse_json(),
                {
                    validate.optional("secureStreams"): [schema_url],
                    validate.optional("streams"): [schema_url],
                    "title": str,
                },
                validate.union_get("secureStreams", "streams", "title"),
            ),
        )

        return secureStreams or streams

    def _get_streams(self):
        self.session.http.headers.clear()
        self.session.http.headers["User-Agent"] = useragents.CHROME

        data = self.session.http.get(
            self.url,
            schema=validate.Schema(
                validate.parse_html(),
                validate.xml_xpath_string(".//script[contains(text(),'window.__PRELOADED_STATE__')][1]/text()"),
                validate.none_or_all(
                    re.compile(r"\bwindow\.__PRELOADED_STATE__\s*=\s*(?P<json>{.+?})\s*;(?:\s|$)"),
                    validate.none_or_all(
                        validate.get("json"),
                        validate.parse_json(),
                    ),
                ),
            ),
        )
        if not data:
            log.error("Could not find JSON data. Invalid URL or bot protection...")
            return

        if self.matches["live"]:
            streams = self._get_live_streams(data, self.match["channel"] or self.DEFAULT_CHANNEL)
        else:
            streams = self._get_vod_streams(data)

        if streams:
            # just return the first stream
            return HLSStream.parse_variant_playlist(self.session, streams[0])


__plugin__ = Bloomberg
