# -*- coding: utf-8 -*-
"""
CloudDrive2 Kodi Plugin - Main Entry Point

URL route format:
  plugin://plugin.video.clouddrive2/?mode=<MODE>&<params...>

Modes:
  main            - Main menu
  account_check   - Check login state, show wizard if needed
  cloud_list      - List configured cloud drives
  cloud_add       - Add cloud drive menu (choose provider type)
  cloud_add_qr    - Start QR code login for given provider
  cloud_remove    - Remove a cloud drive
  cloud_space     - Show cloud drive space info
  mount_list      - List mount points
  mount_add       - Add mount point
  mount_remove    - Remove mount point
  mount_toggle    - Toggle mount/unmount
  account_info    - Show account info
  settings        - Open addon settings
"""

import sys
import os
import socket
import tempfile
import urllib.parse
import urllib.request

import xbmcplugin
import xbmcgui
import xbmcaddon
import xbmc
import xbmcvfs

# Load vendor dependencies - use robust path resolution
def _get_addon_dir():
    """Get addon directory, works both in Kodi and standalone Python."""
    try:
        import xbmcaddon
        import xbmcvfs
        addon = xbmcaddon.Addon()
        return xbmcvfs.translatePath(addon.getAddonInfo("path"))
    except Exception:
        return os.path.dirname(os.path.abspath(__file__))

ADDON_DIR = _get_addon_dir()
VENDOR_DIR = os.path.join(ADDON_DIR, "resources", "lib", "vendors")
if VENDOR_DIR not in sys.path:
    sys.path.insert(0, VENDOR_DIR)
    
from resources.lib.service import SystemctlService
from resources.lib import cd2_utils
from resources.lib.cd2_constants import *
from resources.lib.cd2_client import get_client
from resources.lib.cd2_dialogs import ok, notification
from resources.lib.cd2_l10n import _

log = cd2_utils.log

_addon = None

def _get_addon():
    global _addon
    if _addon is None:
        _addon = xbmcaddon.Addon(ADDON_ID)
    return _addon


def get_params():
    """Parse query string parameters from plugin URL."""
    params = {"mode": MODE_MAIN}
    try:
        qs = sys.argv[2] if len(sys.argv) > 2 else ""
        if qs.startswith("?"):
            qs = qs[1:]
        for pair in qs.split("&"):
            if "=" in pair:
                k, v = pair.split("=", 1)
                params[k] = urllib.parse.unquote(v)
    except Exception:
        pass
    return params


def add_main_menu_item(handle, label, mode, **kwargs):
    """Add a directory item to the main menu."""
    kwargs["mode"] = mode
    qs = "&".join(f"{k}={urllib.parse.quote(str(v))}" for k, v in kwargs.items())
    url = f"{sys.argv[0]}?{qs}"
    li = xbmcgui.ListItem(label)
    li.setProperty("IsPlayable", "false")
    xbmcplugin.addDirectoryItem(handle, url, li, isFolder=True)


def show_main_menu(handle):
    """Display the main CloudDrive2 menu."""
    xbmcplugin.setContent(handle, "files")

    # Service status determines menu labels
    try:
        svc = SystemctlService(CD2_SERVICE_NAME)
        svc_running = svc.status_service() == "active"
    except Exception:
        svc_running = False

    if svc_running:
        start_label = f"[B]{_(32152)}[/B]  [COLOR red][{_(32153)}][/COLOR]"
        stop_label = f"[B]{_(32154)}[/B]"
    else:
        start_label = f"[B]{_(32152)}[/B]"
        stop_label = f"[B]{_(32154)}[/B]  [COLOR red][{_(32155)}][/COLOR]"

    add_main_menu_item(handle, f"[B]{_(32001)}[/B]", MODE_ACCOUNT_CHECK)
    add_main_menu_item(handle, f"[B]{_(32007)}[/B]", MODE_SEARCH)
    add_main_menu_item(handle, f"[B]{_(32171)}[/B]", MODE_FILE_BROWSE)
    add_main_menu_item(handle, f"[B]{_(32002)}[/B]", MODE_CLOUD_LIST)
    add_main_menu_item(handle, f"[B]{_(32003)}[/B]", MODE_CLOUD_ADD)
    add_main_menu_item(handle, f"[B]{_(32004)}[/B]", MODE_MOUNT_LIST)
    add_main_menu_item(handle, f"[B]{_(32158)}[/B]", MODE_WEB_ADMIN)
    add_main_menu_item(handle, start_label, MODE_SERVICE_START)
    add_main_menu_item(handle, stop_label, MODE_SERVICE_STOP)
    add_main_menu_item(handle, f"[B]{_(32141)}[/B]", MODE_CHECK_UPDATE)
    add_main_menu_item(handle, f"[B]{_(32006)}[/B]", MODE_SETTINGS)

    xbmcplugin.endOfDirectory(handle)


def show_account_info(handle):
    """Show account and system information."""
    client = get_client()
    try:
        sys_info = client.get_system_info(timeout=5)
        run_info = client.get_runtime_info(timeout=5)
        running = client.get_running_info(timeout=5)
    except Exception as e:
        ok(_(32030), _(32031, e))
        xbmcplugin.endOfDirectory(handle)
        return

    def _safe_int(val):
        try:
            return int(val)
        except (ValueError, TypeError):
            return val

    lines = []
    lines.append(_(32101, sys_info.UserName))
    lines.append(_(32102, getattr(run_info, 'productName', None) or 'N/A'))
    lines.append(_(32103, getattr(run_info, 'productVersion', None) or 'N/A'))
    lines.append(_(32104, getattr(run_info, 'osInfo', None) or 'N/A'))
    lines.append(_(32105, sys_info.SystemReady))

    uptime = getattr(running, 'uptime', None)
    if uptime is not None:
        uptime = _safe_int(uptime)
        lines.append(_(32106, uptime))

    mem = getattr(running, 'memUsageKB', None)
    if mem is not None:
        mem = _safe_int(mem)
        if isinstance(mem, int):
            lines.append(_(32107, mem // 1024))
        else:
            lines.append(_(32107).format(mem))

    xbmcplugin.endOfDirectory(handle)
    xbmcgui.Dialog().textviewer(_(32100), "\n".join(lines))


def check_update_handler():
    """Check for CD2 updates, prompt download if available."""
    client = get_client()
    progress = xbmcgui.DialogProgress()
    progress.create("CloudDrive2", _(32142))

    current_version = "N/A"
    try:
        run_info = client.get_runtime_info(timeout=5)
        current_version = getattr(run_info, 'productVersion', 'N/A') or 'N/A'
    except Exception:
        pass

    try:
        result = client.check_update(timeout=10)
    except Exception as e:
        progress.close()
        ok(_(32030), _(32143, str(e)))
        return

    progress.close()

    has_update = result.hasUpdate if hasattr(result, 'hasUpdate') else False
    new_version = result.newVersion if hasattr(result, 'newVersion') else ""
    description = result.description if hasattr(result, 'description') else ""

    if has_update and new_version:
        dialog = xbmcgui.Dialog()
        msg = _(32144, current_version, new_version)
        if description:
            msg += f"\n\n{description}"
        confirm = dialog.yesno("CloudDrive2", msg + "\n\n" + _(32145))
        if confirm:
            _do_update(client)
    else:
        xbmcgui.Dialog().ok("CloudDrive2", _(32146, current_version))


def _do_update(client):
    """Download and install the update."""
    progress = xbmcgui.DialogProgress()
    progress.create("CloudDrive2", _(32147))

    try:
        client.download_update(timeout=300)
    except Exception as e:
        progress.close()
        ok(_(32030), _(32143, str(e)))
        return

    progress.update(50, _(32148))
    try:
        client.update_system(timeout=60)
        progress.update(100)
    except Exception as e:
        progress.close()
        ok(_(32030), _(32143, str(e)))
        return

    progress.close()
    xbmcgui.Dialog().ok("CloudDrive2", _(32149))


def _clear_all_data():
    """Clear all CD2 account data: logout CloudFS, clear credentials/token, wipe data dir."""
    import shutil
    import xml.etree.ElementTree as ET

    # 1. Logout from CloudFS
    client = get_client()
    try:
        client.logout(timeout=10)
    except Exception:
        pass

    # 2. Clear saved credentials in settings file directly (bypass Kodi cache)
    settings_path = os.path.join(xbmcvfs.translatePath("special://profile"),
                                 "addon_data", ADDON_ID, "settings.xml")
    try:
        tree = ET.parse(settings_path)
        root = tree.getroot()
        for el in root.iter("setting"):
            if el.get("id") in ("cd2_username", "cd2_password"):
                el.text = ""
        tree.write(settings_path, encoding="utf-8", xml_declaration=True)
    except Exception:
        pass
    cd2_utils.clear_token()

    # 3. Clear /storage/Waytech/ except config.toml
    waytech = "/storage/Waytech"
    if os.path.exists(waytech):
        for item in os.listdir(waytech):
            item_path = os.path.join(waytech, item)
            if item == "config.toml":
                continue
            try:
                if os.path.isdir(item_path):
                    shutil.rmtree(item_path)
                else:
                    os.remove(item_path)
            except Exception:
                pass

    # 4. Prompt reboot
    if xbmcgui.Dialog().yesno("CloudDrive2", _(32168), _(32169)):
        os.system("reboot")


def get_local_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("223.5.5.5", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"


class _WebAdminDialog(xbmcgui.WindowXMLDialog):
    def onInit(self):
        self.getControl(100).setImage(self._img_path)
        self.getControl(101).setLabel(_(32159))
        self.getControl(102).setLabel(f"{_(32160)}: {self._local_ip}:19798")
        self.getControl(103).setLabel(_(32161))
        self.getControl(109).setLabel(_(32162))
        self.getControl(110).setLabel(_(32163))
        self.getControl(111).setLabel(_(32164))
        self.getControl(112).setLabel(f"[B]{_(32165)}: {self._username}[/B]")
        self.getControl(113).setLabel(f"[B]{_(32166)}: {self._password}[/B]")



def show_web_admin():
    if not cd2_utils.is_service_running():
        xbmcgui.Dialog().ok(_(32030), _(32170))
        return

    local_ip = get_local_ip()
    qr_url = f"https://api.2dcode.biz/v1/create-qr-code?data=http://{local_ip}:19798&size=300x300"

    tmpdir = tempfile.gettempdir()
    img_path = os.path.join(tmpdir, "cd2_admin_qr.png")

    try:
        proxy_handler = urllib.request.ProxyHandler({})
        opener = urllib.request.build_opener(proxy_handler)
        resp = opener.open(qr_url, timeout=30)
        with open(img_path, "wb") as f:
            f.write(resp.read())
    except Exception as e:
        xbmcgui.Dialog().ok(_(32030), str(e))
        return

    addon = _get_addon()
    dialog = _WebAdminDialog("dialog_layout.xml", ADDON_DIR, "Default", "1080i")
    dialog._img_path = img_path
    dialog._local_ip = local_ip
    dialog._username = addon.getSetting("cd2_username") or "-"
    dialog._password = addon.getSetting("cd2_password") or "-"
    dialog.doModal()


def open_clouddrive2():
    """Start CD2 service and enable autostart."""
    svc = SystemctlService(CD2_SERVICE_NAME)
    try:
        svc.ensure_service_file()
        svc.start_service()
        svc.enable_service()
        notification("CloudDrive2", _(32156))
    except Exception as e:
        ok(_(32030), str(e))


def closed_clouddrive2():
    """Stop CD2 service and disable autostart."""
    svc = SystemctlService(CD2_SERVICE_NAME)
    try:
        svc.stop_service()
        svc.disable_service()
        notification("CloudDrive2", _(32157))
    except Exception as e:
        ok(_(32030), str(e))


# ---- Main Entry Point ----

def main_entry_point():
    log("===== CloudDrive2 Plugin START =====")
    log(f"Args: {sys.argv}")

    # Ensure clouddrive binary has execute permission
    _bin = os.path.join(os.path.dirname(os.path.abspath(__file__)), "clouddrive")
    if os.path.exists(_bin) and (os.stat(_bin).st_mode & 0o777) != 0o755:
        try:
            os.chmod(_bin, 0o755)
        except Exception:
            pass

    # Handle RunScript calls (e.g. settings "Clear Token" button)
    # Settings RunScript passes action name directly as sys.argv[1]
    _run_actions = {"clear_token", "clear_all_data"}
    if len(sys.argv) > 1 and sys.argv[1] in _run_actions:
        action = sys.argv[1]
        log(f"RunScript action: {action}")
        if action == "clear_token":
            cd2_utils.clear_token()
            xbmcgui.Dialog().notification("CloudDrive2", "Token cleared")
        elif action == "clear_all_data":
            _clear_all_data()
        return

    handle = int(sys.argv[1])
    params = get_params()
    mode = params.get("mode", MODE_MAIN)
    log(f"Mode: {mode}, Params: {params}")

    # Check service availability first (skip for modes that don't need CD2 running)
    _no_service_modes = {MODE_MAIN, MODE_SERVICE_START, MODE_SERVICE_STOP, MODE_WEB_ADMIN}
    if mode not in _no_service_modes:
        if not cd2_utils.is_service_running():
            ok(_(32032), _(32033))
            xbmcplugin.endOfDirectory(handle)
            return

    # Route to handler
    if mode == MODE_MAIN:
        from resources.lib.cd2_auth import silent_check
        if not silent_check():
            notification("CloudDrive2", _(32011))
        show_main_menu(handle)

    elif mode == MODE_ACCOUNT_CHECK:
        from resources.lib.cd2_auth import check_and_guide
        check_and_guide()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_FILE_BROWSE:
        from resources.lib.cd2_cloud import show_download_browser
        path = params.get("path", None)
        show_download_browser(handle, path)

    elif mode == MODE_DOWNLOAD_FILE:
        path = params.get("path", "")
        name = params.get("name", "")
        if path:
            from resources.lib.cd2_cloud import start_download
            start_download(path, name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_SEARCH:
        from resources.lib.cd2_cloud import show_search
        show_search(handle)

    elif mode == MODE_CLOUD_LIST:
        from resources.lib.cd2_cloud import show_cloud_list
        show_cloud_list(handle)

    elif mode == MODE_CLOUD_ADD:
        from resources.lib.cd2_cloud import show_cloud_add_menu
        show_cloud_add_menu(handle)

    elif mode == MODE_CLOUD_ADD_ALIST:
        from resources.lib.cd2_cloud import add_alist_api
        add_alist_api()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_CLOUD_ADD_SMB:
        from resources.lib.cd2_cloud import show_smb_servers
        show_smb_servers(handle)

    elif mode == MODE_SMB_SHARES:
        server = params.get("server", "")
        if server:
            from resources.lib.cd2_cloud import show_smb_shares
            show_smb_shares(handle, server)
        else:
            xbmcplugin.endOfDirectory(handle)

    elif mode == MODE_SMB_LOGIN:
        server = params.get("server", "")
        share = params.get("share", "")
        user = params.get("user", "")
        password = params.get("password", "")
        workgroup = params.get("workgroup", "")
        if server and share:
            from resources.lib.cd2_cloud import do_login_smb
            do_login_smb(server, share, user, password, workgroup)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_CLOUD_ADD_QR:
        provider = params.get("provider", "")
        if provider:
            from resources.lib.cd2_qrlogin import qr_login_do
            qr_login_do(provider)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_CLOUD_REMOVE:
        cloud_name = params.get("cloud_name", "")
        user_name = params.get("user_name", "")
        log(f"CLOUD_REMOVE: cloud_name={cloud_name}, user_name={user_name}")
        if cloud_name:
            from resources.lib.cd2_cloud import remove_cloud_api
            remove_cloud_api(cloud_name, user_name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_CLOUD_SPACE:
        cloud_name = params.get("cloud_name", "")
        if cloud_name:
            from resources.lib.cd2_cloud import show_cloud_space
            show_cloud_space(cloud_name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_MOUNT_LIST:
        from resources.lib.cd2_mount import show_mount_list
        show_mount_list(handle)

    elif mode == MODE_MOUNT_ADD:
        cloud_name = params.get("cloud_name", "")
        from resources.lib.cd2_mount import add_mount_dialog
        add_mount_dialog(cloud_name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_MOUNT_REMOVE:
        cloud_name = params.get("cloud_name", "")
        from resources.lib.cd2_mount import remove_mount
        remove_mount(cloud_name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_MOUNT_RESTORE:
        from resources.lib.cd2_mount import restore_default_config
        restore_default_config()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_MOUNT_TOGGLE:
        cloud_name = params.get("cloud_name", "")
        from resources.lib.cd2_mount import toggle_mount
        toggle_mount(cloud_name)
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_ACCOUNT_INFO:
        show_account_info(handle)

    elif mode == MODE_WEB_ADMIN:
        show_web_admin()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_SERVICE_START:
        open_clouddrive2()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_SERVICE_STOP:
        closed_clouddrive2()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_CHECK_UPDATE:
        check_update_handler()
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_SETTINGS:
        xbmc.executebuiltin("Addon.OpenSettings(plugin.video.clouddrive2)")
        xbmc.executebuiltin("Container.Refresh")

    elif mode == MODE_PLAY_FILE:
        path = params.get("path", "")
        name = params.get("name", "")
        if path:
            from resources.lib.cd2_cloud import play_file
            play_file(handle, path, name)
        else:
            xbmcplugin.endOfDirectory(handle)

    elif mode == MODE_NOOP:
        xbmcplugin.endOfDirectory(handle)


    log("===== CloudDrive2 Plugin END =====")


if __name__ == "__main__":
    main_entry_point()
