"""Interactive configuration wizard and config operations for FWAuto projects.

This module provides:
- Dynamic wizard for project initialization (auto-triggered)
- Edit wizard for existing project configuration
- Config get/set/show operations for /config command
"""

import tomllib
from importlib.resources import files
from pathlib import Path
from typing import Any

import tomli_w
from rich.console import Console
from rich.prompt import IntPrompt, Prompt
from rich.table import Table

console = Console()


def _select_option(
    prompt_text: str,
    options: list[str] | list[tuple[str, str]],
    default: int = 1,
) -> str:
    """
    顯示編號選項，讓使用者用數字選擇。

    Args:
        prompt_text: 提示文字
        options: 選項列表，可以是 list[str] 或 list[tuple[str, str]]
                 tuple 格式為 (選項名, 說明)
        default: 預設選項（1-based）

    Returns:
        選中的選項值
    """
    console.print(f"{prompt_text}:")

    # 處理兩種格式
    option_names = []
    for i, option in enumerate(options, 1):
        if isinstance(option, tuple):
            name, desc = option
            option_names.append(name)
            console.print(f"  {i}. {name}")
            console.print(f"     [dim]{desc}[/dim]")
        else:
            option_names.append(option)
            console.print(f"  {i}. {option}")

    choices = [str(i) for i in range(1, len(options) + 1)]
    choice = IntPrompt.ask("Select", default=default, choices=choices)
    return option_names[choice - 1]


def copy_build_template(project_root: Path) -> None:
    """複製 BUILD_Makefile template 到專案。"""
    template_src = files("fwauto.templates").joinpath("BUILD_Makefile")
    target_dir = project_root / ".fwauto" / "build"
    target_dir.mkdir(parents=True, exist_ok=True)
    target_path = target_dir / "Makefile"

    target_path.write_bytes(template_src.read_bytes())
    console.print(f"[dim]  → Copied template: {target_path}[/dim]")


# ============================================
# Dynamic Wizard Functions (New)
# ============================================


def load_user_config() -> dict[str, Any]:
    """載入 User Config 為 dict（已移除 User Config，總是返回空 dict）"""
    # User Config 已移除，wizard 每次詢問所有項目
    return {}


def get_missing_config_items(user_config: dict) -> list[str]:
    """
    檢查 User Config 缺少哪些必要項目。

    Returns:
        List of missing items: "sdk", "build", "deploy"
    """
    missing = []
    if not user_config.get("sdk", {}).get("path"):
        missing.append("sdk")
    # 檢查 build.type 或 build.script（向後兼容）
    build_config = user_config.get("build", {})
    if not build_config.get("type") and not build_config.get("script"):
        missing.append("build")
    # 檢查 deploy.type 或 deploy.script（向後兼容）
    deploy_config = user_config.get("deploy", {})
    if not deploy_config.get("type") and not deploy_config.get("script"):
        missing.append("deploy")
    return missing


def ensure_project_initialized(project_root: Path | None = None) -> Path | None:
    """
    確保專案已初始化。若 .fwauto/ 不存在則根據 User Config 狀態動態觸發嚮導。

    Args:
        project_root: 專案根目錄（預設為當前目錄）

    Returns:
        Path to project root if project is ready (existing or just created)
        None if user cancelled or wizard failed
    """
    if project_root is None:
        project_root = Path.cwd()

    config_file = project_root / ".fwauto" / "config.toml"

    if config_file.exists():
        return project_root

    # 檢查 User Config 狀態
    user_config = load_user_config()
    missing = get_missing_config_items(user_config)

    if not missing:
        # User Config 完整，直接建立 .fwauto/
        console.print("[green]✓ Using environment defaults from User Config[/green]")
        if create_project_from_user_config(project_root, user_config):
            return project_root
        return None

    # 動態嚮導：只問缺少的項目
    console.print("[yellow]⚠️  FWAuto project not initialized[/yellow]")
    console.print(f"[cyan]🚀 Starting setup wizard ({len(missing)} step(s))...[/cyan]\n")

    if run_dynamic_wizard(project_root, user_config, missing):
        return project_root
    return None


def run_dynamic_wizard(
    project_root: Path,
    user_config: dict,
    missing: list[str],
) -> bool:
    """
    動態嚮導 - 只收集缺少的配置。

    Args:
        project_root: 專案根目錄
        user_config: 現有的 User Config
        missing: 缺少的配置項目列表

    Returns:
        True if successful, False if cancelled
    """
    total_steps = len(missing)
    current_step = 0
    collected: dict[str, Any] = {}

    def _step_header(title: str, description: str = "") -> None:
        nonlocal current_step
        current_step += 1
        console.print(f"\n[bold][{current_step}/{total_steps}] {title}[/bold]")
        if description:
            console.print()
            console.print(f"[dim]{description}[/dim]")
            console.print()

    try:
        # 只問缺少的項目
        if "sdk" in missing:
            _step_header(
                "SDK Configuration",
                "This is the path where the SDK is installed on the host machine.\n"
                "The SDK usually contains the cross-compiler, sysroot, libraries, and\n"
                "environment scripts needed to build the project.\n"
                "If your SDK is installed elsewhere, enter that full path here.",
            )
            sdk_path = Prompt.ask("SDK path", default="/opt/ti-sdk")
            collected["sdk"] = {"path": sdk_path}

        if "build" in missing:
            _step_header(
                "Build Configuration",
                "Select how the project should be built.",
            )
            build_type = _select_option(
                "Build type",
                [
                    ("makefile", "Build using a Makefile (recommended)."),
                    ("command", "Build using a custom shell command."),
                ],
                default=1,
            )
            collected["build"] = {"type": build_type}

            if build_type == "makefile":
                makefile = Prompt.ask("Makefile path", default=".fwauto/build/Makefile")
                target = Prompt.ask("Build target", default="build")
                collected["build"]["makefile"] = makefile
                collected["build"]["target"] = target
                copy_build_template(project_root)
            else:  # command
                command = Prompt.ask("Build command")
                collected["build"]["command"] = command

        if "deploy" in missing:
            _step_header(
                "Deploy Configuration",
                "Choose how the built output will be deployed to the target board.",
            )
            deploy_type = _select_option(
                "Deploy type",
                [
                    ("network", "Deploy via SSH/SCP over network (recommended)."),
                    ("serial", "Deploy via serial connection."),
                    ("command", "Use a custom deployment command."),
                ],
                default=1,
            )
            collected["deploy"] = {"type": deploy_type}

            if deploy_type == "network":
                board_ip = Prompt.ask("Board IP", default="192.168.50.169")
                board_user = Prompt.ask("Board user", default="root")
                deploy_path = Prompt.ask("Deploy path", default="/home/root")
                collected["deployment"] = {
                    "board_ip": board_ip,
                    "board_user": board_user,
                    "deploy_path": deploy_path,
                }
                # 使用 delegation script，不需要複製
            elif deploy_type == "serial":
                port = Prompt.ask("Serial port", default="/dev/ttyUSB0")
                collected["deployment"] = {"port": port}
            else:  # command
                command = Prompt.ask("Deploy command")
                collected["deploy"]["command"] = command

    except (KeyboardInterrupt, EOFError):
        console.print("\n[yellow]⚠️  Setup cancelled[/yellow]")
        return False

    # 合併 User Config + 收集的配置
    return create_project_config(project_root, user_config, collected)


def create_project_from_user_config(project_root: Path, user_config: dict) -> bool:
    """
    從 User Config 直接建立專案（0 步驟）。

    Args:
        project_root: 專案根目錄
        user_config: User Config dict

    Returns:
        True if successful
    """
    console.print("[dim]Creating .fwauto/ from environment defaults...[/dim]")

    # 若 build.type == makefile，複製 template
    build_type = user_config.get("build", {}).get("type", "makefile")
    if build_type == "makefile":
        copy_build_template(project_root)

    return create_project_config(project_root, user_config, {})


def create_project_config(
    project_root: Path,
    user_config: dict,
    collected: dict,
) -> bool:
    """
    建立專案配置，合併 User Config 和收集的配置。

    優先順序：collected > user_config > default

    Args:
        project_root: 專案根目錄
        user_config: User Config dict
        collected: 嚮導收集的配置

    Returns:
        True if successful
    """
    # 建立 .fwauto 目錄
    fwauto_dir = project_root / ".fwauto"
    fwauto_dir.mkdir(exist_ok=True)
    (fwauto_dir / "logs").mkdir(exist_ok=True)

    # 合併配置
    project = user_config.get("project", {})
    sdk = collected.get("sdk") or user_config.get("sdk", {})
    build = collected.get("build") or user_config.get("build", {})
    deploy = collected.get("deploy") or user_config.get("deploy", {})

    # deployment 區塊特殊處理：過濾舊的巢狀結構（如 deployment.am62x）
    # 只取非 dict 的值，與 ProjectConfig.deployment_config 行為一致
    if collected.get("deployment"):
        deployment = collected["deployment"]
    else:
        user_deployment = user_config.get("deployment", {})
        deployment = {k: v for k, v in user_deployment.items() if not isinstance(v, dict)}

    # 構建 build 區塊：只有 makefile type 才需要 target
    build_config = {**build}
    if build.get("type") == "makefile":
        build_config["target"] = build.get("target", "build")

    project_config_data = {
        "project": {
            "name": project_root.name,
            "language": project.get("language", "en"),
        },
        "sdk": sdk,
        "build": build_config,
        "deploy": deploy,
    }

    # 只有當 deployment 有內容時才加入
    if deployment:
        project_config_data["deployment"] = deployment

    # 寫入 config.toml
    config_path = fwauto_dir / "config.toml"
    with open(config_path, "wb") as f:
        tomli_w.dump(project_config_data, f)

    console.print(f"\n[green]✓ Project config created: {config_path}[/green]")
    console.print("\n[bold green]✅ Initialization complete![/bold green]")
    console.print("\n[bold]Project structure:[/bold]")
    console.print("  .fwauto/")
    console.print("    ├── config.toml")
    console.print("    └── logs/")

    return True


def _wizard_step_log(console: Console) -> dict:
    """Log 配置 wizard 步驟"""
    console.print("\n[bold cyan]📊 Log Configuration[/bold cyan]")

    log_type = _select_option("Log type", ["file", "network", "serial"], default=1)

    result: dict[str, Any] = {"log": {"type": log_type}}

    if log_type == "file":
        path = Prompt.ask("Log file path", default="./app.log")
        result["log"]["path"] = path

    elif log_type == "network":
        remote = Prompt.ask(
            "Remote log path (user@host:path)",
            default="root@192.168.50.169:/var/log/app.log",
        )
        result["log"]["remote_path"] = remote

    elif log_type == "serial":
        port = Prompt.ask("Serial port", default="/dev/ttyUSB0")
        baudrate = Prompt.ask("Baud rate", default="115200")
        result["log"]["serial_port"] = port
        result["log"]["baudrate"] = int(baudrate)

    return result


def run_log_wizard(config_path: Path) -> bool:
    """
    執行獨立的 log wizard，回傳是否完成

    Args:
        config_path: 專案 config.toml 路徑

    Returns:
        True if completed, False if cancelled
    """
    import tomllib

    console.print("\n[yellow]⚠️ Log not configured[/yellow]")
    console.print("[dim]Starting log setup wizard...[/dim]\n")

    try:
        log_config = _wizard_step_log(console)

        # 讀取現有配置
        if config_path.exists():
            with open(config_path, "rb") as f:
                config_data = tomllib.load(f)
        else:
            config_data = {}

        # 合併 log 配置
        config_data["log"] = log_config["log"]

        # 寫回檔案
        with open(config_path, "wb") as f:
            tomli_w.dump(config_data, f)

        console.print("\n[green]✅ Log configuration saved![/green]")
        return True

    except (KeyboardInterrupt, EOFError):
        console.print("\n[yellow]⚠️ Setup cancelled[/yellow]")
        return False


def run_edit_wizard(project_root: Path) -> bool:
    """
    互動式編輯現有專案配置。

    Args:
        project_root: 專案根目錄

    Returns:
        True if changes were made, False otherwise
    """
    from ..config import load_project_config

    config = load_project_config(project_root)

    # 顯示現有配置摘要
    console.print("[bold]=== Current Configuration ===[/bold]\n")
    console.print(f"  Project Name: [cyan]{config.project_name}[/cyan]")
    console.print(f"  Language: [cyan]{config.project_language}[/cyan]")
    console.print(f"  SDK Path: [cyan]{config.sdk_path or '(not set)'}[/cyan]")
    console.print(f"  Build Script: [cyan]{config.build_script}[/cyan]")
    console.print(f"  Deploy Script: [cyan]{config.deploy_script}[/cyan]")

    # 選擇要修改的項目
    console.print("\n[bold]=== Select item to edit ===[/bold]")
    console.print("  1. Project Settings (name, language)")
    console.print("  2. SDK Configuration (path)")
    console.print("  3. Build Configuration")
    console.print("  4. Deploy Configuration")
    console.print("  0. Exit")

    try:
        choice = IntPrompt.ask("\nSelect", choices=["0", "1", "2", "3", "4"])
    except (KeyboardInterrupt, EOFError):
        console.print("\n[dim]Cancelled[/dim]")
        return False

    if choice == 0:
        console.print("[dim]No changes made[/dim]")
        return False

    # TODO: 實作各項目的編輯邏輯
    console.print("[yellow]⚠️  Edit functionality coming soon...[/yellow]")
    return False


# ============================================
# Config Operations (get/set/show)
# ============================================


def _parse_key(key: str) -> tuple[str, str]:
    """Parse 'section.key' format into (section, key) tuple.

    Args:
        key: Key in 'section.key' format (e.g., 'build.type')

    Returns:
        Tuple of (section, key)

    Raises:
        ValueError: If key format is invalid
    """
    parts = key.split(".")
    if len(parts) != 2 or not parts[0] or not parts[1]:
        raise ValueError(f"Invalid key format: '{key}'. Expected 'section.key' (e.g., 'build.type')")
    return parts[0], parts[1]


def _infer_type(value: str) -> str | int | bool:
    """Infer Python type from string value.

    - Pure digits → int
    - 'true'/'false' (case-insensitive) → bool
    - Otherwise → str

    Args:
        value: String value to convert

    Returns:
        Converted value with inferred type
    """
    if value.isdigit():
        return int(value)
    if value.lower() == "true":
        return True
    if value.lower() == "false":
        return False
    return value


def config_get(key: str, config_path: Path) -> tuple[str, Any]:
    """Get a config value by key.

    Args:
        key: Key in 'section.key' format
        config_path: Path to config.toml

    Returns:
        Tuple of (key, value). Value is None if key not found.
    """
    section, subkey = _parse_key(key)

    with open(config_path, "rb") as f:
        data = tomllib.load(f)

    value = data.get(section, {}).get(subkey)
    return key, value


def config_set(key: str, value: str, config_path: Path) -> None:
    """Set a config value.

    Uses read-modify-write pattern (same as update_last_log_path).

    Args:
        key: Key in 'section.key' format
        value: String value (type will be inferred)
        config_path: Path to config.toml
    """
    section, subkey = _parse_key(key)
    typed_value = _infer_type(value)

    # Read existing config
    if config_path.exists():
        with open(config_path, "rb") as f:
            data = tomllib.load(f)
    else:
        data = {}

    # Ensure section exists
    if section not in data:
        data[section] = {}

    # Set value
    data[section][subkey] = typed_value

    # Write back
    with open(config_path, "wb") as f:
        tomli_w.dump(data, f)


def config_show(config_path: Path) -> None:
    """Display all config values in grouped Rich tables.

    Args:
        config_path: Path to config.toml
    """
    from rich.panel import Panel

    if not config_path.exists():
        console.print("[red]Config file not found[/red]")
        return

    with open(config_path, "rb") as f:
        data = tomllib.load(f)

    if not data:
        console.print("[yellow]Configuration is empty[/yellow]")
        return

    console.print(f"\n[bold]⚙️ FWAuto Configuration[/bold] [dim]({config_path})[/dim]\n")

    for section_name, section_data in data.items():
        if not isinstance(section_data, dict):
            continue

        table = Table(
            show_header=False,
            box=None,
            padding=(0, 1),
            expand=True,
        )
        table.add_column("Key", ratio=2)
        table.add_column("Value", ratio=3)

        for key, value in section_data.items():
            display_value = str(value) if value is not None else "[dim](not set)[/dim]"
            table.add_row(
                f"[dim]{section_name}.{key}[/dim]",
                display_value,
            )

        panel = Panel(
            table,
            title=f"[bold]{section_name.capitalize()}[/bold]",
            title_align="left",
            border_style="cyan",
            padding=(0, 1),
        )
        console.print(panel)

    console.print("\n[dim]Tip: /config get <key> | /config set <key> <value>[/dim]")
