"""Modern CLI using Typer framework."""

import sys
from pathlib import Path

import typer
from rich.console import Console

from fwauto.cli_commands.init import run_init_wizard
from fwauto.graph import create_firmware_graph
from fwauto.state import FirmwareState

# Create Typer app
app = typer.Typer(
    name="fwauto",
    help="🚀 STM32 Firmware Automation Tool with AI",
    add_completion=False,
    pretty_exceptions_enable=False,
)

# Auth sub-commands
auth_app = typer.Typer(help="🔐 Authentication commands")
app.add_typer(auth_app, name="auth")

console = Console()


# ============================================================
# Auth Commands
# ============================================================

@auth_app.command(name="login")
def auth_login(
    dev: bool = typer.Option(False, "--dev", help="Use development mode (skip Google OAuth)"),
):
    """
    🔐 Login to FWAuto usage tracking server.

    Examples:
        fwauto auth login          # Google OAuth login
        fwauto auth login --dev    # Development mode (no OAuth)
    """
    from .auth import get_auth_manager

    auth = get_auth_manager()
    success = auth.ensure_authenticated(use_dev_login=dev)

    if success:
        console.print("[green]✅ 登入成功[/green]")
    else:
        console.print("[red]❌ 登入失敗[/red]")
        raise typer.Exit(1)


@auth_app.command(name="logout")
def auth_logout():
    """
    🚪 Logout from FWAuto usage tracking server.

    Example:
        fwauto auth logout
    """
    from .auth import get_auth_manager

    auth = get_auth_manager()
    auth.logout()


@auth_app.command(name="status")
def auth_status():
    """
    📋 Show current authentication status.

    Example:
        fwauto auth status
    """
    from .auth import cli_status

    cli_status()


@app.command(name="dashboard")
def dashboard_cmd(
    open_browser: bool = typer.Option(False, "--open", "-o", help="Open dashboard in browser"),
):
    """
    🌐 Show or open FWAuto Dashboard.

    Examples:
        fwauto dashboard          # Show dashboard URL
        fwauto dashboard --open   # Open in browser
    """
    import webbrowser
    from .auth import FWAUTO_SERVER_URL

    dashboard_url = f"{FWAUTO_SERVER_URL}/dashboard"

    console.print()
    console.print("🌐 FWAuto Dashboard")
    console.print("=" * 50)
    console.print(f"   URL: {dashboard_url}")
    console.print()

    if open_browser:
        console.print("[dim]正在開啟瀏覽器...[/dim]")
        webbrowser.open(dashboard_url)
    else:
        console.print("[dim]提示：使用 --open 或 -o 可直接開啟瀏覽器[/dim]")
    console.print()


def _ensure_claude_code_installed() -> bool:
    """
    確保 Claude Code CLI 已安裝。

    Returns True if installed, False otherwise.
    """
    from .claude_code_installer import is_claude_code_installed, ensure_claude_code_installed

    if is_claude_code_installed():
        return True

    # 需要安裝
    return ensure_claude_code_installed(auto_install=True)


def _ensure_authenticated() -> bool:
    """
    Ensure user is authenticated before running AI commands.

    Returns True if authenticated, False otherwise.
    """
    from .auth import get_auth_manager

    auth = get_auth_manager()

    # 嘗試載入已有的 token
    if auth._load_config() and auth._verify_token():
        return True

    # 需要登入
    console.print("[yellow]⚠️  尚未登入，需要先登入才能使用 AI 功能[/yellow]")
    console.print()

    # 詢問是否要登入
    try:
        do_login = typer.confirm("是否現在登入？", default=True)
        if do_login:
            return auth.ensure_authenticated(use_dev_login=False)
        else:
            console.print("[dim]提示：執行 'fwauto auth login' 進行登入[/dim]")
            return False
    except (KeyboardInterrupt, EOFError):
        console.print("\n[yellow]已取消[/yellow]")
        return False


def _ensure_ai_ready() -> bool:
    """
    確保 AI 功能所需的所有前置條件。

    檢查：
    1. Claude Code CLI 已安裝
    2. 用戶已登入

    Returns True if ready, False otherwise.
    """
    # 1. 檢查 Claude Code CLI
    if not _ensure_claude_code_installed():
        return False

    # 2. 檢查登入狀態
    if not _ensure_authenticated():
        return False

    return True


def _get_auth_status() -> str:
    """Get authentication status for display."""
    from .auth import get_user_token, AUTH_CONFIG_FILE
    import json

    token = get_user_token()
    if not token:
        return "❌ 未登入"

    # Try to get email from config
    try:
        if AUTH_CONFIG_FILE.exists():
            with open(AUTH_CONFIG_FILE, 'r', encoding='utf-8') as f:
                config = json.load(f)
                email = config.get('email', '')
                if email:
                    return f"✅ {email}"
    except Exception:
        pass

    return "✅ 已登入"


def _get_help_info() -> str:
    """Generate help information string.

    Returns formatted help text including:
    - Version
    - Available commands
    - Environment info (Python, platform, project path)
    - Auth status
    """
    import platform
    from importlib.metadata import version

    from .config import find_project_root
    from .auth import FWAUTO_SERVER_URL

    # Get version
    try:
        ver = version("fwauto")
    except Exception:
        ver = "unknown"

    # Get project root
    project_root = find_project_root()
    project_path = str(project_root) if project_root else "不在專案目錄中"

    # Get auth status
    auth_status = _get_auth_status()

    # Build help text
    help_text = f"""🚀 FWAuto v{ver}

📋 支援的指令：
  build       🔨 Build firmware project
  deploy      📥 Deploy firmware to device
  run         ⚡ Run build and deploy
  log         📊 Analyze UART log files
  feat        🚀 AI-assisted feature implementation
  rag         📚 RAG document search and AI query
  chat        💬 Chat with AI
  init        🚀 Initialize new project
  dashboard   🌐 Show Dashboard URL
  help        ❓ Show this help message

🔐 認證指令：
  auth login     登入
  auth logout    登出
  auth status    查看登入狀態

💡 直接執行 fwauto（無參數）進入互動模式

🔧 環境資訊：
  Python:    {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}
  Platform:  {platform.system().lower()}
  Project:   {project_path}

🔐 登入狀態： {auth_status}
🌐 Dashboard: {FWAUTO_SERVER_URL}/dashboard"""

    return help_text


def _build_deploy_state(
    binary_args: str,
    project_root: str,
    platform: str,
) -> FirmwareState:
    """Build FirmwareState for deploy command.

    Used by both CLI deploy command and /deploy slash command.

    Args:
        binary_args: Binary arguments string
        project_root: Project root path
        platform: Platform identifier

    Returns:
        FirmwareState configured for deploy
    """
    return {
        "user_prompt": "部署韌體到裝置",
        "project_root": project_root,
        "project_initialized": True,
        "platform": platform,
        "execution_mode": "deploy",
        "command": "deploy",
        "command_args": {"binary_args": binary_args},
        "mode_metadata": {},
        "command_error": None,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
    }


def _build_log_state(
    log_path: str | None,
    analysis_prompt: str,
    project_root: str,
    platform: str,
) -> FirmwareState:
    """Build FirmwareState for log command.

    Used by both CLI log command and /log slash command.
    Maintains double storage pattern for log_file_path.

    Args:
        log_path: Path to log file (None to auto-detect from config)
        analysis_prompt: Analysis prompt text
        project_root: Project root path
        platform: Platform identifier

    Returns:
        FirmwareState configured for log analysis
    """
    return {
        "user_prompt": analysis_prompt,
        "project_root": project_root,
        "project_initialized": True,
        "platform": platform,
        "execution_mode": "log",
        "command": "log",
        "command_args": {
            "log_path": log_path,
            "analysis_prompt": analysis_prompt,
        },
        "mode_metadata": {},
        "command_error": None,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "log_file_path": log_path,  # Double storage (None is OK, log_node will handle)
        "log_analysis_result": None,
        "firmware_path": None,
    }


def run_workflow(state: FirmwareState) -> None:
    """Execute the firmware workflow with given state."""
    workflow = create_firmware_graph()

    try:
        # Stream workflow execution
        for event in workflow.stream(state):
            for node, result in event.items():
                # Display progress
                if node == "build":
                    status = result.get("build_status")
                    if status == "success":
                        console.print("[green]✓ Build succeeded[/green]")
                    elif status == "error":
                        iteration = result.get("iteration", 0)
                        max_retries = result.get("max_retries", 3)
                        console.print(f"[red]❌ Build failed (attempt {iteration}/{max_retries})[/red]")

                elif node == "deploy":
                    status = result.get("deploy_status")
                    if status == "success":
                        console.print("[green]✓ Deploy succeeded[/green]")

                        # Show remote log path if available
                        log_file_path = result.get("log_file_path")
                        if log_file_path:
                            console.print(f"[cyan]📊 Remote log: {log_file_path}[/cyan]")

                    elif status == "error":
                        console.print("[red]❌ Deploy failed[/red]")

                        # Show brief error summary
                        errors = result.get("deploy_errors", [])
                        if errors:
                            # Show first line of error
                            error_summary = errors[0].split("\n")[0] if errors[0] else ""
                            if error_summary and error_summary != "Deploy failed: ":
                                console.print(f"[red]   {error_summary}[/red]")

                        # Hint to check detailed logs
                        console.print("[dim]📝 See detailed logs in .fwauto/logs/[/dim]")

                elif node == "log":
                    # Log analysis output is handled by the node itself
                    pass

    except KeyboardInterrupt:
        console.print("\n[yellow]⚠️  Operation cancelled by user[/yellow]")
        sys.exit(130)
    except Exception as e:
        console.print(f"[red]❌ Workflow error: {e}[/red]")
        sys.exit(1)


@app.command()
def build():
    """
    🔨 Build STM32 firmware project.

    Requires .fwauto/ configuration in current directory or parent directories.

    Example:
        fwauto build
    """
    console.print("[cyan]🔨 Building project (using .fwauto/ config)...[/cyan]")

    state: FirmwareState = {
        "user_prompt": "build",
        "project_root": "",
        "project_initialized": False,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "execution_mode": "build",
        "command": "build",
        "command_args": {},
        "mode_metadata": None,
        "command_error": None,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
    }

    run_workflow(state)


@app.command()
def deploy(
    binary_args: str = typer.Option(
        "",
        "--binary-args",
        "-ba",
        help="Arguments to pass to the binary (e.g., 'on' or '--mode test')",
    ),
    scenario: str = typer.Option(
        "",
        "--scenario",
        "-s",
        help="Use a predefined scenario (overridden by --binary-args)",
    ),
):
    """
    📥 Deploy firmware to device.

    Supports passing arguments to the binary after deployment.

    \b
    Examples:
        fwauto deploy                             # Deploy without arguments
        fwauto deploy --binary-args "on"          # Pass single argument
        fwauto deploy -ba "arg1 arg2"             # Pass multiple arguments
        fwauto deploy --scenario led-on           # Use predefined scenario
        fwauto deploy -s test-mode                # Use scenario (short option)
    """
    console.print("[cyan]📥 Deploying firmware (using .fwauto/ config)...[/cyan]")

    # 優先級：--binary-args > --scenario
    final_binary_args = binary_args

    if not final_binary_args and scenario:
        # 載入 scenario
        try:
            from .config import find_project_root, load_project_config

            project_root = find_project_root()
            if not project_root:
                console.print("[red]❌ Not in a FWAuto project (no .fwauto/ found)[/red]")
                raise typer.Exit(1)

            config = load_project_config(project_root)
            scenario_manager = config.get_scenario_manager()

            scenario_obj = scenario_manager.get_scenario(scenario)
            if not scenario_obj:
                console.print(f"[red]❌ Scenario '{scenario}' not found[/red]")
                console.print("[yellow]💡 Check scenarios in .fwauto/config.toml[/yellow]")
                raise typer.Exit(1)

            final_binary_args = scenario_obj.binary_args
            console.print(f"[green]✓[/green] Using scenario: {scenario_obj.name}")
            console.print(f"[dim]  Description: {scenario_obj.description}[/dim]")
            console.print(f"[dim]  Args: {scenario_obj.binary_args}[/dim]")

        except typer.Exit:
            raise
        except Exception as e:
            console.print(f"[red]❌ Failed to load scenario: {e}[/red]")
            raise typer.Exit(1)

    if final_binary_args:
        console.print(f"[cyan]📦 Binary args: {final_binary_args}[/cyan]")

    # Get project config for helper function
    from .config import find_project_root, load_project_config

    project_root_path = find_project_root()
    if not project_root_path:
        console.print("[red]❌ Not in a FWAuto project (no .fwauto/ found)[/red]")
        raise typer.Exit(1)

    config = load_project_config(project_root_path)
    sdk_type = config.sdk_type or "unknown"

    # Use helper function to build state
    state = _build_deploy_state(final_binary_args, str(project_root_path), sdk_type)

    run_workflow(state)


@app.command()
def run(
    binary_args: str = typer.Option(
        "",
        "--binary-args",
        "-ba",
        help="Arguments to pass to the binary (e.g., 'on' or '--mode test')",
    ),
    scenario: str = typer.Option(
        "",
        "--scenario",
        "-s",
        help="Use a predefined scenario (overridden by --binary-args)",
    ),
):
    """
    ⚡ Run build and deploy.

    Builds the project and deploys to device with optional binary arguments.

    \b
    Examples:
        fwauto run                                # Build and deploy
        fwauto run --binary-args "on"             # Build, deploy with argument
        fwauto run -ba "arg1 arg2"                # Build, deploy with multiple args
        fwauto run --scenario led-on              # Build, deploy with scenario
        fwauto run -s test-mode                   # Build, deploy with scenario (short)
    """
    console.print("[cyan]⚡ Run build and deploy (using .fwauto/ config)...[/cyan]")

    # 優先級：--binary-args > --scenario
    final_binary_args = binary_args

    if not final_binary_args and scenario:
        # 載入 scenario
        try:
            from .config import find_project_root, load_project_config

            project_root = find_project_root()
            if not project_root:
                console.print("[red]❌ Not in a FWAuto project (no .fwauto/ found)[/red]")
                raise typer.Exit(1)

            config = load_project_config(project_root)
            scenario_manager = config.get_scenario_manager()

            scenario_obj = scenario_manager.get_scenario(scenario)
            if not scenario_obj:
                console.print(f"[red]❌ Scenario '{scenario}' not found[/red]")
                console.print("[yellow]💡 Check scenarios in .fwauto/config.toml[/yellow]")
                raise typer.Exit(1)

            final_binary_args = scenario_obj.binary_args
            console.print(f"[green]✓[/green] Using scenario: {scenario_obj.name}")
            console.print(f"[dim]  Description: {scenario_obj.description}[/dim]")
            console.print(f"[dim]  Args: {scenario_obj.binary_args}[/dim]")

        except typer.Exit:
            raise
        except Exception as e:
            console.print(f"[red]❌ Failed to load scenario: {e}[/red]")
            raise typer.Exit(1)

    if final_binary_args:
        console.print(f"[cyan]📦 Binary args: {final_binary_args}[/cyan]")

    state: FirmwareState = {
        "user_prompt": "run",
        "project_root": "",
        "project_initialized": False,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "execution_mode": "run",
        "command": "run",
        "command_args": {"binary_args": final_binary_args},
        "mode_metadata": {"deploy_after_build": True},
        "command_error": None,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
    }

    run_workflow(state)


@app.command(name="log")
def log_command(
    prompt: str = typer.Argument(..., help="Analysis question or query"),
    log_path: str | None = typer.Option(
        None,
        "--log-path",
        "-l",
        help="Path to UART log file (local or remote: user@host:/path). If not provided, uses last log from config.",
    ),
):
    """
    📊 Analyze UART log files using AI.

    Supports both local and remote log files via SSH/SCP.

    Examples:
        fwauto log "有任何 error 嗎?"
        fwauto log "LED的閃爍頻率為何?" --log-path logs/uart.log
        fwauto log "開機訊息" --log-path user@192.168.1.100:/var/log/uart.log
    """
    # 檢查 AI 功能是否可用（Claude Code + 登入）
    if not _ensure_ai_ready():
        raise typer.Exit(1)

    if log_path:
        console.print(f"[cyan]📊 Analyzing log: {log_path}[/cyan]")
    else:
        console.print("[cyan]📊 Using log path from last deployment...[/cyan]")
    console.print(f"[cyan]❓ Question: {prompt}[/cyan]")

    # Get project config for helper function
    from .config import find_project_root, load_project_config

    project_root_path = find_project_root()
    if not project_root_path:
        console.print("[red]❌ Not in a FWAuto project (no .fwauto/ found)[/red]")
        raise typer.Exit(1)

    config = load_project_config(project_root_path)
    sdk_type = config.sdk_type or "unknown"

    # Use helper function to build state (pass None if not provided)
    state = _build_log_state(log_path, prompt, str(project_root_path), sdk_type)

    run_workflow(state)


@app.command()
def feat(
    prompt: str = typer.Argument(..., help="Feature description in natural language"),
):
    """
    🚀 AI-assisted firmware feature implementation.

    Automatically implements new firmware features with AI assistance,
    including code generation, compilation, auto-fix, and deployment.

    Examples:
        fwauto feat "實作摩斯密碼編碼，支援字符 A-Z"
        fwauto feat "加入蜂鳴器控制，發出 100ms 短音和 300ms 長音"
    """
    # 檢查 AI 功能是否可用（Claude Code + 登入）
    if not _ensure_ai_ready():
        raise typer.Exit(1)

    console.print("[cyan]🚀 AI Feature Implementation[/cyan]")
    console.print(f"[yellow]Feature: {prompt}[/yellow]\n")

    state: FirmwareState = {
        "user_prompt": prompt,
        "project_root": "",
        "project_initialized": False,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "execution_mode": "feat",
        "command": "feat",
        "command_args": {"feature_prompt": prompt},
        "mode_metadata": {"deploy_after_build": True},
        "command_error": None,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
        "platform": "stm32_keil",
    }

    run_workflow(state)


@app.command()
def rag(
    query: str = typer.Argument(..., help="Search query for your documents"),
    top_k: int = typer.Option(5, "--top-k", "-k", help="Number of results to return"),
    auto_select: bool = typer.Option(False, "--auto", "-a", help="Automatically select all results"),
):
    """
    📚 RAG search: Query your uploaded documents and use results with AI.

    Searches your uploaded documents on the server and lets you select
    relevant fragments to include as context for AI assistance.

    Examples:
        fwauto rag "How to configure GPIO?"
        fwauto rag "error handling" --top-k 10
        fwauto rag "LED control" --auto
    """
    # 檢查登入狀態
    if not _ensure_authenticated():
        raise typer.Exit(1)

    from .auth import get_user_token, get_auth_server_url
    import requests

    console.print("[cyan]📚 RAG Document Search[/cyan]")
    console.print(f"[yellow]Query: {query}[/yellow]\n")

    # 1. 呼叫 Server 搜索
    token = get_user_token()
    server_url = get_auth_server_url()

    try:
        response = requests.post(
            f"{server_url}/api/search",
            headers={
                "Authorization": f"Bearer {token}",
                "Content-Type": "application/json"
            },
            json={"query": query, "top_k": top_k},
            timeout=30
        )

        if response.status_code != 200:
            console.print(f"[red]❌ 搜索失敗: {response.text}[/red]")
            raise typer.Exit(1)

        data = response.json()
        results = data.get("results", [])

    except requests.exceptions.RequestException as e:
        console.print(f"[red]❌ 無法連接伺服器: {e}[/red]")
        console.print("[yellow]提示：請確認 Flask Server 正在運行 (python flask_server/app.py)[/yellow]")
        raise typer.Exit(1)

    # 2. 顯示搜索結果
    if not results:
        console.print("[yellow]找不到相關文件片段[/yellow]")
        console.print("[dim]提示：請先在 Dashboard 上傳文件[/dim]")
        raise typer.Exit(0)

    console.print(f"[green]找到 {len(results)} 個相關片段：[/green]\n")

    for i, result in enumerate(results, 1):
        score = result.get("score", 0)
        doc = result.get("document", "unknown")
        text = result.get("text", "")

        # 顯示摘要
        preview = text[:150] + "..." if len(text) > 150 else text
        preview = preview.replace("\n", " ")

        score_color = "green" if score > 0.7 else "yellow" if score > 0.4 else "red"
        console.print(f"[bold][{i}][/bold] [{score_color}]{score:.0%}[/{score_color}] 📄 {doc}")
        console.print(f"    [dim]{preview}[/dim]")
        console.print()

    # 3. 讓用戶選擇要使用的片段
    if auto_select:
        selected_indices = list(range(len(results)))
        console.print("[cyan]--auto 模式：自動選擇所有片段[/cyan]\n")
    else:
        console.print("[cyan]請選擇要加入 AI context 的片段（輸入編號，用逗號分隔，或 'all' 全選，'q' 取消）：[/cyan]")
        try:
            selection = typer.prompt("選擇", default="all")

            if selection.lower() == 'q':
                console.print("[yellow]已取消[/yellow]")
                raise typer.Exit(0)
            elif selection.lower() == 'all':
                selected_indices = list(range(len(results)))
            else:
                # 解析逗號分隔的數字
                selected_indices = []
                for part in selection.split(","):
                    part = part.strip()
                    if part.isdigit():
                        idx = int(part) - 1  # 轉換為 0-based index
                        if 0 <= idx < len(results):
                            selected_indices.append(idx)

        except (KeyboardInterrupt, EOFError):
            console.print("\n[yellow]已取消[/yellow]")
            raise typer.Exit(0)

    if not selected_indices:
        console.print("[yellow]未選擇任何片段[/yellow]")
        raise typer.Exit(0)

    # 4. 組合 context
    selected_chunks = [results[i] for i in selected_indices]
    context_text = "\n\n---\n\n".join([
        f"[來源: {c.get('document', 'unknown')}]\n{c.get('text', '')}"
        for c in selected_chunks
    ])

    console.print(f"[green]已選擇 {len(selected_chunks)} 個片段作為 context[/green]\n")

    # 5. 詢問用戶問題
    console.print("[cyan]請輸入你的問題（AI 將根據選擇的片段回答）：[/cyan]")
    try:
        user_question = typer.prompt("問題")
    except (KeyboardInterrupt, EOFError):
        console.print("\n[yellow]已取消[/yellow]")
        raise typer.Exit(0)

    # 6. 建構完整 prompt 並執行 AI
    full_prompt = f"""根據以下參考資料回答問題。

## 參考資料

{context_text}

## 問題

{user_question}

## 回答

請根據上述參考資料回答問題。如果資料中沒有相關資訊，請說明。"""

    console.print("\n[cyan]🧠 AI 正在處理...[/cyan]\n")

    # 使用 FirmwareState 執行 AI
    state: FirmwareState = {
        "user_prompt": full_prompt,
        "project_root": "",
        "project_initialized": False,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "execution_mode": "rag",
        "command": "rag",
        "command_args": {
            "query": query,
            "question": user_question,
            "context": context_text,
        },
        "mode_metadata": {"rag_context": context_text},
        "command_error": None,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
        "platform": "generic",
    }

    run_workflow(state)


@app.command()
def chat():
    """
    💬 Interactive chat with Claude Code SDK.

    Start an interactive conversation session to:
    - Ask questions about your STM32 project
    - Request code modifications or new features
    - Get help with debugging and analysis
    - Explore codebase structure

    Requires .fwauto/ configuration in current directory or parent directories.

    Examples:
        fwauto chat
    """
    # 檢查 AI 功能是否可用（Claude Code + 登入）
    if not _ensure_ai_ready():
        raise typer.Exit(1)

    console.print("[cyan]💬 Starting interactive chat session...[/cyan]")

    state: FirmwareState = {
        "user_prompt": "chat",
        "project_root": "",
        "project_initialized": False,
        "build_status": "pending",
        "build_errors": [],
        "build_log": "",
        "deploy_status": "pending",
        "deploy_errors": [],
        "deploy_log": "",
        "iteration": 0,
        "max_retries": 3,
        "execution_mode": "chat",
        "command": "chat",
        "command_args": {},
        "mode_metadata": None,
        "command_error": None,
        "log_file_path": None,
        "log_analysis_result": None,
        "firmware_path": None,
        "platform": "stm32_keil",
    }

    run_workflow(state)


@app.command()
def init(
    path: Path | None = typer.Argument(None, help="Project root path (default: current directory)"),
):
    """
    🚀 Initialize new FWAuto project with .fwauto/ configuration.

    Creates .fwauto/ directory structure and configuration files.

    Examples:
        fwauto init              # Initialize in current directory
        fwauto init ./my-project # Initialize in specified directory
    """
    project_root = path if path else Path.cwd()
    console.print(f"[cyan]🚀 Initializing FWAuto project in {project_root}[/cyan]\n")

    success = run_init_wizard(project_root)
    sys.exit(0 if success else 1)


@app.command(name="help")
def help_command():
    """
    ❓ Show help information.

    Displays available commands, version, environment info, and API key status.

    Example:
        fwauto help
    """
    console.print(_get_help_info())


def _enter_unified_chat_mode() -> None:
    """Enter unified chat interface mode.

    This replaces the old _interactive_mode() function.
    Uses chat_node for interactive conversation with slash command support.
    """
    from .config import find_project_root, load_project_config
    from .logging_config import get_logger

    logger = get_logger(__name__)

    try:
        # Load project config (with anchor-based discovery)
        project_root = find_project_root()
        if not project_root:
            console.print("[red]❌ Not in a FWAuto project (no .fwauto/ found)[/red]")
            console.print(
                "[yellow]提示：請在 FWAuto 專案目錄（包含 .fwauto/）中執行此指令，或使用 'fwauto init' 初始化專案[/yellow]"
            )
            sys.exit(1)

        config = load_project_config(project_root)
        sdk_type = config.sdk_type or "unknown"

        console.print(f"[cyan]📁 專案路徑: {project_root}[/cyan]")
        console.print(f"[cyan]🔧 SDK: {sdk_type}[/cyan]")
        console.print("[cyan]💬 進入對話模式（輸入 'exit' 或按 Ctrl+C 離開）[/cyan]")
        console.print("[dim]提示：使用 /build, /deploy, /log 執行指令[/dim]\n")

        # Build initial state for chat mode
        state: FirmwareState = {
            "user_prompt": "",
            "project_root": str(project_root),
            "project_initialized": True,
            "platform": sdk_type,
            "execution_mode": "chat",
            "command": "chat",
            "command_args": {},
            "mode_metadata": {},
            "command_error": None,
            "build_status": "pending",
            "build_errors": [],
            "build_log": "",
            "deploy_status": "pending",
            "deploy_errors": [],
            "deploy_log": "",
            "iteration": 0,
            "max_retries": 3,
            "log_file_path": None,
            "log_analysis_result": None,
            "firmware_path": None,
        }

        # Create and execute graph (which will route to chat_node)
        app_graph = create_firmware_graph()
        result = app_graph.invoke(state)

        if result.get("chat_completed"):
            console.print("\n[green]✅ 對話結束[/green]")
        else:
            console.print("\n[yellow]⚠️ 對話異常結束[/yellow]")

    except FileNotFoundError as e:
        console.print(f"[red]❌ 找不到專案：{e}[/red]")
        console.print("[yellow]提示：請在 FWAuto 專案目錄（包含 .fwauto/）中執行此指令[/yellow]")
        sys.exit(1)

    except Exception as e:
        logger.error(f"Chat mode failed: {e}", exc_info=True)
        console.print(f"[red]❌ 對話模式啟動失敗：{e}[/red]")
        sys.exit(1)


def main():
    """Entry point for the CLI."""
    # Check if running in unified chat mode (no arguments)
    if len(sys.argv) == 1:
        _enter_unified_chat_mode()
    else:
        app()


if __name__ == "__main__":
    main()
