# -*- coding: utf-8 -*-
import os
import re
import time
import json
import hashlib
import xbmcvfs
import requests

from resources.lib.utils.log_utils import get_logger

log = get_logger()


class CSFDScraper:
    """
    Robustní ČSFD scraper inspirovaný nativním XML scraperem csfdcz.xml.
    Používá moderní HTTP hlavičky (zabraňuje zablokování 429) a chytré
    regulární výrazy na parsování jazykových variant názvů, herců, hodnocení a galerie.

    Pozn.: CSFD nasadil Anubis (BotStopper) PoW. Anubis typicky challenge
    spouští pro User-Agent obsahující „Mozilla“. Proto default UA není
    browserový – jinak scraper dostane jen stránku „Ujišťujeme se, že nejste robot!“
    bez výsledků hledání.
    """
    BASE_URL = "https://www.csfd.cz"

    # UA bez „Mozilla“ – Anubis challenge se typicky nespouští
    HEADERS = {
        "User-Agent": "plugin.video.mmirousek_v3/CSFD-Scraper (Kodi; compatible)",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "cs-CZ,cs;q=0.9,en-US;q=0.8,en;q=0.7",
        "Accept-Encoding": "gzip, deflate",
        "Cache-Control": "max-age=0",
    }

    _ANUBIS_MARKERS = (
        "anubis_challenge",
        "Ujišťujeme se, že nejste robot",
        "/.within.website/x/cmd/anubis/",
        "techaro.lol-anubis",
    )

    def __init__(self, cache_dir):
        self.cache_dir = cache_dir
        if not xbmcvfs.exists(self.cache_dir):
            xbmcvfs.mkdirs(self.cache_dir)

    def _get_cache_key(self, url):
        return hashlib.sha1(url.encode('utf-8')).hexdigest()

    @classmethod
    def _is_anubis_challenge(cls, html):
        if not html or len(html) < 500:
            return False
        # Krátká Anubis interstitial (~4 KB) vs. reálná výsledková stránka (~90 KB+)
        low = html[:8000]
        return any(m in low for m in cls._ANUBIS_MARKERS)

    def _read_cache(self, url):
        fp = os.path.join(self.cache_dir, self._get_cache_key(url) + '.json')
        if xbmcvfs.exists(fp):
            with xbmcvfs.File(fp) as f:
                raw = f.read()
            try:
                obj = json.loads(raw)
                # Cache platí 24 hodin
                if time.time() - obj.get('_time', 0) < 86400:
                    payload = obj.get('payload')
                    # Nevracet z cache Anubis challenge (např. po starém Mozilla UA)
                    if self._is_anubis_challenge(payload):
                        log.info("[CSFD] Cache obsahuje Anubis challenge – ignoruji")
                        return None
                    return payload
            except Exception:
                pass
        return None

    def _write_cache(self, url, payload):
        if self._is_anubis_challenge(payload):
            log.warning("[CSFD] Anubis challenge HTML – neukládám do cache")
            return
        fp = os.path.join(self.cache_dir, self._get_cache_key(url) + '.json')
        try:
            with xbmcvfs.File(fp, 'w') as f:
                f.write(json.dumps({'_time': time.time(), 'payload': payload}, ensure_ascii=False))
        except Exception:
            pass

    def _get_html(self, url):
        cached = self._read_cache(url)
        if cached:
            return cached

        wait = 1.5
        for attempt in range(3):
            try:
                r = requests.get(url, headers=self.HEADERS, timeout=12)
                if r.status_code == 200:
                    html = r.text
                    if self._is_anubis_challenge(html):
                        log.warning(
                            f"[CSFD] Anubis challenge (pokus {attempt + 1}/3) – "
                            "stránka je chráněna BotStopperem, UA bez Mozilla by měl projít"
                        )
                        time.sleep(wait)
                        wait = min(wait * 2, 10)
                        continue
                    self._write_cache(url, html)
                    return html
                elif r.status_code == 429:
                    log.warning(f"[CSFD] HTTP 429 – čekám {wait}s")
                    time.sleep(wait)
                    wait = min(wait * 2, 10)
                else:
                    log.warning(f"[CSFD] HTTP {r.status_code} pro {url}")
            except Exception as e:
                log.warning(f"[CSFD] Request error: {e}")
                time.sleep(1)
        return None

    def search(self, query, top_n=12):
        """Vyhledá shodu na ČSFD a vrátí list tuples: [(název, url), ...]"""
        url = f"{self.BASE_URL}/hledat/?q={query.replace(' ', '+')}"
        html = self._get_html(url)
        results = []
        if not html:
            log.warning(f"[CSFD] search: prázdná odpověď pro q={query!r}")
            return results
        if self._is_anubis_challenge(html):
            log.error("[CSFD] search: stále Anubis challenge – výsledky nedostupné")
            return results

        # Hledáme všechny položky (filmy i seriály) včetně dodatečných info (rok, typ)
        # Typický tvar: <a href="/film/123-abc/prehled/" class="film-title-name">Název</a> ...
        parts = html.split('class="film-title-name"')
        for i in range(1, len(parts)):
            prev_block = parts[i - 1]
            m_href = re.search(r'href="(/film/[^"]+)"[^>]*$', prev_block, re.IGNORECASE)
            if not m_href:
                continue
            href = m_href.group(1)

            curr_block = parts[i]
            m_title = re.search(
                r'^>([^<]+)</a>([\s\S]*?)(?:</article>|</li>|<div|$)',
                curr_block,
                re.IGNORECASE,
            )
            if not m_title:
                continue

            title = re.sub(r'<[^>]+>', '', m_title.group(1)).strip()
            rest = m_title.group(2)

            extra = []
            m_info_block = re.search(
                r'<span class="film-title-info">([\s\S]*?)(?:</h3>|</p>|</div>)', rest
            )
            if m_info_block:
                for m_info in re.finditer(
                    r'<span class="info">\s*\((.*?)\)\s*</span>', m_info_block.group(1)
                ):
                    extra.append(m_info.group(1).strip())

            if extra:
                title = f"{title} [{', '.join(extra)}]"

            if title and all(t[1] != self.BASE_URL + href for t in results):
                results.append((title, self.BASE_URL + href))
            if len(results) >= top_n:
                break

        if not results:
            for m in re.finditer(
                r'href="(/film/[^"]+)"[^>]*>([^<]+)</a>', html, re.IGNORECASE
            ):
                href, title = m.group(1), re.sub(r'<[^>]+>', '', m.group(2)).strip()
                if title and all(t[1] != self.BASE_URL + href for t in results):
                    results.append((title, self.BASE_URL + href))
                if len(results) >= top_n:
                    break

        log.info(f"[CSFD] search q={query!r} -> {len(results)} výsledků")
        return results

    def get_light_detail(self, url, max_comments=5):
        """
        Odlehčená verze pro Hybridní okno. Získá pouze:
        - Plot (děj)
        - Hodnocení
        - Uživatelské recenze
        - Délku (runtime) a Rok (pro jistotu)
        Nestahuje podstránky /hraji/ a /galerie/, ty se berou z TMDb/DB.
        """
        html = self._get_html(url)

        d = {
            "title_cz": "",
            "year": "",
            "runtime": "",
            "rating": "N/A",
            "votes": "",
            "plot": "",
            "comments": [],
        }

        if not html:
            return d

        flags = re.DOTALL | re.IGNORECASE

        m_h1 = re.search(r'<h1[^>]*>([^<]+)</h1>', html, flags)
        if m_h1:
            d["title_cz"] = m_h1.group(1).strip()

        m_year = re.search(
            r'<div[^>]*class="origin"[^>]*>[\s\S]*?<span>(\d{4})</span>', html, flags
        )
        if m_year:
            d["year"] = m_year.group(1).strip()

        m_runtime = re.search(r'<div class="origin">[\s\S]*?(\d+)\s*min', html, flags)
        if m_runtime:
            d["runtime"] = m_runtime.group(1).strip()

        m_rating = re.search(
            r'class="film-rating-average[^"]*"[^>]*>\s*([0-9]{1,3})\s*%', html, flags
        )
        if m_rating:
            d["rating"] = m_rating.group(1).strip()

        m_votes = re.search(r'class="counter">\s*\((.*?)\)\s*<', html, flags)
        if m_votes:
            d["votes"] = m_votes.group(1).strip()

        m_plot = re.search(
            r'class="(?:plot-full|plot-full hidden)">[^<]*<p>\s*(.*?)\s*<em class="span-more-small"',
            html,
            flags,
        )
        if m_plot:
            raw_plot = re.sub(r'<br\s*/?>', '\n', m_plot.group(1))
            d["plot"] = re.sub(r'<[^>]+>', '', raw_plot).strip()
        else:
            m_plot2 = re.search(
                r'<div[^>]*class="plot-text"[^>]*>\s*<p>\s*(.*?)\s*</p>', html, flags
            )
            if m_plot2:
                raw_plot = re.sub(r'<br\s*/?>', '\n', m_plot2.group(1))
                d["plot"] = re.sub(r'<[^>]+>', '', raw_plot).strip()

        for mm in re.finditer(
            r'class="user-title-name"[^>]*>(.*?)</a>[\s\S]*?data-film-review-content>\s*([\s\S]*?)</span>',
            html,
            flags,
        ):
            author = mm.group(1).strip()
            txt = mm.group(2)
            txt = re.sub(r'<br\s*/?>', '\n', txt)
            txt = re.sub(r'<[^>]+>', '', txt).strip()
            if txt and len(txt) > 15:
                d["comments"].append(f"[B][COLOR gold]👤 {author}[/COLOR][/B]\n{txt}")
            if len(d["comments"]) >= max_comments:
                break

        return d
