"""
$description Live TV channels and video on-demand service from ZDF, a German public, independent broadcaster.
$url zdf.de
$type live, vod
$region Germany
"""

import logging
import re
from urllib.parse import urlparse, urlunparse

from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
from streamlink.utils.url import url_concat

log = logging.getLogger(__name__)


@pluginmatcher(re.compile(
    r"https?://(\w+\.)?(zdf\.de|3sat\.de)/"
))
class ZDFMediathek(Plugin):
    PLAYER_ID = "ngplayer_2_4"

    def _get_streams(self):
        zdf_json = self.session.http.get(self.url, schema=validate.Schema(
            validate.parse_html(),
            validate.xml_xpath_string(".//*[@data-zdfplayer-jsb][1]/@data-zdfplayer-jsb"),
            validate.none_or_all(
                validate.parse_json(),
                {
                    "apiToken": str,
                    "content": validate.url(),
                },
                validate.union_get("apiToken", "content"),
            ),
        ))
        if zdf_json is None:
            return

        apiToken, apiUrl = zdf_json

        headers = {
            "Accept": "application/vnd.de.zdf.v1.0+json;charset=UTF-8",
            "Api-Auth": f"Bearer {apiToken}",
            "Referer": self.url
        }

        pApiUrl = urlparse(apiUrl)
        apiUrlBase = urlunparse((pApiUrl.scheme, pApiUrl.netloc, "", "", "", ""))
        apiUrlPath = self.session.http.get(apiUrl, headers=headers, schema=validate.Schema(
            validate.parse_json(),
            {"mainVideoContent": {
                "http://zdf.de/rels/target": {
                    "http://zdf.de/rels/streams/ptmd-template": str
                }
            }},
            validate.get(("mainVideoContent", "http://zdf.de/rels/target", "http://zdf.de/rels/streams/ptmd-template")),
            validate.transform(lambda template: template.format(playerId=self.PLAYER_ID).replace(" ", ""))
        ))

        stream_request_url = url_concat(apiUrlBase, apiUrlPath)
        data = self.session.http.get(stream_request_url, headers=headers, schema=validate.Schema(
            validate.parse_json(),
            {"priorityList": [{
                "formitaeten": validate.all(
                    [{
                        "type": str,
                        "qualities": validate.all(
                            [{
                                "quality": str,
                                "audio": {
                                    "tracks": [{
                                        "uri": validate.url()
                                    }]
                                }
                            }],
                            validate.filter(lambda obj: obj["quality"] == "auto")
                        )
                    }],
                    validate.filter(lambda obj: obj["type"] == "h264_aac_ts_http_m3u8_http")
                )
            }]},
            validate.get("priorityList")
        ))

        for priority in data:
            for formitaeten in priority["formitaeten"]:
                for quality in formitaeten["qualities"]:
                    for audio in quality["audio"]["tracks"]:
                        yield from HLSStream.parse_variant_playlist(self.session, audio["uri"], headers=headers).items()


__plugin__ = ZDFMediathek
