from __future__ import annotations

__version__ = '0.8.1'

import abc
import json

from yt_dlp.extractor.youtube.pot.provider import (
    ExternalRequestFeature,
    PoTokenContext,
    PoTokenProvider,
    PoTokenProviderRejectedRequest,
)
from yt_dlp.extractor.youtube.pot.utils import WEBPO_CLIENTS
from yt_dlp.utils import js_to_json
from yt_dlp.utils.traversal import traverse_obj


class BgUtilPTPBase(PoTokenProvider, abc.ABC):
    PROVIDER_VERSION = __version__
    BUG_REPORT_LOCATION = (
        'https://github.com/jim60105/bgutil-ytdlp-pot-provider/issues'
    )
    _SUPPORTED_EXTERNAL_REQUEST_FEATURES = (
        ExternalRequestFeature.PROXY_SCHEME_HTTP,
        ExternalRequestFeature.PROXY_SCHEME_HTTPS,
        ExternalRequestFeature.PROXY_SCHEME_SOCKS4,
        ExternalRequestFeature.PROXY_SCHEME_SOCKS4A,
        ExternalRequestFeature.PROXY_SCHEME_SOCKS5,
        ExternalRequestFeature.PROXY_SCHEME_SOCKS5H,
        ExternalRequestFeature.SOURCE_ADDRESS,
        ExternalRequestFeature.DISABLE_TLS_VERIFICATION,
    )
    _SUPPORTED_CLIENTS = WEBPO_CLIENTS
    _SUPPORTED_CONTEXTS = (
        PoTokenContext.GVS,
        PoTokenContext.PLAYER,
        PoTokenContext.SUBS,
    )
    _GETPOT_TIMEOUT = 20.0
    _GET_SERVER_VSN_TIMEOUT = 5.0
    _MIN_NODE_VSN = (18, 0, 0)

    def _info_and_raise(self, msg, raise_from=None):
        self.logger.info(msg)
        raise PoTokenProviderRejectedRequest(msg) from raise_from

    def _warn_and_raise(self, msg, once=True, raise_from=None):
        self.logger.warning(msg, once=once)
        raise PoTokenProviderRejectedRequest(msg) from raise_from

    def _get_attestation(self, webpage: str | None):
        if not webpage:
            return None
        raw_cd = (
            traverse_obj(
                self.ie._search_regex(
                    r'''(?sx)window\s*\.\s*ytAtN\s*\(\s*
                        (?P<js>\{.+?}\s*)
                    \s*\)\s*;''',
                    webpage,
                    'ytAtN challenge',
                    default=None),
                ({js_to_json}, {json.loads}, 'R'))
            or traverse_obj(
                self.ie._search_regex(
                    r'''(?sx)window\.ytAtR\s*=\s*(?P<raw_cd>(?P<q>['"])
                        (?:
                            \\.|
                            (?!(?P=q)).
                        )*
                    (?P=q))\s*;''',
                    webpage,
                    'ytAtR challenge',
                    default=None),
                ({js_to_json}, {json.loads})))
        if att_txt := traverse_obj(raw_cd, ({json.loads}, 'bgChallenge')):
            return att_txt
        self.logger.warning('Failed to extract initial attestation from the webpage')
        return None


__all__ = ['__version__']
