"""Installation tool for whisper.cpp"""

import os
import sys
import platform
import subprocess
import shutil
import json
import logging
from pathlib import Path
from typing import Dict, Any, Optional, Union
import asyncio
import aiohttp
try:
    from importlib.resources import files
except ImportError:
    # Python < 3.9 fallback
    from importlib_resources import files

from voice_mode.server import mcp
from voice_mode.config import SERVICE_AUTO_ENABLE, DEFAULT_WHISPER_MODEL, WHISPER_PORT
from voice_mode.utils.services.whisper_helpers import download_whisper_model
from voice_mode.utils.version_helpers import (
    get_git_tags, get_latest_stable_tag, get_current_version,
    checkout_version, is_version_installed
)
from voice_mode.utils.migration_helpers import auto_migrate_if_needed
from voice_mode.utils.gpu_detection import detect_gpu

logger = logging.getLogger("voicemode")


async def update_whisper_service_files(
    install_dir: str,
    voicemode_dir: str,
    auto_enable: Optional[bool] = None
) -> Dict[str, Any]:
    """Update service files (plist/systemd) for whisper service.
    
    This function updates the service files without reinstalling whisper itself.
    It ensures paths are properly expanded and templates are up to date.
    
    Returns:
        Dict with success status and details about what was updated
    """
    system = platform.system()
    result = {"success": False, "updated": False}
    
    # Create bin directory if it doesn't exist
    bin_dir = os.path.join(install_dir, "bin")
    os.makedirs(bin_dir, exist_ok=True)
    
    # Create/update start script
    logger.info("Updating whisper-server start script...")
    
    # Load template script
    template_content = None
    source_template = Path(__file__).parent.parent.parent.parent / "templates" / "scripts" / "start-whisper-server.sh"
    if source_template.exists():
        logger.info(f"Loading template from source: {source_template}")
        template_content = source_template.read_text()
    else:
        try:
            template_resource = files("voice_mode.templates.scripts").joinpath("start-whisper-server.sh")
            template_content = template_resource.read_text()
            logger.info("Loaded template from package resources")
        except Exception as e:
            logger.warning(f"Failed to load template script: {e}. Using fallback inline script.")
    
    # Use fallback inline script if template not found
    if template_content is None:
        template_content = f"""#!/bin/bash

# Whisper Service Startup Script
# This script is used by both macOS (launchd) and Linux (systemd) to start the whisper service
# It sources the voicemode.env file to get configuration, especially VOICEMODE_WHISPER_MODEL

# Determine whisper directory (script is in bin/, whisper root is parent)
SCRIPT_DIR="$(cd "$(dirname "${{BASH_SOURCE[0]}}")" && pwd)"
WHISPER_DIR="$(dirname "$SCRIPT_DIR")"

# Voicemode configuration directory
VOICEMODE_DIR="$HOME/.voicemode"
LOG_DIR="$VOICEMODE_DIR/logs/whisper"

# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"

# Log file for this script (separate from whisper server logs)
STARTUP_LOG="$LOG_DIR/startup.log"

# Source voicemode configuration if it exists
if [ -f "$VOICEMODE_DIR/voicemode.env" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Sourcing voicemode.env" >> "$STARTUP_LOG"
    source "$VOICEMODE_DIR/voicemode.env"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Warning: voicemode.env not found" >> "$STARTUP_LOG"
fi

# Model selection with environment variable support
MODEL_NAME="${{VOICEMODE_WHISPER_MODEL:-base}}"
MODEL_PATH="$WHISPER_DIR/models/ggml-$MODEL_NAME.bin"

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting whisper-server with model: $MODEL_NAME" >> "$STARTUP_LOG"

# Check if model exists
if [ ! -f "$MODEL_PATH" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error: Model $MODEL_NAME not found at $MODEL_PATH" >> "$STARTUP_LOG"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Available models:" >> "$STARTUP_LOG"
    ls -1 "$WHISPER_DIR/models/" 2>/dev/null | grep "^ggml-.*\\.bin$" >> "$STARTUP_LOG"
    
    # Try to find any available model as fallback
    FALLBACK_MODEL=$(ls -1 "$WHISPER_DIR/models/" 2>/dev/null | grep "^ggml-.*\\.bin$" | head -1)
    if [ -n "$FALLBACK_MODEL" ]; then
        MODEL_PATH="$WHISPER_DIR/models/$FALLBACK_MODEL"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Using fallback model: $FALLBACK_MODEL" >> "$STARTUP_LOG"
    else
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fatal: No whisper models found" >> "$STARTUP_LOG"
        exit 1
    fi
fi

# Port configuration (with environment variable support)
WHISPER_PORT="${{VOICEMODE_WHISPER_PORT:-2022}}"

# Determine server binary location
# Check new CMake build location first, then legacy location
if [ -f "$WHISPER_DIR/build/bin/whisper-server" ]; then
    SERVER_BIN="$WHISPER_DIR/build/bin/whisper-server"
elif [ -f "$WHISPER_DIR/server" ]; then
    SERVER_BIN="$WHISPER_DIR/server"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Error: whisper-server binary not found" >> "$STARTUP_LOG"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Checked: $WHISPER_DIR/build/bin/whisper-server" >> "$STARTUP_LOG"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Checked: $WHISPER_DIR/server" >> "$STARTUP_LOG"
    exit 1
fi

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Using binary: $SERVER_BIN" >> "$STARTUP_LOG"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Model path: $MODEL_PATH" >> "$STARTUP_LOG"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Port: $WHISPER_PORT" >> "$STARTUP_LOG"

# Start whisper-server
# Using exec to replace this script process with whisper-server
cd "$WHISPER_DIR"
exec "$SERVER_BIN" \\
    --host 0.0.0.0 \\
    --port "$WHISPER_PORT" \\
    --model "$MODEL_PATH" \\
    --inference-path /v1/audio/transcriptions \\
    --threads 8
"""
    
    start_script_path = os.path.join(bin_dir, "start-whisper-server.sh")
    with open(start_script_path, 'w') as f:
        f.write(template_content)
    os.chmod(start_script_path, 0o755)
    
    # Update service files based on platform
    if system == "Darwin":
        logger.info("Updating launchagent for whisper-server...")
        launchagents_dir = os.path.expanduser("~/Library/LaunchAgents")
        os.makedirs(launchagents_dir, exist_ok=True)
        
        # Create log directory
        log_dir = os.path.join(voicemode_dir, 'logs', 'whisper')
        os.makedirs(log_dir, exist_ok=True)
        
        plist_name = "com.voicemode.whisper.plist"
        plist_path = os.path.join(launchagents_dir, plist_name)
        
        # Load plist template
        source_template = Path(__file__).parent.parent.parent.parent / "templates" / "launchd" / "com.voicemode.whisper.plist"
        if source_template.exists():
            logger.info(f"Loading plist template from source: {source_template}")
            plist_content = source_template.read_text()
        else:
            template_resource = files("voice_mode.templates.launchd").joinpath("com.voicemode.whisper.plist")
            plist_content = template_resource.read_text()
            logger.info("Loaded plist template from package resources")
        
        # Replace placeholders with expanded paths
        plist_content = plist_content.replace("{START_SCRIPT_PATH}", start_script_path)
        plist_content = plist_content.replace("{LOG_DIR}", os.path.join(voicemode_dir, 'logs'))
        plist_content = plist_content.replace("{INSTALL_DIR}", install_dir)
        
        # Unload if already loaded (ignore errors)
        try:
            subprocess.run(["launchctl", "unload", plist_path], capture_output=True)
        except:
            pass
        
        # Write updated plist
        with open(plist_path, 'w') as f:
            f.write(plist_content)
        
        result["success"] = True
        result["updated"] = True
        result["plist_path"] = plist_path
        result["start_script"] = start_script_path
        
        # Handle auto_enable if specified
        if auto_enable is None:
            auto_enable = SERVICE_AUTO_ENABLE
        
        if auto_enable:
            logger.info("Auto-enabling whisper service...")
            from voice_mode.tools.service import enable_service
            enable_result = await enable_service("whisper")
            if "✅" in enable_result:
                result["enabled"] = True
            else:
                logger.warning(f"Auto-enable failed: {enable_result}")
                result["enabled"] = False
    
    elif system == "Linux":
        logger.info("Updating systemd user service for whisper-server...")
        systemd_user_dir = os.path.expanduser("~/.config/systemd/user")
        os.makedirs(systemd_user_dir, exist_ok=True)

        # Create log directory
        log_dir = os.path.join(voicemode_dir, 'logs', 'whisper')
        os.makedirs(log_dir, exist_ok=True)

        service_name = "voicemode-whisper.service"
        service_path = os.path.join(systemd_user_dir, service_name)

        # Load systemd service template
        source_template = Path(__file__).parent.parent.parent.parent / "templates" / "systemd" / "voicemode-whisper.service"
        if source_template.exists():
            logger.info(f"Loading systemd template from source: {source_template}")
            service_content = source_template.read_text()
        else:
            try:
                template_resource = files("voice_mode.templates.systemd").joinpath("voicemode-whisper.service")
                service_content = template_resource.read_text()
                logger.info("Loaded systemd template from package resources")
            except Exception as e:
                logger.warning(f"Failed to load template: {e}. Using fallback inline template.")
                # Fallback inline template if loading fails
                service_content = f"""# voicemode-whisper.service v1.1.0
# Last updated: 2025-11-12
# Uses unified startup script for dynamic model selection

[Unit]
Description=Whisper.cpp Speech Recognition Server
After=network.target

[Service]
Type=simple
ExecStart={{START_SCRIPT_PATH}}
# Wait for service to be ready by checking health endpoint
ExecStartPost=/bin/sh -c 'while ! curl -sf http://127.0.0.1:{{WHISPER_PORT}}/health >/dev/null 2>&1; do echo "Waiting for Whisper to be ready..."; sleep 1; done; echo "Whisper is ready!"'
Restart=on-failure
RestartSec=10
WorkingDirectory={{INSTALL_DIR}}
StandardOutput=append:{{LOG_DIR}}/whisper/whisper.out.log
StandardError=append:{{LOG_DIR}}/whisper/whisper.err.log
Environment="PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/cuda/bin"

[Install]
WantedBy=default.target
"""

        # Replace placeholders with expanded paths
        service_content = service_content.replace("{START_SCRIPT_PATH}", start_script_path)
        service_content = service_content.replace("{LOG_DIR}", os.path.join(voicemode_dir, 'logs'))
        service_content = service_content.replace("{INSTALL_DIR}", install_dir)
        service_content = service_content.replace("{WHISPER_PORT}", str(WHISPER_PORT))

        # Write systemd service file
        with open(service_path, 'w') as f:
            f.write(service_content)
        
        # Reload systemd
        try:
            subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
            result["success"] = True
            result["updated"] = True
            result["service_path"] = service_path
            result["start_script"] = start_script_path
        except subprocess.CalledProcessError as e:
            logger.warning(f"Failed to reload systemd: {e}")
            result["success"] = True  # Still consider it success if file was written
            result["updated"] = True
            result["service_path"] = service_path
            result["start_script"] = start_script_path
        
        # Handle auto_enable if specified
        if auto_enable is None:
            auto_enable = SERVICE_AUTO_ENABLE
        
        if auto_enable:
            logger.info("Auto-enabling whisper service...")
            from voice_mode.tools.service import enable_service
            enable_result = await enable_service("whisper")
            if "✅" in enable_result:
                result["enabled"] = True
            else:
                logger.warning(f"Auto-enable failed: {enable_result}")
                result["enabled"] = False
    
    else:
        result["success"] = False
        result["error"] = f"Unsupported platform: {system}"
    
    return result


@mcp.tool()
async def whisper_install(
    install_dir: Optional[str] = None,
    model: str = DEFAULT_WHISPER_MODEL,
    no_model: Union[bool, str] = False,
    use_gpu: Optional[Union[bool, str]] = None,
    force_reinstall: Union[bool, str] = False,
    auto_enable: Optional[Union[bool, str]] = None,
    version: str = "latest",
    skip_core_ml: Union[bool, str] = False,
    skip_deps: Union[bool, str] = False
) -> Dict[str, Any]:
    """
    Install whisper.cpp with automatic system detection and configuration.

    Supports macOS (with Metal) and Linux (with CUDA if available).
    On Apple Silicon Macs, automatically downloads pre-built Core ML models
    for 2-3x better performance (no Python dependencies or Xcode required!).

    Args:
        install_dir: Directory to install whisper.cpp (default: ~/.voicemode/whisper.cpp)
        model: Whisper model to download (tiny, base, small, medium, large-v2, large-v3, etc.)
               Default is base for good balance of speed and accuracy (142MB).
               On Apple Silicon, also downloads pre-built Core ML model.
        no_model: Skip model download entirely (default: False)
        use_gpu: Enable GPU support if available (default: auto-detect)
        force_reinstall: Force reinstallation even if already installed
        auto_enable: Enable service after install. If None, uses VOICEMODE_SERVICE_AUTO_ENABLE config.
        version: Version to install (default: "latest" for latest stable release)
        skip_core_ml: Skip Core ML model download on Apple Silicon (default: False)
        skip_deps: Skip dependency checks (for advanced users, default: False)

    Returns:
        Installation status with paths and configuration details
    """
    try:
        # Check for and migrate old installations
        migration_msg = auto_migrate_if_needed("whisper")

        # NixOS cannot build whisper.cpp through the standard FHS path —
        # cmake/gcc/CUDA expect paths like /usr/local/cuda/ and /usr/include/
        # that don't exist on NixOS.  The VoiceMode flake.nix provides Nix-
        # native packages instead.
        if os.path.isfile("/etc/NIXOS"):
            return {
                "success": False,
                "error": "NixOS detected — the standard whisper installer cannot "
                         "build on NixOS because it expects FHS paths that don't exist.",
                "nixos_guidance": {
                    "cpu": "nix build github:mbailey/voicemode#whisper-cpp",
                    "cuda": "nix build github:mbailey/voicemode#whisper-cpp-cuda",
                    "wrapper": "nix build github:mbailey/voicemode#voice-mode-cuda",
                    "note": "The voice-mode-cuda wrapper puts whisper-server on PATH "
                            "so VoiceMode discovers it automatically. See flake.nix "
                            "for GPU architecture options (cudaArch)."
                }
            }

        # Check whisper build dependencies (unless skipped)
        if not skip_deps:
            from voice_mode.utils.dependencies.checker import (
                check_component_dependencies,
                install_missing_dependencies
            )

            results = check_component_dependencies('whisper')
            missing = [pkg for pkg, installed in results.items() if not installed]

            if missing:
                logger.info(f"Missing whisper build dependencies: {', '.join(missing)}")
                # Check if we're in an interactive terminal (not MCP context)
                is_interactive = sys.stdin.isatty() if hasattr(sys.stdin, 'isatty') else False
                success, output = install_missing_dependencies(missing, interactive=is_interactive)
                if not success:
                    return {
                        "success": False,
                        "error": "Required build dependencies not installed",
                        "missing_dependencies": missing
                    }
        else:
            logger.info("Skipping dependency checks (--skip-deps specified)")

        # Set default install directory under ~/.voicemode
        voicemode_dir = os.path.expanduser("~/.voicemode")
        os.makedirs(voicemode_dir, exist_ok=True)
        
        if install_dir is None:
            install_dir = os.path.join(voicemode_dir, "services", "whisper")
        else:
            install_dir = os.path.expanduser(install_dir)
        
        # Resolve version if "latest" is specified
        if version == "latest":
            tags = get_git_tags("https://github.com/ggerganov/whisper.cpp")
            if not tags:
                return {
                    "success": False,
                    "error": "Failed to fetch available versions"
                }
            version = get_latest_stable_tag(tags)
            if not version:
                return {
                    "success": False,
                    "error": "No stable versions found"
                }
            logger.info(f"Using latest stable version: {version}")
        
        # Check if already installed
        if os.path.exists(install_dir) and not force_reinstall:
            if os.path.exists(os.path.join(install_dir, "main")) or os.path.exists(os.path.join(install_dir, "build", "bin", "whisper-cli")):
                # Check if the requested version is already installed
                if is_version_installed(Path(install_dir), version):
                    current_version = get_current_version(Path(install_dir))
                    
                    # Always update service files even if whisper is already installed
                    logger.info("Whisper is already installed, updating service files...")
                    service_update_result = await update_whisper_service_files(
                        install_dir=install_dir,
                        voicemode_dir=voicemode_dir,
                        auto_enable=auto_enable
                    )
                    
                    # Check for model if not skipping
                    if not no_model:
                        model_path = os.path.join(install_dir, "models", f"ggml-{model}.bin")
                        if not os.path.exists(model_path):
                            logger.info(f"Downloading model {model}...")
                            download_result = await download_whisper_model(
                                model=model,
                                models_dir=os.path.join(install_dir, "models"),
                                force_download=False,
                                skip_core_ml=skip_core_ml
                            )
                            if download_result["success"]:
                                model_path = download_result["path"]
                                if download_result.get("core_ml_status", {}).get("success"):
                                    logger.info(f"✅ Core ML model downloaded for 2-3x faster performance!")
                    else:
                        model_path = None

                    # Build response message
                    message = f"whisper.cpp version {current_version} already installed."
                    if service_update_result.get("updated"):
                        message += " Service files updated."
                    if service_update_result.get("enabled"):
                        message += " Service auto-enabled."
                    
                    return {
                        "success": True,
                        "install_path": install_dir,
                        "model_path": model_path,
                        "already_installed": True,
                        "service_files_updated": service_update_result.get("updated", False),
                        "version": current_version,
                        "plist_path": service_update_result.get("plist_path"),
                        "service_path": service_update_result.get("service_path"),
                        "start_script": service_update_result.get("start_script"),
                        "message": message
                    }
        
        # Detect system
        system = platform.system()
        is_macos = system == "Darwin"
        is_linux = system == "Linux"
        
        if not is_macos and not is_linux:
            return {
                "success": False,
                "error": f"Unsupported operating system: {system}"
            }
        
        # Auto-detect GPU if not specified
        if use_gpu is None:
            use_gpu, gpu_type = detect_gpu()
            logger.info(f"Auto-detected GPU: {gpu_type} (enabled: {use_gpu})")
        else:
            # User specified whether to use GPU
            if use_gpu:
                # Get the detected GPU type
                _, detected_type = detect_gpu()
                gpu_type = detected_type if detected_type != "cpu" else ("metal" if is_macos else "cuda")
            else:
                gpu_type = "cpu"
        
        logger.info(f"Installing whisper.cpp on {system} with {gpu_type} support")
        
        # Check prerequisites
        missing_deps = []
        
        if is_macos:
            # Check for Xcode Command Line Tools
            try:
                subprocess.run(["xcode-select", "-p"], capture_output=True, check=True)
            except:
                missing_deps.append("Xcode Command Line Tools (run: xcode-select --install)")
            
            # Check for Homebrew
            if not shutil.which("brew"):
                missing_deps.append("Homebrew (install from https://brew.sh)")
            
            # Check for cmake
            if not shutil.which("cmake"):
                # If homebrew is available, offer to install cmake automatically
                if shutil.which("brew"):
                    logger.info("cmake not found, attempting to install via homebrew...")
                    try:
                        subprocess.run(["brew", "install", "cmake"], check=True)
                        logger.info("Successfully installed cmake")
                    except subprocess.CalledProcessError:
                        missing_deps.append("cmake (failed to install, please run: brew install cmake)")
                else:
                    missing_deps.append("cmake (run: brew install cmake)")
        
        elif is_linux:
            # Check for build essentials
            if not shutil.which("gcc") or not shutil.which("make"):
                missing_deps.append("build-essential (run: sudo apt-get install build-essential)")
            
            if use_gpu and not shutil.which("nvcc"):
                # Suggest distro-appropriate install command, or --no-gpu as alternative
                if shutil.which("apt-get"):
                    cuda_install = "sudo apt-get install nvidia-cuda-toolkit"
                elif shutil.which("dnf"):
                    cuda_install = "sudo dnf install cuda-toolkit"
                else:
                    cuda_install = "your distribution's CUDA toolkit package"
                missing_deps.append(
                    f"CUDA toolkit (run: {cuda_install}, or use --no-gpu for CPU-only)"
                )
        
        if missing_deps:
            return {
                "success": False,
                "error": "Missing dependencies",
                "missing": missing_deps,
                "message": "Please install missing dependencies and try again"
            }
        
        # Remove existing installation if force_reinstall
        if force_reinstall and os.path.exists(install_dir):
            logger.info(f"Removing existing installation at {install_dir}")
            shutil.rmtree(install_dir)
        
        # Clone whisper.cpp if not exists
        if not os.path.exists(install_dir):
            logger.info(f"Cloning whisper.cpp repository (version {version})...")
            subprocess.run([
                "git", "clone", "https://github.com/ggerganov/whisper.cpp.git", install_dir
            ], check=True)
            # Checkout the specific version
            if not checkout_version(Path(install_dir), version):
                shutil.rmtree(install_dir)
                return {
                    "success": False,
                    "error": f"Failed to checkout version {version}"
                }
        else:
            logger.info(f"Using existing whisper.cpp directory, switching to version {version}...")
            # Clean any local changes and checkout the version
            subprocess.run(["git", "reset", "--hard"], cwd=install_dir, check=True)
            subprocess.run(["git", "clean", "-fd"], cwd=install_dir, check=True)
            if not checkout_version(Path(install_dir), version):
                return {
                    "success": False,
                    "error": f"Failed to checkout version {version}"
                }
        
        # Build whisper.cpp
        logger.info(f"Building whisper.cpp with {gpu_type} support...")
        original_dir = os.getcwd()
        os.chdir(install_dir)
        
        # Clean any previous build (only if Makefile exists)
        if os.path.exists("Makefile"):
            try:
                subprocess.run(["make", "clean"], check=True, 
                             capture_output=True, text=True)
            except subprocess.CalledProcessError:
                logger.warning("Make clean skipped (no previous build), continuing...")
        
        # Build with CMake for better control and Core ML support
        build_env = os.environ.copy()
        cmake_flags = []

        # Enable SDL2 for whisper-stream binary (real-time transcription)
        cmake_flags.append("-DWHISPER_SDL2=ON")

        # Enable GPU support based on platform
        if is_macos:
            # On macOS, always enable Metal
            cmake_flags.append("-DGGML_METAL=ON")
            # On Apple Silicon, also enable Core ML for better performance
            if platform.machine() == "arm64":
                cmake_flags.append("-DWHISPER_COREML=ON")
                cmake_flags.append("-DWHISPER_COREML_ALLOW_FALLBACK=ON")
                logger.info("Enabling Core ML support with fallback for Apple Silicon")
        elif is_linux and use_gpu:
            cmake_flags.append("-DGGML_CUDA=ON")
        
        # Get number of CPU cores for parallel build
        cpu_count = os.cpu_count() or 4
        
        # Determine if we should show build output
        debug_mode = os.environ.get("VOICEMODE_DEBUG", "").lower() in ("true", "1", "yes")
        
        # Configure with CMake
        logger.info("Configuring whisper.cpp build...")
        logger.info(f"CMake flags: {cmake_flags}")
        cmake_cmd = ["cmake", "-B", "build"] + cmake_flags
        logger.info(f"CMake command: {' '.join(cmake_cmd)}")
        
        if debug_mode:
            subprocess.run(cmake_cmd, env=build_env, check=True)
        else:
            try:
                result = subprocess.run(cmake_cmd, env=build_env, 
                                      capture_output=True, text=True, check=True)
            except subprocess.CalledProcessError as e:
                logger.error(f"Configuration failed: {e}")
                if e.stderr:
                    logger.error(f"Configuration errors:\n{e.stderr}")
                raise
        
        # Build with CMake
        logger.info("Building whisper.cpp (this may take a few minutes)...")
        build_cmd = ["cmake", "--build", "build", "-j", str(cpu_count), "--config", "Release"]
        
        if debug_mode:
            subprocess.run(build_cmd, env=build_env, check=True)
        else:
            try:
                result = subprocess.run(build_cmd, env=build_env, 
                                      capture_output=True, text=True, check=True)
                logger.info("Build completed successfully")
            except subprocess.CalledProcessError as e:
                logger.error(f"Build failed: {e}")
                if e.stdout:
                    logger.error(f"Build output:\n{e.stdout}")
                if e.stderr:
                    logger.error(f"Build errors:\n{e.stderr}")
                raise
        
        # Note: whisper-server is now built as part of the main build target
        
        # Download model unless --no-model specified
        if not no_model:
            logger.info(f"Downloading default model: {model}")
            models_dir = os.path.join(install_dir, "models")

            download_result = await download_whisper_model(
                model=model,
                models_dir=models_dir,
                force_download=False,
                skip_core_ml=skip_core_ml
            )

            if not download_result["success"]:
                logger.warning(f"Failed to download model: {download_result.get('error', 'Unknown error')}")
                logger.info("You can download models later using 'voicemode whisper model install'")
                model_path = None
                model_error = download_result.get('error', 'Unknown error')
            else:
                model_path = download_result["path"]
                model_error = None
                if download_result.get("core_ml_status", {}).get("success"):
                    logger.info(f"✅ Core ML model downloaded for 2-3x faster performance!")
        else:
            logger.info("Skipping model download (--no-model specified)")
            model_path = None
            model_error = None
        
        # Test whisper with sample if available (only if we have a model)
        # With CMake build, binaries are in build/bin/
        main_path = os.path.join(install_dir, "build", "bin", "whisper-cli")
        sample_path = os.path.join(install_dir, "samples", "jfk.wav")
        if model_path and os.path.exists(sample_path) and os.path.exists(main_path):
            try:
                result = subprocess.run([
                    main_path, "-m", model_path, "-f", sample_path, "-np"
                ], capture_output=True, text=True, timeout=30)
                
                if result.returncode != 0:
                    logger.warning(f"Test run failed: {result.stderr}")
            except subprocess.TimeoutExpired:
                logger.warning("Test run timed out")
        
        # Restore original directory
        if 'original_dir' in locals():
            os.chdir(original_dir)
        
        # Update service files (includes creating start script)
        logger.info("Installing/updating service files...")
        service_update_result = await update_whisper_service_files(
            install_dir=install_dir,
            voicemode_dir=voicemode_dir,
            auto_enable=auto_enable
        )
        
        if not service_update_result.get("success"):
            logger.error(f"Failed to update service files: {service_update_result.get('error', 'Unknown error')}")
            return {
                "success": False,
                "error": f"Service file update failed: {service_update_result.get('error', 'Unknown error')}"
            }
        
        # Get the start script path from the result
        start_script_path = service_update_result.get("start_script")
        
        # Build return message based on results
        if system == "Darwin":
            current_version = get_current_version(Path(install_dir))
            enable_message = " Service auto-enabled." if service_update_result.get("enabled") else ""
            
            return {
                "success": True,
                "install_path": install_dir,
                "model_path": model_path,
                "model_error": model_error,
                "gpu_enabled": use_gpu,
                "gpu_type": gpu_type,
                "version": current_version,
                "performance_info": {
                    "system": system,
                    "gpu_acceleration": gpu_type,
                    "model": model,
                    "binary_path": main_path if 'main_path' in locals() else os.path.join(install_dir, "main"),
                    "server_port": 2022,
                    "server_url": "http://localhost:2022"
                },
                "launchagent": service_update_result.get("plist_path"),
                "start_script": start_script_path,
                "message": f"Successfully installed whisper.cpp {current_version} with {gpu_type} support and whisper-server on port 2022{enable_message}{' (' + migration_msg + ')' if migration_msg else ''}"
            }
        
        elif system == "Linux":
            current_version = get_current_version(Path(install_dir))
            enable_message = " Service auto-enabled." if service_update_result.get("enabled") else ""
            systemd_message = "Systemd service installed"
            
            return {
                "success": True,
                "install_path": install_dir,
                "model_path": model_path,
                "model_error": model_error,
                "gpu_enabled": use_gpu,
                "gpu_type": gpu_type,
                "version": current_version,
                "performance_info": {
                    "system": system,
                    "gpu_acceleration": gpu_type,
                    "model": model,
                    "binary_path": main_path if 'main_path' in locals() else os.path.join(install_dir, "main"),
                    "server_port": 2022,
                    "server_url": "http://localhost:2022"
                },
                "systemd_service": service_update_result.get("service_path"),
                "systemd_enabled": service_update_result.get("enabled", False),
                "start_script": start_script_path,
                "message": f"Successfully installed whisper.cpp {current_version} with {gpu_type} support. {systemd_message}{enable_message}{' (' + migration_msg + ')' if migration_msg else ''}"
            }
        
        else:
            current_version = get_current_version(Path(install_dir))
            return {
                "success": True,
                "install_path": install_dir,
                "model_path": model_path,
                "model_error": model_error,
                "gpu_enabled": use_gpu,
                "gpu_type": gpu_type,
                "version": current_version,
                "performance_info": {
                    "system": system,
                    "gpu_acceleration": gpu_type,
                    "model": model,
                    "binary_path": main_path if 'main_path' in locals() else os.path.join(install_dir, "main")
                },
                "message": f"Successfully installed whisper.cpp {current_version} with {gpu_type} support{enable_message}{' (' + migration_msg + ')' if migration_msg else ''}"
            }
        
    except subprocess.CalledProcessError as e:
        if 'original_dir' in locals():
            os.chdir(original_dir)
        return {
            "success": False,
            "error": f"Command failed: {e.cmd}",
            "stderr": e.stderr.decode() if e.stderr else None
        }
    except Exception as e:
        if 'original_dir' in locals():
            os.chdir(original_dir)
        return {
            "success": False,
            "error": str(e)
        }