"""Flet application entry point — Material Design 3 dark theme with navigation rail."""

from __future__ import annotations

import json
import os
import threading
import urllib.request

import flet as ft

# ---------------------------------------------------------------------------
# Theme colours (matching overlay palette)
# ---------------------------------------------------------------------------
TEAL = "#4ec9b0"
ERROR_RED = "#f14c4c"
SURFACE = "#1e1e1e"
BG = "#0d0d0d"


def _poll_daemon_loop(port: int, callback):
    """Poll /health every 3s and call callback(running, info_dict)."""
    while True:
        try:
            req = urllib.request.Request(f"http://127.0.0.1:{port}/health")
            with urllib.request.urlopen(req, timeout=1) as resp:
                data = json.loads(resp.read().decode())
            # Also fetch interview-info for richer status
            try:
                req2 = urllib.request.Request(f"http://127.0.0.1:{port}/interview-info")
                with urllib.request.urlopen(req2, timeout=1) as resp2:
                    info = json.loads(resp2.read().decode())
            except Exception:
                info = {}
            callback(True, info)
        except Exception:
            callback(False, {})
        threading.Event().wait(3)


def run_flet_gui(saved_config: dict) -> None:
    """Launch the Flet-based GUI."""
    # Hide the Python backend from the dock — only the Flet window should show
    try:
        from AppKit import NSApplication, NSApplicationActivationPolicyAccessory
        NSApplication.sharedApplication().setActivationPolicy_(NSApplicationActivationPolicyAccessory)
    except Exception:
        pass

    # Brand the Flet desktop client with our app name.
    # Copy Flet's .app, patch CFBundleName, set FLET_VIEW_PATH.
    # Note: dock icon can't be changed (compiled into Flutter binary).
    # See .work/flet-dock-icon-research.md for details.
    try:
        from pathlib import Path
        import shutil
        import subprocess as _sp

        branded_dir = Path.home() / ".ai-interview" / "flet-client"

        for flet_src in sorted(Path.home().glob(".flet/client/*/Flet.app"), reverse=True):
            branded_app = branded_dir / "AI Interview Assistant.app"
            src_version = flet_src.parent.name

            version_marker = branded_dir / ".version"
            if not branded_app.exists() or not version_marker.exists() or version_marker.read_text().strip() != src_version:
                for old in branded_dir.glob("*.app"):
                    shutil.rmtree(old)
                branded_dir.mkdir(parents=True, exist_ok=True)
                shutil.copytree(str(flet_src), str(branded_app))
                version_marker.write_text(src_version)

                plist = branded_app / "Contents" / "Info.plist"
                if plist.exists():
                    for key, val in [
                        ("CFBundleName", "AI Interview Assistant"),
                        ("CFBundleDisplayName", "AI Interview Assistant"),
                        ("NSLocalNetworkUsageDescription", "AI Interview Assistant needs local network access to connect to Ollama and Whisper servers."),
                    ]:
                        _sp.run(["/usr/libexec/PlistBuddy", "-c", f"Set :{key} '{val}'", str(plist)], capture_output=True)
                        _sp.run(["/usr/libexec/PlistBuddy", "-c", f"Add :{key} string '{val}'", str(plist)], capture_output=True)

                    # Add Bonjour services for local network discovery
                    _sp.run(["/usr/libexec/PlistBuddy", "-c", "Add :NSBonjourServices array", str(plist)], capture_output=True)
                    _sp.run(["/usr/libexec/PlistBuddy", "-c", "Add :NSBonjourServices:0 string '_http._tcp'", str(plist)], capture_output=True)

                    # Re-sign so macOS accepts the plist changes
                    _sp.run(["codesign", "--force", "--deep", "--sign", "-", str(branded_app)], capture_output=True)

            os.environ["FLET_VIEW_PATH"] = str(branded_dir)
            break
    except Exception:
        pass

    def main(page: ft.Page):
        from ai_interview.i18n import t
        page.title = t("app_title")

        theme_pref = saved_config.get("gui_theme", "system")
        _THEME_MAP = {"dark": ft.ThemeMode.DARK, "light": ft.ThemeMode.LIGHT, "system": ft.ThemeMode.SYSTEM}
        page.theme_mode = _THEME_MAP.get(theme_pref, ft.ThemeMode.SYSTEM)

        page.theme = ft.Theme(color_scheme_seed=TEAL)
        page.dark_theme = ft.Theme(
            color_scheme_seed=TEAL,
            color_scheme=ft.ColorScheme(
                primary=TEAL,
                on_primary="#ffffff",
                surface=SURFACE,
                on_surface="#cccccc",
                error=ERROR_RED,
            ),
        )
        page.window.width = 1100
        page.window.height = 1000
        page.window.min_width = 900
        page.window.min_height = 800

        page.window.wait_until_ready_to_show = True
        try:
            from AppKit import NSScreen
            f = NSScreen.mainScreen().frame()
            sw, sh = int(f.size.width), int(f.size.height)
            page.window.top = (sh - 1000) // 2
            page.window.left = (sw - 1100) // 2
        except Exception:
            pass
        page.padding = 0

        build_page(page, saved_config)

    ft.app(target=main)


def build_page(page: ft.Page, saved_config: dict) -> None:
    """Build all screens and navigation. Can be called again to rebuild on language change."""
    from ai_interview.i18n import t
    page.controls.clear()

    from ai_interview.flet_gui.screens import DashboardScreen, HotkeysScreen, SettingsScreen

    dashboard = DashboardScreen(page, saved_config)
    hotkeys_screen = HotkeysScreen(page, saved_config)
    settings_screen = SettingsScreen(page, saved_config)

    screens = [dashboard, hotkeys_screen, settings_screen]
    content_area = ft.Container(content=screens[0], expand=True, padding=0)

    # --- Status indicator ---
    status_icon = ft.Icon(ft.Icons.CIRCLE, color="#5a5a5a", size=12)
    status_text = ft.Text(t("stopped"), size=11, color="#808080")

    def on_status(running: bool, info: dict):
            if running:
                status_icon.color = TEAL
                status_text.value = t("running")
                status_text.color = TEAL
            else:
                status_icon.color = "#5a5a5a"
                status_text.value = t("stopped")
                status_text.color = "#808080"

            dashboard.update_status(running, info)
            hotkeys_screen.update_session_state(running)
            settings_screen.update_session_state(running)
            try:
                page.update()
            except Exception:
                pass

    port = int(saved_config.get("port", 7890))
    page.run_thread(_poll_daemon_loop, port, on_status)

    # --- Navigation rail ---
    def on_nav_change(e):
            idx = e.control.selected_index
            content_area.content = screens[idx]
            if hasattr(screens[idx], "on_activate"):
                screens[idx].on_activate()
            page.update()

    rail = ft.NavigationRail(
            selected_index=0,
            label_type=ft.NavigationRailLabelType.ALL,
            bgcolor=ft.Colors.SURFACE,
            min_width=130,
            min_extended_width=200,
            expand=True,
            destinations=[
                ft.NavigationRailDestination(
                    icon=ft.Icons.DASHBOARD_OUTLINED,
                    selected_icon=ft.Icons.DASHBOARD,
                    label=t("dashboard"),
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.KEYBOARD_OUTLINED,
                    selected_icon=ft.Icons.KEYBOARD,
                    label=t("hotkeys"),
                ),
                ft.NavigationRailDestination(
                    icon=ft.Icons.SETTINGS_OUTLINED,
                    selected_icon=ft.Icons.SETTINGS,
                    label=t("settings"),
                ),
            ],
            on_change=on_nav_change,
    )

    sidebar = ft.Container(
            content=ft.Column(
                [
                    rail,
                    ft.Container(
                        content=ft.Row(
                            [status_icon, status_text],
                            spacing=6,
                            alignment=ft.MainAxisAlignment.CENTER,
                        ),
                        padding=ft.padding.only(bottom=16, top=8),
                    ),
                ],
                spacing=0,
                expand=True,
            ),
            width=130,
            bgcolor=ft.Colors.SURFACE,
    )

    page.add(
    ft.Row(
            [sidebar, ft.VerticalDivider(width=1), content_area],
            expand=True,
            spacing=0,
    )
    )
    page.update()
