import xbmc
import xbmcgui
import xbmcaddon
import xbmcvfs
import os
import json
import threading

from endpoints import CHANGELOG_URL, CHANGELOG_URL_2

ADDON = xbmcaddon.Addon()

CHANGELOG_VERSION_PATH = xbmcvfs.translatePath("special://userdata/addon_data/plugin.video.jet_guide/changelog_version.json")
CHANGELOG_LOCAL_PATH = xbmcvfs.translatePath("special://home/addons/plugin.video.jet_guide/CHANGELOG.md")
NAVIGATION_LOCAL_PATH2 = xbmcvfs.translatePath("special://home/addons/plugin.video.jet_guide/NAVIGATION.md")

PAGES = [
    {"label": "Changelog (Local)", "local_path": CHANGELOG_LOCAL_PATH, "url": None},
    {"label": "Navigation", "local_path": NAVIGATION_LOCAL_PATH2, "url": None},
    {"label": "More Info", "local_path": None, "url": CHANGELOG_URL},
    {"label": "Extra Info", "local_path": None, "url": CHANGELOG_URL_2},
]

COLOR_HEADER = "FF4FC3F7"      # Light Blue
COLOR_SUBHEADER = "FF81D4FA"   # Lighter Blue
COLOR_BOLD = "FFFFAB40"        # Orange
COLOR_BULLET = "FF80CBC4"      # Teal
COLOR_TEXT = "FFFFFFFF"         # White

VISIBLE_LINES = 18
SCROLL_STEP = 3
AUTO_SCROLL_DELAY = 8.0
AUTO_SCROLL_SPEED = 1.0
SCROLL_BAR_TOP = 145
SCROLL_BAR_BOTTOM = 505
SCROLL_BAR_HEIGHT = 30


def parse_markdown_to_kodi(text):
    import re
    lines = text.split('\n')
    result = []
    for line in lines:
        stripped = line.strip()
        if stripped.startswith('## '):
            result.append(f'[COLOR={COLOR_HEADER}][B]{stripped[3:]}[/B][/COLOR]')
        elif stripped.startswith('### '):
            result.append(f'[COLOR={COLOR_SUBHEADER}][B]{stripped[4:]}[/B][/COLOR]')
        elif stripped.startswith('-'):
            inner = stripped[2:]
            inner = re.sub(r'\*\*(.+?)\*\*', rf'[COLOR={COLOR_BOLD}][B]\1[/B][/COLOR]', inner)
            result.append(f'[COLOR={COLOR_BULLET}]  \u2022 [/COLOR]{inner}')
        elif stripped.startswith('---'):
            result.append(f'[COLOR={COLOR_BULLET}]{"─" * 60}[/COLOR]')
        elif stripped.startswith('**') and stripped.endswith('**'):
            result.append(f'[COLOR={COLOR_BOLD}][B]{stripped[2:-2]}[/B][/COLOR]')
        else:
            inner = re.sub(r'\*\*(.+?)\*\*', rf'[COLOR={COLOR_BOLD}][B]\1[/B][/COLOR]', stripped)
            result.append(f'[COLOR={COLOR_TEXT}]{inner}[/COLOR]')
    return '\n'.join(result)


def _fetch_page_text(page):
    import urllib.request
    if page.get("local_path") and xbmcvfs.exists(page["local_path"]):
        with xbmcvfs.File(page["local_path"], "r") as f:
            return f.read()
    if page.get("url"):
        cache_path = xbmcvfs.translatePath(
            "special://userdata/addon_data/plugin.video.jet_guide/changelog_cache_{}.txt".format(PAGES.index(page))
        )
        headers = {'User-Agent': 'Mozilla/5.0'}
        req = urllib.request.Request(page["url"], headers=headers)
        try:
            with urllib.request.urlopen(req) as response:
                text = response.read().decode('utf-8')
            with xbmcvfs.File(cache_path, "w") as f:
                f.write(text)
            return text
        except Exception as e:
            xbmc.log(f"[jet_guide] Failed to fetch {page['label']}: {e}", xbmc.LOGERROR)
            if xbmcvfs.exists(cache_path):
                with xbmcvfs.File(cache_path, "r") as f:
                    return f.read()
    return f"Failed to load {page.get('label', 'page')}."


class ChangelogWindow(xbmcgui.WindowXML):
    def __init__(self, xml_file, addon_path):
        xbmc.log(f"[jet_guide] ChangelogWindow init with xml={xml_file}, path={addon_path}", xbmc.LOGINFO)
        super().__init__(xml_file, addon_path)
        self.dont_show_again = False
        self._page_index = 0
        self._full_text = ""
        self._display_lines = []
        self._scroll_offset = 0
        self._auto_scroll_timer = None
        self._auto_scroll_running = False
        self._manual_scroll_timer = None

    def _update_textbox(self):
        end = self._scroll_offset + VISIBLE_LINES
        visible = '\n'.join(self._display_lines[self._scroll_offset:end])
        self.getControl(5000).setText(visible)
        max_offset = max(1, len(self._display_lines) - VISIBLE_LINES)
        ratio = self._scroll_offset / max_offset
        bar_y = int(SCROLL_BAR_TOP + ratio * (SCROLL_BAR_BOTTOM - SCROLL_BAR_TOP - SCROLL_BAR_HEIGHT))
        self.getControl(5004).setPosition(1240, bar_y)

    def _start_auto_scroll(self):
        self._stop_auto_scroll()
        self._auto_scroll_running = True
        self._auto_scroll_timer = threading.Timer(AUTO_SCROLL_DELAY, self._auto_scroll_tick)
        self._auto_scroll_timer.daemon = True
        self._auto_scroll_timer.start()

    def _stop_auto_scroll(self):
        self._auto_scroll_running = False
        if self._auto_scroll_timer:
            self._auto_scroll_timer.cancel()
            self._auto_scroll_timer = None

    def _auto_scroll_tick(self):
        if not self._auto_scroll_running:
            return
        max_offset = max(0, len(self._display_lines) - VISIBLE_LINES)
        if self._scroll_offset < max_offset:
            self._scroll_offset += 1
        else:
            self._scroll_offset = 0
        self._update_textbox()
        self._auto_scroll_timer = threading.Timer(AUTO_SCROLL_SPEED, self._auto_scroll_tick)
        self._auto_scroll_timer.daemon = True
        self._auto_scroll_timer.start()

    def _schedule_auto_scroll(self):
        if self._manual_scroll_timer:
            self._manual_scroll_timer.cancel()
        self._manual_scroll_timer = threading.Timer(AUTO_SCROLL_DELAY, self._start_auto_scroll)
        self._manual_scroll_timer.daemon = True
        self._manual_scroll_timer.start()

    def _manual_scroll(self, direction):
        self._stop_auto_scroll()
        if self._manual_scroll_timer:
            self._manual_scroll_timer.cancel()
        max_offset = max(0, len(self._display_lines) - VISIBLE_LINES)
        self._scroll_offset = max(0, min(max_offset, self._scroll_offset + direction * SCROLL_STEP))
        self._update_textbox()
        self._schedule_auto_scroll()

    def _show_page(self, index):
        self._stop_auto_scroll()
        if self._manual_scroll_timer:
            self._manual_scroll_timer.cancel()
        self._page_index = index % len(PAGES)
        page = PAGES[self._page_index]
        raw_text = _fetch_page_text(page)
        self._full_text = parse_markdown_to_kodi(raw_text)
        self._display_lines = self._full_text.split('\n')
        self._scroll_offset = 0
        self._update_textbox()
        next_page = PAGES[(self._page_index + 1) % len(PAGES)]
        self.getControl(8000).setLabel(f"[B]Next Page: {next_page['label']}[/B]")
        xbmc.log(f"[jet_guide] Showing page {self._page_index}: {page['label']}", xbmc.LOGINFO)
        self._start_auto_scroll()

    def onInit(self):
        try:
            xbmc.log("[jet_guide] Changelog onInit started", xbmc.LOGINFO)
            self.setProperty('version', ADDON.getAddonInfo('version'))
            self._show_page(0)
            xbmc.log("[jet_guide] Changelog onInit completed", xbmc.LOGINFO)
            self.setFocusId(9000)
        except Exception as e:
            xbmc.log(f"[jet_guide] Error initializing changelog: {str(e)}", xbmc.LOGERROR)

    def onAction(self, action):
        action_id = action.getId()
        if action_id in [xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK, 92]:
            self._stop_auto_scroll()
            if self._manual_scroll_timer:
                self._manual_scroll_timer.cancel()
            save_dont_show_again()
            self.close()
        elif action_id in [xbmcgui.ACTION_SELECT_ITEM, xbmcgui.ACTION_MOUSE_LEFT_CLICK]:
            focused = self.getFocusId()
            if focused == 9000:
                self._stop_auto_scroll()
                save_dont_show_again()
                xbmc.sleep(500)
                self.close()
            elif focused == 8000:
                self._show_page(self._page_index + 1)
            elif focused == 5001:
                self._manual_scroll(-1)
            elif focused == 5002:
                self._manual_scroll(1)
        elif action_id == xbmcgui.ACTION_MOVE_UP:
            focused = self.getFocusId()
            if focused == 5000:
                self._manual_scroll(-1)
            elif focused == 5002:
                self._manual_scroll(-1)
        elif action_id == xbmcgui.ACTION_MOVE_DOWN:
            focused = self.getFocusId()
            if focused == 5000:
                self._manual_scroll(1)
            elif focused == 5001:
                self._manual_scroll(1)
        elif action_id in [xbmcgui.ACTION_MOUSE_WHEEL_UP, xbmcgui.ACTION_MOUSE_WHEEL_DOWN]:
            focused = self.getFocusId()
            if focused in [5000, 5001, 5002]:
                direction = -1 if action_id == xbmcgui.ACTION_MOUSE_WHEEL_UP else 1
                self._manual_scroll(direction)


def get_saved_version():
    try:
        if xbmcvfs.exists(CHANGELOG_VERSION_PATH):
            with xbmcvfs.File(CHANGELOG_VERSION_PATH, "r") as f:
                data = json.loads(f.read())
                return data.get('version')
    except Exception:
        pass
    return None


def save_saved_version(version):
    try:
        with xbmcvfs.File(CHANGELOG_VERSION_PATH, "w") as f:
            json.dump({'version': version, 'dont_show': False}, f)
    except Exception as e:
        xbmc.log(f"[jet_guide] Error saving version: {str(e)}", xbmc.LOGERROR)


def save_dont_show_again():
    try:
        current_version = ADDON.getAddonInfo('version')
        with xbmcvfs.File(CHANGELOG_VERSION_PATH, "w") as f:
            json.dump({'version': current_version, 'dont_show': True}, f)
        xbmc.log(f"[jet_guide] Saved dont_show for version {current_version}", xbmc.LOGINFO)
    except Exception as e:
        xbmc.log(f"[jet_guide] Error saving dont_show: {str(e)}", xbmc.LOGERROR)


def check_and_show_changelog(addon_path):
    try:
        xbmc.log(f"[jet_guide][debug] Entered check_and_show_changelog. ADDON.getAddonInfo('version')={ADDON.getAddonInfo('version')}", xbmc.LOGINFO)

        xbmc.log("[jet_guide] check_and_show_changelog called", xbmc.LOGINFO)
        current_version = ADDON.getAddonInfo('version')
        saved = None
        if xbmcvfs.exists(CHANGELOG_VERSION_PATH):
            with xbmcvfs.File(CHANGELOG_VERSION_PATH, "r") as f:
                try:
                    saved = json.loads(f.read())
                except Exception:
                    saved = None
        show = True
        if saved and saved.get('version') == current_version and saved.get('dont_show'):
            show = False
        if show:
            xbmc.log("[jet_guide] Showing changelog window", xbmc.LOGINFO)
            save_saved_version(current_version)
            win = ChangelogWindow("changelog.xml", addon_path)
            win.doModal()
            del win
        else:
            xbmc.log("[jet_guide] Not showing changelog window (already seen)", xbmc.LOGINFO)
    except Exception as e:
        xbmc.log(f"[jet_guide] Error showing changelog: {str(e)}", xbmc.LOGERROR)


def show_changelog_from_tools(addon_path):
    try:
        xbmc.log("[jet_guide] show_changelog_from_tools called", xbmc.LOGINFO)
        win = ChangelogWindow("changelog.xml", addon_path)
        win.doModal()
        del win
    except Exception as e:
        xbmc.log(f"[jet_guide] Error showing changelog: {str(e)}", xbmc.LOGERROR)
        xbmcgui.Dialog().ok("Error", f"Failed to show changelog: {str(e)}")
