from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional

from .themes import ThemeManager
from .config import ConfigManager
from .shortcuts import ShortcutManager
from .table import TableModel
from .voice import VoiceCommand
from .plugins import EventBus, PluginManager, WidgetRegistry
from .assistant.manager import AssistantManager


@dataclass
class Widget:
    kind: str
    title: str
    data: Dict[str, Any] = field(default_factory=dict)

class Section:
    def __init__(self, title: str):
        self.title = title
        self.widgets: List[Widget] = []
        self.subtabs: List[Tab] = []

    def add_text(self, text: str):
        return self.add_paragraph("Text", text)

    def add_paragraph(self, title: str, text: str):
        w = Widget("paragraph", title, {"text": text})
        self.widgets.append(w)
        return w

    def add_divider(self, title: str = ""):
        w = Widget("divider", title or "Divider", {})
        self.widgets.append(w)
        return w

    def add_badge(self, title: str, value: str, tone: str = "info"):
        w = Widget("badge", title, {"value": value, "tone": tone})
        self.widgets.append(w)
        return w

    def add_progress(self, title: str, value: int = 0):
        w = Widget("progress", title, {"value": max(0, min(100, int(value)))})
        self.widgets.append(w)
        return w

    def add_stat(self, title: str, value: str, tone: str = "info"):
        w = Widget("stat", title, {"value": value, "tone": tone})
        self.widgets.append(w)
        return w

    def add_key_value(self, key: str, value: str):
        w = Widget("key_value", key, {"value": value})
        self.widgets.append(w)
        return w

    def add_button(self, title: str, callback: Optional[Callable[[], Any]] = None, hotkey: Optional[str] = None, close_on_press: bool = False):
        w = Widget("button", title, {"callback": callback, "hotkey": hotkey, "close_on_press": close_on_press})
        self.widgets.append(w)
        return w

    def add_toggle(self, title: str, default: bool = False):
        w = Widget("toggle", title, {"value": default})
        self.widgets.append(w)
        return w

    def add_input(self, title: str, placeholder: str = "", required: bool = False, input_type: str = "text", multiline: bool = False):
        w = Widget("input", title, {"placeholder": placeholder, "required": required, "input_type": input_type, "multiline": multiline})
        self.widgets.append(w)
        return w

    def add_select(self, title: str, options: List[str], default=None, callback=None):
        w = Widget("select", title, {"options": list(options), "value": default, "callback": callback})
        self.widgets.append(w)
        return w

    def add_multi_select(self, title: str, options: List[str], default=None):
        w = Widget("multi_select", title, {"options": list(options), "value": list(default or [])})
        self.widgets.append(w)
        return w

    def add_list(self, title: str, items: List[str]):
        w = Widget("list", title, {"items": list(items)})
        self.widgets.append(w)
        return w

    def add_tree(self, title: str, tree: Dict[str, Any]):
        w = Widget("tree", title, {"tree": tree})
        self.widgets.append(w)
        return w

    def add_table(self, title: str, columns: List[str], rows: List[List[Any]], searchable: bool = False, editable: bool = False, paginated: bool = True):
        model = TableModel(columns, rows)
        w = Widget("table", title, {
            "model": model,
            "searchable": searchable,
            "editable": editable,
            "paginated": paginated,
        })
        self.widgets.append(w)
        return w

    def add_json_viewer(self, title: str, data: Any):
        w = Widget("json", title, {"data": data})
        self.widgets.append(w)
        return w

    def add_log_viewer(self, title: str):
        w = Widget("logs", title, {"entries": []})
        self.widgets.append(w)
        return w

    def add_terminal_output(self, title: str):
        class TerminalBuffer:
            def __init__(self):
                self.lines = []
            def write(self, text):
                self.lines.append(str(text))
        buf = TerminalBuffer()
        w = Widget("terminal", title, {"buffer": buf})
        self.widgets.append(w)
        return buf

    def add_file_picker(self, title: str, path="."):
        w = Widget("file_picker", title, {"path": path})
        self.widgets.append(w)
        return w

    def add_clock(self, title: str = "Clock"):
        w = Widget("clock", title, {})
        self.widgets.append(w)
        return w

    def add_context_menu(self, title: str, actions: Dict[str, Callable]):
        w = Widget("context_menu", title, {"actions": actions})
        self.widgets.append(w)
        return w

    def add_command_palette(self, title: str, commands: Dict[str, Callable]):
        w = Widget("command_palette", title, {"commands": commands})
        self.widgets.append(w)
        return w

    def add_voice_command(self, title: str, mode="hybrid", command_callback=None, free_callback=None, fuzzy_threshold=0.72):
        vc = VoiceCommand(mode=mode, command_callback=command_callback, free_callback=free_callback, fuzzy_threshold=fuzzy_threshold)
        w = Widget("voice", title, {"voice": vc})
        self.widgets.append(w)
        return vc

    def create_tab(self, title: str):
        tab = Tab(title)
        self.subtabs.append(tab)
        return tab

    def render(self):
        lines = [f"## {self.title}"]
        for widget in self.widgets:
            kind = widget.kind
            data = widget.data
            if kind == "paragraph":
                lines.append(f"✨ {widget.title}: {data['text']}")
            elif kind == "divider":
                lines.append("─" * 42)
            elif kind == "badge":
                lines.append(f"🏷️ {widget.title}: {data['value']} [{data['tone']}]")
            elif kind == "progress":
                bars = int(data['value'] / 10)
                lines.append(f"📈 {widget.title}: [{'#' * bars}{'.' * (10-bars)}] {data['value']}%")
            elif kind == "stat":
                lines.append(f"📊 {widget.title}: {data['value']} [{data['tone']}]")
            elif kind == "key_value":
                lines.append(f"🔑 {widget.title}: {data['value']}")
            elif kind == "button":
                suffix = f" (hotkey: {data['hotkey']})" if data.get("hotkey") else ""
                lines.append(f"🔘 {widget.title}{suffix}")
            elif kind == "toggle":
                lines.append(f"🧷 {widget.title}: {data['value']}")
            elif kind == "input":
                lines.append(f"⌨️ {widget.title} <{data['input_type']}>")
            elif kind == "select":
                lines.append(f"🧭 {widget.title}: {data.get('value')}")
            elif kind == "multi_select":
                lines.append(f"✅ {widget.title}: {', '.join(map(str, data.get('value', [])))}")
            elif kind == "list":
                lines.append(f"📋 {widget.title}: {len(data['items'])} item(s)")
            elif kind == "tree":
                lines.append(f"🌲 {widget.title}")
            elif kind == "table":
                model = data["model"]
                lines.append(f"🗂️ {widget.title}: {len(model.rows)} row(s), columns={model.columns}")
            elif kind == "json":
                lines.append(f"🧾 {widget.title}: JSON ready")
            elif kind == "logs":
                lines.append(f"🪵 {widget.title}: {len(data['entries'])} entry(s)")
            elif kind == "terminal":
                lines.append(f"🖥️ {widget.title}: {len(data['buffer'].lines)} line(s)")
            elif kind == "file_picker":
                lines.append(f"📁 {widget.title}: {data['path']}")
            elif kind == "clock":
                lines.append(f"🕒 {widget.title}")
            elif kind == "context_menu":
                lines.append(f"📌 {widget.title}: {len(data['actions'])} action(s)")
            elif kind == "command_palette":
                lines.append(f"⚡ {widget.title}: {len(data['commands'])} command(s)")
            elif kind == "voice":
                lines.append(f"🎤 {widget.title}")
            else:
                lines.append(f"• {widget.title}")
        for tab in self.subtabs:
            lines.append("")
            lines.append(tab.render())
        return "\n".join(lines)

class Tab:
    def __init__(self, title: str):
        self.title = title
        self.sections: List[Section] = []

    def create_section(self, title: str):
        section = Section(title)
        self.sections.append(section)
        return section

    def create_tab(self, title: str):
        nested = Section(self.title)
        return nested.create_tab(title)

    def render(self):
        lines = [f"# Tab: {self.title}"]
        for section in self.sections:
            lines.append(section.render())
            lines.append("")
        return "\n".join(lines).rstrip()

class Window:
    def __init__(self, title: str, subtitle: str = "", theme="aurora", icon_pack="emoji"):
        self.title = title
        self.subtitle = subtitle
        self.theme_manager = ThemeManager(theme)
        self.icon_pack = icon_pack
        self.sections: List[Section] = []
        self.tabs: List[Tab] = []
        self.logs: List[tuple[str, str]] = []
        self.notifications: List[str] = []
        self.event_bus = EventBus()
        self.plugin_manager = PluginManager(self.event_bus)
        self.widget_registry = WidgetRegistry()
        self.shortcuts = ShortcutManager()
        self.config = ConfigManager()
        self.assistant = AssistantManager()

    def set_theme(self, name: str):
        return self.theme_manager.set_theme(name)

    def set_icon_pack(self, name: str):
        self.icon_pack = name
        return self.icon_pack

    def create_section(self, title: str):
        section = Section(title)
        self.sections.append(section)
        return section

    def create_tab(self, title: str):
        tab = Tab(title)
        self.tabs.append(tab)
        return tab

    def notify(self, text: str):
        self.notifications.append(text)

    def modal(self, title: str, message: str):
        self.notify(f"[Modal] {title}: {message}")
        return {"title": title, "message": message}

    def confirm(self, message: str, callback=None):
        result = {"confirmed": True, "message": message}
        if callback:
            callback()
        self.notify(f"[Confirm] {message}")
        return result

    def register_command(self, name, callback):
        self.config.set(f"command::{name}", True)
        self.event_bus.on(f"command::{name}", callback)

    def execute_command(self, name, *args, **kwargs):
        return self.event_bus.emit(f"command::{name}", *args, **kwargs)

    def log(self, *args):
        if len(args) == 1:
            level, message = "INFO", args[0]
        elif len(args) >= 2:
            level, message = args[0], args[1]
        else:
            level, message = "INFO", ""
        self.logs.append((str(level), str(message)))
        return self.logs[-1]

    def save_state(self, path="nest_ui.state.json"):
        data = {
            "title": self.title,
            "subtitle": self.subtitle,
            "theme": self.theme_manager.current,
            "icon_pack": self.icon_pack,
            "logs": self.logs,
            "notifications": self.notifications,
            "tabs": [tab.title for tab in self.tabs],
            "sections": [section.title for section in self.sections],
        }
        import json
        with open(path, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        return path

    def load_state(self, path="nest_ui.state.json"):
        import json
        with open(path, "r", encoding="utf-8") as f:
            data = json.load(f)
        self.set_theme(data.get("theme", "aurora"))
        self.icon_pack = data.get("icon_pack", "emoji")
        self.logs = [tuple(x) for x in data.get("logs", [])]
        self.notifications = data.get("notifications", [])
        return data

    def render(self):
        lines = [f"╔═ {self.title} ═╗"]
        if self.subtitle:
            lines.append(self.subtitle)
        lines.append(f"Theme: {self.theme_manager.current} | Icons: {self.icon_pack}")
        if self.notifications:
            lines.append("")
            lines.append("Notifications:")
            for item in self.notifications[-5:]:
                lines.append(f"• {item}")
        if self.logs:
            lines.append("")
            lines.append("Logs:")
            for level, message in self.logs[-8:]:
                lines.append(f"[{level}] {message}")
        for section in self.sections:
            lines.append("")
            lines.append(section.render())
        for tab in self.tabs:
            lines.append("")
            lines.append(tab.render())
        return "\n".join(lines)

    def run(self):
        print(self.render())

class App:
    def __init__(self, theme="aurora", icon_pack="emoji"):
        self.theme = theme
        self.icon_pack = icon_pack

    def create_window(self, title: str, subtitle: str = ""):
        return Window(title, subtitle, theme=self.theme, icon_pack=self.icon_pack)

def main():
    app = App()
    window = app.create_window("Nest UI", "Result Version")
    section = window.create_section("Overview")
    section.add_stat("Status", "Ready", tone="success")
    section.add_paragraph("Message", "Nest UI is installed correctly.")
    window.run()
