# -*- coding: utf-8 -*-
import re
import xbmc

class StreamCurator:
    """
    Handles stream curation, ranking, and feature extraction for series episodes.
    """

    def __init__(self, addon=None):
        self.addon = addon

    def curate_streams(
        self,
        candidates,
        skip_high_quality: bool = False,
        force_hd_only: bool = False,
        name_only: bool = False,
        only_uhd: bool = False,
        max_per_episode: int = 50
    ):
        """
        FULL-PASS kurátor + enrichment z cache + prioritní řazení feature značek:
        1) CZdab (česká audio stopa) – kompat: CZ / CZaudio
        2) CZtit (české titulky) – kompat: CZsub
        3) Audio kvalita: Atmos > 7.1 > 5.1 > 2.0
        4) Rozlišení: 2160p > 1440p > 1080p > 720p > SD
        5) Obraz: DV > HDR10 > HDR
        6) Kodeky: HEVC > H.264
        7) Ostatní (v původním pořadí)
        """
        try:
            from resources.lib.series.subcaps_cache import (
                has_cz_subs, has_cz_audio, audio_badges, video_badges, is_probed,
            )
        except Exception:
            has_cz_subs = lambda x: False
            has_cz_audio = lambda x: False
            audio_badges = lambda x: []
            video_badges = lambda x: []
            is_probed = lambda x: False

        normalized = []

        # --- pomocná: unikátní list se zachováním prvního výskytu ---
        def _uniq_keep_order(items):
            out, seen = [], set()
            for it in items or []:
                key = str(it)
                if key in seen:
                    continue
                seen.add(key)
                out.append(it)
            return out

        # --- pomocná: prioritní řazení features ---
        def _rank_feature(tok: str, orig_index: int):
            """
            Vrací tuple (group, order_in_group, orig_index) — menší = výše.
            """
            t = (tok or "").strip()
            tl = t.lower()
            tu = t.upper()

            # 1) CZdab (česká audio stopa) – kompat tokeny: CZ / CZaudio /
            #    historické kombinace typu CZ-SK / CZ-EN / CZ-Atmos-5.1
            if tl in ("czdab", "cz", "czaudio"):
                return (0, 0, orig_index)
            if tu.startswith("CZ-"):
                return (0, 0, orig_index)

            # 2) CZtit (české titulky) – kompat token: CZsub
            if tl in ("cztit", "czsub"):
                return (1, 0, orig_index)

            # 3) Audio kvalita
            audio_order = {"atmos": 0, "7.1": 1, "5.1": 2, "2.0": 3}
            if tl in audio_order:
                return (2, audio_order[tl], orig_index)

            # 4) Rozlišení
            res_order = {"2160p": 0, "1440p": 1, "1080p": 2, "720p": 3, "sd": 4}
            if tl in res_order:
                return (3, res_order[tl], orig_index)

            # 5) Obrazové formáty
            video_fmt = {"dv": 0, "hdr10+": 1, "hdr10": 2, "hdr": 3}
            if tl in video_fmt:
                return (4, video_fmt[tl], orig_index)

            # 6) Kodeky
            codec_order = {"hevc": 0, "h.264": 1}
            if tl in codec_order:
                return (5, codec_order[tl], orig_index)

            # 7) Ostatní – zůstanou na konci v původním pořadí
            return (6, 0, orig_index)

        def _promote_features(feats: list) -> list:
            # dedupe (zachovat první výskyt), potom seřadit podle priorit
            deduped = _uniq_keep_order([str(f) for f in (feats or [])])
            ranked = [( _rank_feature(tok, idx), tok ) for idx, tok in enumerate(deduped)]
            ranked.sort(key=lambda x: x[0])
            return [tok for _, tok in ranked]

        for c in (candidates or []):
            ident = c.get('ident')
            if not ident:
                continue

            item = {
                'ident': ident,
                'name': c.get('name') or '',
                'quality': c.get('quality') or c.get('ainfo') or '',
                'lang': c.get('lang') or '',
                'size': int(c.get('size', '0') or 0),
                'ainfo': c.get('ainfo') or '',
                'score': 0,
                'added_at': xbmc.getInfoLabel('System.Date'),
                'source': 'webshare'
            }

            # základní feature značky z názvu/ainfo
            feats = list(self.extract_features(item) or [])

            # >>> enrichment z cache: CZ titulky (nový tag CZtit, kompat staré CZsub)
            try:
                if has_cz_subs(ident) and not any(
                    str(f).lower() in ('czsub', 'cztit') for f in feats
                ):
                    feats.append('CZtit')
            except Exception:
                pass

            # enrichment z cache: audio (CZ/kanály/Atmos) + video (2160p/HDR/DV)
            try:
                for b in audio_badges(ident):
                    if b not in feats:
                        feats.append(b)
            except Exception:
                pass
            try:
                for b in video_badges(ident):
                    if b not in feats:
                        feats.append(b)
            except Exception:
                pass
            # <<< enrichment z cache

            # >>> negative override z cache pro probované streamy:
            # Pokud byl stream skutečně proben (ffprobe / http_range_probe),
            # cache je autoritativní zdroj pro CZdab/CZtit. Filename-derived
            # CZ tagy z `extract_features` musí být odstraněny, pokud cache
            # CZ stopu / titulky **nepotvrdila** (jinak by FP z parsingu
            # názvu typu `EN.cz.titulky.mkv` přežil).
            try:
                if is_probed(ident):
                    if not has_cz_audio(ident):
                        feats = [
                            f for f in feats
                            if not (
                                str(f).lower() in ('cz', 'czdab', 'czaudio')
                                or str(f).upper().startswith('CZ-')
                            )
                        ]
                    if not has_cz_subs(ident):
                        feats = [
                            f for f in feats
                            if str(f).lower() not in ('cztit', 'czsub')
                        ]
            except Exception:
                pass
            # <<< negative override

            feats = _promote_features(feats)

            item['features'] = feats
            item['label'] = ', '.join(feats) if feats else (
                (item['quality'] or '').strip() or (item['name'] or '').strip() or 'Stream'
            )

            normalized.append(item)

        return normalized

    @staticmethod
    def extract_features(st):
        """
        Vrátí seznam vlastností streamu, např. ['CZdab', 'CZtit', '5.1', 'HDR10', 'HEVC', '2160p'].

        Jazykové tagy jsou jednotně **pouze** `CZdab` (česká audio stopa) a
        `CZtit` (české titulky). Žádné kombinované tokeny typu CZ-SK / CZ-EN
        ani ne-CZ jazykové značky se nevyrábí.

        Vstupy bere z:
        - st['name'] (původní filename),
        - st['quality'] a st['ainfo'],
        - st['lang'] (pokud není v názvu).
        """
        name = (st.get('name') or '')
        q    = (st.get('quality') or '')
        ai   = (st.get('ainfo') or '')
        lang = (st.get('lang') or '')
        blob = ' '.join([name, q, ai]).lower()

        feats = []

        # 1) jazyk: rozlišit CZ audio (CZdab) vs. CZ titulky (CZtit).
        #
        # Detekce je sdílená s offline_managerem (`series_helpers`):
        #   - silný CZ-dub marker (`cz.dab`, `cs.dub`, `dab.cz`, …) nebo
        #     holé `cz`/`cs` v blobu BEZ subs kontextu → CZdab
        #   - silný CZ-tit marker (`cz.tit`, `cs.sub`, `czech.forced`, …) → CZtit
        #
        # Tím se zabrání tomu, aby `Movie.2024.1080p.EN.cz.titulky.mkv` byl
        # falešně označen jako CZdab.
        from resources.lib.series.series_helpers import (
            detect_cz_dub_from_blob,
            detect_cz_tit_from_blob,
        )
        if detect_cz_dub_from_blob(blob, lang):
            feats.append('CZdab')
        if detect_cz_tit_from_blob(blob):
            feats.append('CZtit')

        # 2) audio layout / Atmos – jako samostatné featury
        if re.search(r'\batmos\b', blob):
            feats.append('Atmos')
        ch = re.search(r'\b(7\.1|5\.1|2\.0)\b', blob)
        if ch:
            feats.append(ch.group(1))

        # 3) HDR/DV — priorita HDR10+ > HDR10 > HDR
        # Pozn.: `\bhdr10\b` matchuje i `HDR10+` (boundary 0|+), ale ne
        # `HDR10plus` ani `HDR10 plus`. Explicitní HDR10+ větev musí jít
        # PŘED `\bhdr10\b`, jinak by se zapsal HDR10 a HDR10+ by se ztratil.
        if re.search(r'\bhdr10\s*\+|\bhdr10\s*plus\b', blob):
            feats.append('HDR10+')
        elif re.search(r'\bhdr10\b', blob):
            feats.append('HDR10')
        elif re.search(r'\bhdr\b', blob):
            feats.append('HDR')
        if re.search(r'\b(dv|dolby\s*vision)\b', blob):
            feats.append('DV')

        # 4) kodek
        if re.search(r'\b(hevc|x265)\b', blob):
            feats.append('HEVC')
        elif re.search(r'\b(x264|avc)\b', blob):
            feats.append('H.264')

        # 5) rozlišení
        if re.search(r'\b(2160p|4k)\b', blob):
            feats.append('2160p')
        elif re.search(r'\b1080p\b', blob):
            feats.append('1080p')
        elif re.search(r'\b720p\b', blob):
            feats.append('720p')

        # unikátní pořadí zachovat
        uniq = []
        for f in feats:
            if f not in uniq:
                uniq.append(f)
        return uniq
