"""
OMNIWEB Desktop - Transform web apps into desktop applications
Author: Juste Elysée MALANDILA

Built on pywebview for native window creation.
"""

import sys
import threading
import time
from typing import Optional, Dict, Any
import uvicorn


class DesktopApp:
    """
    Transform OMNIWEB web app into a desktop application.
    
    Uses pywebview to create a native window that runs your web app.
    
    Example:
        >>> from omniweb import OmniWeb
        >>> from omniweb.desktop import DesktopApp
        >>> 
        >>> app = OmniWeb()
        >>> 
        >>> @app.get("/")
        >>> async def home():
        >>>     return {"message": "Hello Desktop!"}
        >>> 
        >>> if __name__ == "__main__":
        >>>     DesktopApp(app).run()
    """
    
    def __init__(
        self,
        app,
        title: str = "OMNIWEB App",
        width: int = 1200,
        height: int = 800,
        resizable: bool = True,
        fullscreen: bool = False,
        min_size: tuple = (400, 300),
        background_color: str = "#FFFFFF",
        host: str = "127.0.0.1",
        port: int = 8000,
    ):
        """
        Initialize desktop app wrapper.
        
        Args:
            app: OMNIWEB application instance
            title: Window title
            width: Window width in pixels
            height: Window height in pixels
            resizable: Allow window resizing
            fullscreen: Start in fullscreen mode
            min_size: Minimum window size (width, height)
            background_color: Window background color
            host: Server host (use 127.0.0.1 for security)
            port: Server port
        """
        self.app = app
        self.title = title
        self.width = width
        self.height = height
        self.resizable = resizable
        self.fullscreen = fullscreen
        self.min_size = min_size
        self.background_color = background_color
        self.host = host
        self.port = port
        
        # Check if pywebview is available
        try:
            import webview
            self.webview = webview
        except ImportError:
            raise ImportError(
                "pywebview is required for desktop mode. "
                "Install it with: pip install omniweb[desktop]"
            )
    
    def _start_server(self):
        """Start uvicorn server in background thread."""
        config = uvicorn.Config(
            self.app,
            host=self.host,
            port=self.port,
            log_level="warning",
            access_log=False,
        )
        server = uvicorn.Server(config)
        server.run()
    
    def run(
        self,
        debug: bool = False,
        icon: Optional[str] = None,
        on_top: bool = False,
        confirm_close: bool = False,
    ):
        """
        Run the desktop application.
        
        Args:
            debug: Enable debug mode (shows dev tools)
            icon: Path to window icon file
            on_top: Keep window on top of others
            confirm_close: Ask for confirmation before closing
        
        Example:
            >>> DesktopApp(app).run(debug=True, icon="icon.png")
        """
        # Start web server in background thread
        server_thread = threading.Thread(
            target=self._start_server,
            daemon=True
        )
        server_thread.start()
        
        # Wait for server to be ready
        time.sleep(1)
        
        # URL to load
        url = f"http://{self.host}:{self.port}"
        
        print(f"""
╔══════════════════════════════════════════════════════════╗
║                                                          ║
║  🖥️  OMNIWEB DESKTOP MODE                                ║
║                                                          ║
║  Created by: Juste Elysée MALANDILA                     ║
║  App: {self.title:<48}║
║                                                          ║
╚══════════════════════════════════════════════════════════╝

🚀 Starting desktop application...
🌐 Backend: {url}
📏 Window: {self.width}x{self.height}
🔧 Debug: {debug}
        """)
        
        # Create native window
        window = self.webview.create_window(
            title=self.title,
            url=url,
            width=self.width,
            height=self.height,
            resizable=self.resizable,
            fullscreen=self.fullscreen,
            min_size=self.min_size,
            background_color=self.background_color,
            on_top=on_top,
            confirm_close=confirm_close,
        )
        
        # Add icon if provided
        if icon:
            try:
                window.icon = icon
            except Exception as e:
                print(f"⚠️  Could not load icon: {e}")
        
        # Start GUI (this blocks until window is closed)
        self.webview.start(debug=debug)
        
        print("\n👋 Desktop app closed. Goodbye!")


def run_as_desktop(
    app,
    title: Optional[str] = None,
    width: int = 1200,
    height: int = 800,
    **kwargs
):
    """
    Convenience function to run app as desktop.
    
    Example:
        >>> from omniweb import Nexium
        >>> from omniweb.desktop import run_as_desktop
        >>> 
        >>> app = Nexium()
        >>> 
        >>> if __name__ == "__main__":
        >>>     run_as_desktop(app, title="My App")
    """
    if title is None:
        title = getattr(app, "title", "OMNIWEB App")
    
    desktop = DesktopApp(
        app,
        title=title,
        width=width,
        height=height,
        **kwargs
    )
    desktop.run()


class DesktopAPI:
    """
    API for desktop-specific features.
    
    Allows your web app to interact with the desktop window.
    
    Example:
        >>> from omniweb import Nexium
        >>> from omniweb.desktop import DesktopAPI
        >>> 
        >>> app = Nexium()
        >>> desktop_api = DesktopAPI()
        >>> 
        >>> @app.get("/window/minimize")
        >>> async def minimize():
        >>>     desktop_api.minimize()
        >>>     return {"status": "minimized"}
    """
    
    def __init__(self):
        """Initialize desktop API."""
        try:
            import webview
            self.webview = webview
        except ImportError:
            self.webview = None
    
    @property
    def available(self) -> bool:
        """Check if desktop features are available."""
        return self.webview is not None
    
    def get_window(self):
        """Get the active window."""
        if not self.available:
            return None
        try:
            return self.webview.windows[0] if self.webview.windows else None
        except Exception:
            return None
    
    def minimize(self):
        """Minimize the window."""
        window = self.get_window()
        if window:
            window.minimize()
    
    def maximize(self):
        """Maximize the window."""
        window = self.get_window()
        if window:
            window.maximize()
    
    def restore(self):
        """Restore the window."""
        window = self.get_window()
        if window:
            window.restore()
    
    def toggle_fullscreen(self):
        """Toggle fullscreen mode."""
        window = self.get_window()
        if window:
            window.toggle_fullscreen()
    
    def set_title(self, title: str):
        """Set window title."""
        window = self.get_window()
        if window:
            window.set_title(title)
    
    def resize(self, width: int, height: int):
        """Resize window."""
        window = self.get_window()
        if window:
            window.resize(width, height)
    
    def move(self, x: int, y: int):
        """Move window to position."""
        window = self.get_window()
        if window:
            window.move(x, y)
    
    def destroy(self):
        """Close the window."""
        window = self.get_window()
        if window:
            window.destroy()
    
    def evaluate_js(self, script: str) -> Any:
        """
        Execute JavaScript in the window.
        
        Args:
            script: JavaScript code to execute
            
        Returns:
            Result of the JavaScript execution
        """
        window = self.get_window()
        if window:
            return window.evaluate_js(script)
        return None
    
    def load_url(self, url: str):
        """Load a new URL in the window."""
        window = self.get_window()
        if window:
            window.load_url(url)
    
    def load_html(self, html: str):
        """Load HTML content directly."""
        window = self.get_window()
        if window:
            window.load_html(html)
    
    def get_elements(self, selector: str) -> list:
        """Get DOM elements by CSS selector."""
        window = self.get_window()
        if window:
            script = f"document.querySelectorAll('{selector}')"
            return window.evaluate_js(script)
        return []
    
    def show_dialog(
        self,
        dialog_type: str = "open",
        directory: str = "",
        save_filename: str = "",
        file_types: tuple = (),
    ) -> Optional[str]:
        """
        Show file dialog.
        
        Args:
            dialog_type: 'open', 'save', or 'folder'
            directory: Initial directory
            save_filename: Default filename for save dialog
            file_types: Allowed file types
            
        Returns:
            Selected file/folder path or None
        """
        window = self.get_window()
        if not window:
            return None
        
        if dialog_type == "open":
            return window.create_file_dialog(
                self.webview.OPEN_DIALOG,
                directory=directory,
                file_types=file_types,
            )
        elif dialog_type == "save":
            return window.create_file_dialog(
                self.webview.SAVE_DIALOG,
                directory=directory,
                save_filename=save_filename,
                file_types=file_types,
            )
        elif dialog_type == "folder":
            return window.create_file_dialog(
                self.webview.FOLDER_DIALOG,
                directory=directory,
            )
        return None
