from vinetrimmer.objects.tracks import Tracks
from vinetrimmer.utils.widevine.device import LocalDevice


def _hydrate_hidden_tracks(self, title, manifest, tracks, license_url):
    """
    Hydrate hidden audio and subtitle tracks.
    Netflix does not include all download URLs for audio/subtitle tracks in the initial manifest for performance optimization.
    This method sequentially requests these hidden tracks.
    """
    from itertools import zip_longest

    # Collect unhydrated audio tracks
    unavailable_audio_tracks = []
    for audio in manifest.get("audio_tracks", []):
        if len(audio.get("streams", [])) == 0:
            # Audio is available but has no stream information
            self.log.info(f"Found hidden audio track: {audio.get('languageDescription', 'Unknown')}")
            unavailable_audio_tracks.append((
                audio.get("new_track_id"),
                audio.get("id")
            ))

    # Collect unhydrated subtitle tracks
    unavailable_subtitle_tracks = []
    for subtitle in manifest.get("timedtexttracks", []):
        if subtitle.get("isNoneTrack"):
            continue
        if subtitle.get("hydrated") == False:
            # Subtitle is not hydrated
            # self.log.info(f"Found hidden subtitle track: {subtitle.get('languageDescription', 'Unknown')}")
            unavailable_subtitle_tracks.append((
                subtitle.get("new_track_id"),
                subtitle.get("id")
            ))

    if not unavailable_audio_tracks and not unavailable_subtitle_tracks:
        self.log.info("No hidden audio or subtitle tracks found")
        return

    self.log.info(f"Fetching {len(unavailable_audio_tracks)} hidden audio track(s) and {len(unavailable_subtitle_tracks)} hidden subtitle track(s)...")

    # Hydrate hidden tracks one by one
    for audio_info, subtitle_info in zip_longest(
        unavailable_audio_tracks,
        unavailable_subtitle_tracks,
        fillvalue=(None, None)
    ):
        audio_track_id, audio_id = audio_info if audio_info[0] else (None, None)
        subtitle_track_id, subtitle_id = subtitle_info if subtitle_info[0] else (None, None)

        try:
            # Request specific hidden track
            hydrated_manifest = self.get_manifest(
                title,
                self.profiles,
                required_audio_track_id=audio_track_id,
                required_text_track_id=subtitle_track_id
            )

            # Parse hydrated tracks
            hydrated_tracks = self.manifest_as_tracks(hydrated_manifest)

            # Add audio track
            if audio_track_id:
                for audio in manifest.get("audio_tracks", []):
                    if audio.get("id") == audio_id:
                        for track in hydrated_tracks.audio:
                            if track.encrypted:
                                track.extra["license_url"] = license_url
                            tracks.add(track, warn_only=True)
                            # self.log.info(f"Added hidden audio track: {track.language}")
                        break

            # Add subtitle track
            if subtitle_track_id:
                for subtitle in manifest.get("timedtexttracks", []):
                    if subtitle.get("id") == subtitle_id:
                        for track in hydrated_tracks.subtitles:
                            tracks.add(track, warn_only=True)
                            # self.log.info(f"Added hidden subtitle track: {track.language}")
                        break
        except Exception as e:
            self.log.warning(f"Error hydrating hidden track: {e}")
            continue
        
        
def get_tracks(self, title):
    if self.vcodec == "H264":
        # If H.264, get both MPL and HPL tracks as they alternate in terms of bitrate
        tracks = Tracks()

        self.config["profiles"]["video"]["H264"]["MPL+HPL+QC"] = (
                self.config["profiles"]["video"]["H264"]["MPL"] + self.config["profiles"]["video"]["H264"]["HPL"] +
                self.config["profiles"]["video"]["H264"]["QC"]
        )

        if self.audio_only or self.subs_only or self.chapters_only:
            profiles = ["MPL+HPL+QC"]
        else:
            profiles = self.profile.split("+")

        for profile in profiles:
            try:
                manifest = self.get_manifest(title, self.config["profiles"]["video"]["H264"][profile])
            except:
                manifest = self.get_manifest(title, self.config["profiles"]["video"]["H264"]["MPL"] +
                                                self.config["profiles"]["video"]["H264"]["HPL"])
            manifest_tracks = self.manifest_as_tracks(manifest)
            license_url = manifest["links"]["license"]["href"]

            if self.cdm.device.security_level == 3 and self.cdm.device.type == LocalDevice.Types.CHROME:
                self.cdm.uuid = self.cdm.chrome_uuid
                self.cdm.urn = f"urn:uuid:{self.cdm.uuid}"
                max_quality = max(x.height for x in manifest_tracks.videos)
                # if profile == "MPL" and max_quality >= 720:
                #    manifest_sd = self.get_manifest(title, self.config["profiles"]["video"]["H264"]["BPL"])
                #    license_url_sd = manifest_sd["links"]["license"]["href"]
                #    if "SD_LADDER" in manifest_sd["video_tracks"][0]["streams"][0]["tags"]:
                #        # SD manifest is new encode encrypted with different keys that won't work for HD
                #        continue
                #    license_url = license_url_sd
                if profile == "HPL" and max_quality >= 1080:
                    if "SEGMENT_MAP_2KEY" in manifest["video_tracks"][0]["streams"][0]["tags"]:
                        # 1080p license restricted from Android L3, 720p license will work for 1080p
                        manifest_720 = self.get_manifest(
                            title, [x for x in self.config["profiles"]["video"]["H264"]["HPL"] if "l40" not in x]
                        )
                        license_url = manifest_720["links"]["license"]["href"]
                    else:
                        # Older encode, can't use 720p keys for 1080p
                        continue

            for track in manifest_tracks:
                if track.encrypted:
                    track.extra["license_url"] = license_url
                    # Fix PSSH with correct KID
                    # track.pssh.init_data = b'\x08\x01\x12\x10' + bytes.fromhex(track.kid)
            tracks.add(manifest_tracks, warn_only=True)

        # Hydrate hidden audio and subtitle tracks (using the last manifest)
        _hydrate_hidden_tracks(title, manifest, tracks, license_url)
        return tracks
    else:
        pass