from .common import InfoExtractor
from ..utils import ExtractorError, str_or_none, traverse_obj, unified_strdate


class IchinanaLiveIE(InfoExtractor):
    IE_NAME = '17live'
    _VALID_URL = r'https?://(?:www\.)?17\.live/(?:[^/]+/)*(?:live|profile/r)/(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://17.live/live/3773096',
        'info_dict': {
            'id': '3773096',
            'title': '萠珈☕🤡🍫moka',
            'is_live': True,
            'uploader': '萠珈☕🤡🍫moka',
            'uploader_id': '3773096',
            'like_count': 366,
            'view_count': 18121,
            'timestamp': 1630569012,
        },
        'skip': 'running as of writing, but may be ended as of testing',
    }, {
        'note': 'nothing except language differs',
        'url': 'https://17.live/ja/live/3773096',
        'only_matching': True,
    }]

    @classmethod
    def suitable(cls, url):
        return not IchinanaLiveClipIE.suitable(url) and super().suitable(url)

    def _real_extract(self, url):
        video_id = self._match_id(url)
        url = f'https://17.live/live/{video_id}'

        enter = self._download_json(
            f'https://api-dsa.17app.co/api/v1/lives/{video_id}/enter', video_id,
            headers={'Referer': url}, fatal=False, expected_status=420,
            data=b'\0')
        if enter and enter.get('message') == 'ended':
            raise ExtractorError('This live has ended.', expected=True)

        view_data = self._download_json(
            f'https://api-dsa.17app.co/api/v1/lives/{video_id}', video_id,
            headers={'Referer': url})

        uploader = traverse_obj(
            view_data, ('userInfo', 'displayName'), ('userInfo', 'openID'))

        video_urls = view_data.get('rtmpUrls')
        if not video_urls:
            raise ExtractorError('unable to extract live URL information')
        formats = []
        for (name, value) in video_urls[0].items():
            if not isinstance(value, str):
                continue
            if not value.startswith('http'):
                continue
            quality = -1
            if 'web' in name:
                quality -= 1
            if 'High' in name:
                quality += 4
            if 'Low' in name:
                quality -= 2
            formats.append({
                'format_id': name,
                'url': value,
                'quality': quality,
                'http_headers': {'Referer': url},
                'ext': 'flv',
                'vcodec': 'h264',
                'acodec': 'aac',
            })

        return {
            'id': video_id,
            'title': uploader or video_id,
            'formats': formats,
            'is_live': True,
            'uploader': uploader,
            'uploader_id': video_id,
            'like_count': view_data.get('receivedLikeCount'),
            'view_count': view_data.get('viewerCount'),
            'thumbnail': view_data.get('coverPhoto'),
            'description': view_data.get('caption'),
            'timestamp': view_data.get('beginTime'),
        }


class IchinanaLiveClipIE(InfoExtractor):
    IE_NAME = '17live:clip'
    _VALID_URL = r'https?://(?:www\.)?17\.live/(?:[^/]+/)*profile/r/(?P<uploader_id>\d+)/clip/(?P<id>[^/]+)'
    _TESTS = [{
        'url': 'https://17.live/profile/r/1789280/clip/1bHQSK8KUieruFXaCH4A4upCzlN',
        'info_dict': {
            'id': '1bHQSK8KUieruFXaCH4A4upCzlN',
            'title': 'マチコ先生🦋Class💋',
            'description': 'マチ戦隊　第一次　バスターコール\n総額200万coin！\n動画制作@うぉーかー🌱Walker🎫',
            'uploader_id': '1789280',
        },
    }, {
        'url': 'https://17.live/ja/profile/r/1789280/clip/1bHQSK8KUieruFXaCH4A4upCzlN',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        uploader_id, video_id = self._match_valid_url(url).groups()
        url = f'https://17.live/profile/r/{uploader_id}/clip/{video_id}'

        view_data = self._download_json(
            f'https://api-dsa.17app.co/api/v1/clips/{video_id}', video_id,
            headers={'Referer': url})

        uploader = traverse_obj(
            view_data, ('userInfo', 'displayName'), ('userInfo', 'name'))

        formats = []
        if view_data.get('videoURL'):
            formats.append({
                'id': 'video',
                'url': view_data['videoURL'],
                'quality': -1,
            })
        if view_data.get('transcodeURL'):
            formats.append({
                'id': 'transcode',
                'url': view_data['transcodeURL'],
                'quality': -1,
            })
        if view_data.get('srcVideoURL'):
            # highest quality
            formats.append({
                'id': 'srcVideo',
                'url': view_data['srcVideoURL'],
                'quality': 1,
            })

        for fmt in formats:
            fmt.update({
                'ext': 'mp4',
                'protocol': 'https',
                'vcodec': 'h264',
                'acodec': 'aac',
                'http_headers': {'Referer': url},
            })

        return {
            'id': video_id,
            'title': uploader or video_id,
            'formats': formats,
            'uploader': uploader,
            'uploader_id': uploader_id,
            'like_count': view_data.get('likeCount'),
            'view_count': view_data.get('viewCount'),
            'thumbnail': view_data.get('imageURL'),
            'duration': view_data.get('duration'),
            'description': view_data.get('caption'),
            'upload_date': unified_strdate(str_or_none(view_data.get('createdAt'))),
        }
