#!/usr/bin/env bash
# TypeDialog Installation Script
# Installs TypeDialog (main + backends + tools) for interactive configuration and provisioning
#
# TypeDialog Suite Components:
#   BACKENDS (interactive forms):
#     - typedialog         CLI backend (step-by-step prompts)
#     - typedialog-tui     Terminal UI backend (3-panel interface)
#     - typedialog-web     Web backend (browser-based interface)
#   TOOLS (provisioning):
#     - typedialog-ag      Type-safe AI agents for automation
#     - typedialog-ai      AI configuration assistant (HTTP server backend)
#     - typedialog-prov-gen Provisioning structure generator
#
# Usage:
#   ./install-typedialog.sh                              # Interactive mode
#   ./install-typedialog.sh --version 0.1.0             # Specify version
#   ./install-typedialog.sh --components all            # Install all (default)
#   ./install-typedialog.sh --components backends       # Only: cli,tui,web
#   ./install-typedialog.sh --components tools          # Only: ag,ai,prov-gen
#   ./install-typedialog.sh --components cli,tui,ag     # Custom selection
#   ./install-typedialog.sh --install-dir /usr/local/bin # Custom directory
#   ./install-typedialog.sh --help                       # Show help

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Script configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
VERSIONS_FILE="${PROJECT_ROOT}/core/versions.ncl"

# All available components
BACKENDS=("cli" "tui" "web")
TOOLS=("ag" "ai" "prov-gen")
ALL_COMPONENTS=("${BACKENDS[@]}" "${TOOLS[@]}")

# Default values
TYPEDIALOG_VERSION=""
INSTALL_DIR=""
INSTALL_COMPONENTS="all"
FORCE=false
VERBOSE=false
SKIP_VALIDATION=false
INTERACTIVE=false

# ============================================================================
# Helper Functions
# ============================================================================

print_header() {
    echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
    echo -e "${BLUE}$1${NC}"
    echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
}

print_info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

print_success() {
    echo -e "${GREEN}✅ $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

print_error() {
    echo -e "${RED}❌ $1${NC}" >&2
}

debug() {
    if [[ "$VERBOSE" == "true" ]]; then
        echo -e "${BLUE}🔍 $1${NC}"
    fi
}

# ============================================================================
# Platform Detection
# ============================================================================

detect_os() {
    local os=""
    case "$(uname -s)" in
        Darwin*)  os="macos" ;;
        Linux*)   os="linux" ;;
        MINGW*|MSYS*|CYGWIN*)  os="windows" ;;
        *)  print_error "Unsupported OS: $(uname -s)"; return 1 ;;
    esac
    echo "$os"
}

detect_arch() {
    local arch=""
    case "$(uname -m)" in
        x86_64|amd64)   arch="x86_64" ;;
        aarch64|arm64)  arch="aarch64" ;;
        *)  print_error "Unsupported architecture: $(uname -m)"; return 1 ;;
    esac
    echo "$arch"
}

get_binary_name() {
    local component=$1
    local os=$2

    # Map component name to binary name
    local binary="typedialog"
    case "$component" in
        tui)        binary="typedialog-tui" ;;
        web)        binary="typedialog-web" ;;
        ag)         binary="typedialog-ag" ;;
        ai)         binary="typedialog-ai" ;;
        prov-gen)   binary="typedialog-prov-gen" ;;
        *)          binary="typedialog" ;;
    esac

    case "$os" in
        macos|linux)
            echo "${binary}"
            ;;
        windows)
            echo "${binary}.exe"
            ;;
        *)
            echo "${binary}"
            ;;
    esac
}

# ============================================================================
# Version Management
# ============================================================================

extract_version_from_ncl() {
    local tool=$1

    if [[ ! -f "$VERSIONS_FILE" ]]; then
        debug "versions.ncl not found at $VERSIONS_FILE"
        return 1
    fi

    # Extract version for tool using grep
    local version_line=$(grep -A 2 "name = \"$tool\"" "$VERSIONS_FILE" | grep "current =" | head -1)

    if [[ -z "$version_line" ]]; then
        return 1
    fi

    # Extract version string (format: current = "X.Y.Z",)
    local version=$(echo "$version_line" | sed 's/.*current = "\([^"]*\)".*/\1/')

    if [[ -z "$version" || "$version" == "$version_line" ]]; then
        return 1
    fi

    echo "$version"
}

# ============================================================================
# Installation Functions
# ============================================================================

ensure_install_dir() {
    local dir=$1

    if [[ ! -d "$dir" ]]; then
        print_info "Creating installation directory: $dir"
        mkdir -p "$dir" || {
            print_error "Failed to create directory: $dir"
            return 1
        }
    fi

    # Verify directory is writable
    if [[ ! -w "$dir" ]]; then
        print_error "Installation directory is not writable: $dir"
        return 1
    fi
}

download_binary() {
    local binary=$1
    local version=$2
    local os=$3
    local arch=$4
    local output_path=$5

    # GitHub release URL pattern
    local github_repo="typedialog/typedialog"
    local release_url="https://github.com/${github_repo}/releases/download/v${version}"

    # Determine binary name
    local binary_name=$(get_binary_name "$binary" "$os")
    local download_url="${release_url}/${binary_name}-${os}-${arch}"

    print_info "Downloading: ${binary} (${version}) for ${os}/${arch}"
    debug "URL: $download_url"

    # Download with curl
    if ! curl -fsSL --progress-bar "$download_url" -o "$output_path"; then
        print_error "Failed to download from: $download_url"
        return 1
    fi

    # Verify downloaded file
    if [[ ! -f "$output_path" ]]; then
        print_error "Downloaded file not found: $output_path"
        return 1
    fi

    # Check file size (should not be tiny)
    local file_size=$(stat -f%z "$output_path" 2>/dev/null || stat -c%s "$output_path" 2>/dev/null || echo 0)
    if [[ $file_size -lt 1000000 ]]; then  # Less than 1MB = likely error
        print_warning "Downloaded file seems too small ($file_size bytes), may be error page"
        return 1
    fi

    print_success "Downloaded: $output_path"
}

install_binary() {
    local source=$1
    local dest=$2
    local binary_name=$3

    # Copy binary
    if ! cp "$source" "$dest"; then
        print_error "Failed to copy binary from $source to $dest"
        return 1
    fi

    # Make executable
    if ! chmod +x "$dest"; then
        print_error "Failed to make binary executable: $dest"
        return 1
    fi

    print_success "Installed: $dest"
}

validate_installation() {
    local binary=$1
    local expected_version=$2

    # Check if binary exists in PATH
    if ! command -v "$binary" &> /dev/null; then
        print_error "Binary not found in PATH: $binary"
        return 1
    fi

    # Get installed version
    local installed_version=$("$binary" --version 2>&1 | head -1 | sed 's/.*\s\([0-9.]*\)$/\1/' || echo "")

    if [[ -z "$installed_version" ]]; then
        print_warning "Could not determine installed version of $binary"
        if [[ "$SKIP_VALIDATION" == "false" ]]; then
            return 1
        fi
        return 0
    fi

    # Check version match
    if [[ "$installed_version" != "$expected_version" ]]; then
        print_warning "Version mismatch: expected $expected_version, got $installed_version"
        if [[ "$FORCE" != "true" ]]; then
            return 1
        fi
    fi

    print_success "Validated: $binary ($installed_version)"
}

# ============================================================================
# Main Installation Flow
# ============================================================================

install_component() {
    local component=$1
    local version=$2
    local install_dir=$3
    local os=$4
    local arch=$5
    local component_type=${6:-""}  # "backend" or "tool" for logging

    local binary_name=$(get_binary_name "$component" "$os")
    local display_name="typedialog"

    if [[ "$component" != "cli" ]]; then
        display_name="typedialog-${component}"
    fi

    print_info "Installing: ${display_name}${component_type:+ ($component_type)}"

    # Create temp directory for downloads
    local temp_dir=$(mktemp -d)
    trap "rm -rf $temp_dir" EXIT

    # Download component binary
    local temp_binary="${temp_dir}/${binary_name}"
    download_binary "$component" "$version" "$os" "$arch" "$temp_binary" || {
        print_warning "Failed to download ${display_name} (may not be available for this version/platform)"
        return 0  # Don't fail if component unavailable
    }

    # Install component binary
    install_binary "$temp_binary" "${install_dir}/${binary_name}" "${display_name}" || {
        print_warning "Failed to install ${display_name}"
        return 0  # Don't fail if installation fails
    }

    return 0
}

install_components() {
    local components=$1
    local version=$2
    local install_dir=$3
    local os=$4
    local arch=$5

    if [[ -z "$components" || "$components" == "none" ]]; then
        print_info "No components specified for installation"
        return 0
    fi

    # Expand "all" and "backends"/"tools" aliases
    local expanded_components=""

    if [[ "$components" == "all" ]]; then
        expanded_components="${ALL_COMPONENTS[*]}"
    elif [[ "$components" == "backends" ]]; then
        expanded_components="${BACKENDS[*]}"
    elif [[ "$components" == "tools" ]]; then
        expanded_components="${TOOLS[*]}"
    else
        # Assume comma-separated list
        expanded_components=$(echo "$components" | sed 's/,/ /g')
    fi

    print_header "Installing TypeDialog Components"

    local installed_count=0
    local failed_count=0

    for component in $expanded_components; do
        component=$(echo "$component" | xargs)  # trim whitespace

        if [[ -z "$component" ]]; then
            continue
        fi

        # Validate component name
        if [[ ! " ${ALL_COMPONENTS[*]} " =~ " ${component} " ]]; then
            print_warning "Unknown component: $component"
            continue
        fi

        # Determine component type for logging
        local ctype=""
        if [[ " ${BACKENDS[*]} " =~ " ${component} " ]]; then
            ctype="backend"
        elif [[ " ${TOOLS[*]} " =~ " ${component} " ]]; then
            ctype="tool"
        fi

        if install_component "$component" "$version" "$install_dir" "$os" "$arch" "$ctype"; then
            ((installed_count++))
        else
            ((failed_count++))
        fi
    done

    echo ""
    print_success "Installation completed: ${installed_count} component(s) installed"
    if [[ $failed_count -gt 0 ]]; then
        print_warning "${failed_count} component(s) failed"
    fi
}

validate_all() {
    local install_dir=$1

    print_header "Validating Installation"

    # Validate main binary
    validate_installation "typedialog" "$TYPEDIALOG_VERSION" || return 1

    # Validate installed backends
    for backend in tui web; do
        if command -v "typedialog-${backend}" &> /dev/null; then
            validate_installation "typedialog-${backend}" "$TYPEDIALOG_VERSION" || true
        fi
    done

    return 0
}

# ============================================================================
# Help and Configuration
# ============================================================================

show_help() {
    cat <<EOF
${BLUE}TypeDialog Installation Script${NC}
Complete installation of TypeDialog suite: backends (CLI/TUI/Web) + tools (AG/AI/ProvGen)

Usage: $(basename "$0") [OPTIONS]

OPTIONS:
  -v, --version VERSION           TypeDialog version to install (default: from versions.ncl)
  -c, --components COMPONENTS     Components to install (see COMPONENTS below)
  -d, --install-dir DIR           Installation directory (default: ~/.local/bin)
  -i, --interactive               Interactive mode (select components)
  --force                         Force installation even on version mismatch
  --skip-validation               Skip validation checks after installation
  --verbose                       Enable verbose output
  -h, --help                      Show this help message

COMPONENTS:
  Aliases (install multiple):
    all                           All 6 components (backends + tools) - DEFAULT
    backends                      All backends: cli, tui, web
    tools                          All tools: ag, ai, prov-gen

  Individual:
    BACKENDS (interactive forms):
      cli                         CLI backend (step-by-step prompts)
      tui                         Terminal UI backend (3-panel interface)
      web                         Web backend (browser-based)

    TOOLS (provisioning):
      ag                          AI agents for automation & transpilation
      ai                          AI configuration assistant (HTTP server)
      prov-gen                    Provisioning structure generator

  Examples:
    all                           typedialog + typedialog-tui + typedialog-web + typedialog-ag + typedialog-ai + typedialog-prov-gen
    backends                      typedialog + typedialog-tui + typedialog-web
    cli,tui,ag                    typedialog + typedialog-tui + typedialog-ag (custom selection)

EXAMPLES:
  # Interactive mode (select what to install)
  $(basename "$0") --interactive

  # Install all components with defaults
  $(basename "$0") --components all

  # Install only backends
  $(basename "$0") --components backends

  # Install only tools
  $(basename "$0") --components tools

  # Custom selection
  $(basename "$0") --components cli,tui,prov-gen

  # Install specific version to system directory
  $(basename "$0") --version 0.1.0 --components all --install-dir /usr/local/bin

  # Verbose installation with validation
  $(basename "$0") --verbose --components all

ENVIRONMENT VARIABLES:
  TYPEDIALOG_INSTALL_DIR         Override default installation directory
  TYPEDIALOG_VERSION             Override version detection

EOF
}

# ============================================================================
# Parse Arguments
# ============================================================================

prompt_for_components() {
    echo ""
    print_info "Select what to install:"
    echo ""
    echo "  1) All components (backends + tools) - RECOMMENDED"
    echo "  2) Backends only (CLI, TUI, Web)"
    echo "  3) Tools only (AG, AI, ProvGen)"
    echo "  4) Custom selection"
    echo "  5) Cancel"
    echo ""
    read -rp "Choice [1-5]: " choice

    case "$choice" in
        1)  INSTALL_COMPONENTS="all" ;;
        2)  INSTALL_COMPONENTS="backends" ;;
        3)  INSTALL_COMPONENTS="tools" ;;
        4)
            echo ""
            echo "Available components:"
            echo "  Backends: cli, tui, web"
            echo "  Tools: ag, ai, prov-gen"
            echo ""
            read -rp "Enter comma-separated list (e.g., cli,tui,ag): " custom
            INSTALL_COMPONENTS="$custom"
            ;;
        5)
            print_info "Installation cancelled"
            exit 0
            ;;
        *)
            print_error "Invalid choice"
            exit 1
            ;;
    esac
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -v|--version)
                TYPEDIALOG_VERSION="$2"
                shift 2
                ;;
            -c|--components)
                INSTALL_COMPONENTS="$2"
                shift 2
                ;;
            -d|--install-dir)
                INSTALL_DIR="$2"
                shift 2
                ;;
            -i|--interactive)
                INTERACTIVE=true
                shift
                ;;
            --force)
                FORCE=true
                shift
                ;;
            --skip-validation)
                SKIP_VALIDATION=true
                shift
                ;;
            --verbose)
                VERBOSE=true
                shift
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                print_error "Unknown option: $1"
                show_help
                exit 1
                ;;
        esac
    done
}

# ============================================================================
# Main Entry Point
# ============================================================================

main() {
    parse_args "$@"

    print_header "TypeDialog Installation Suite"

    # Interactive mode
    if [[ "$INTERACTIVE" == "true" ]]; then
        prompt_for_components
    fi

    # Detect platform
    local os=$(detect_os) || exit 1
    local arch=$(detect_arch) || exit 1
    print_info "Platform: $os/$arch"

    # Determine version
    if [[ -z "$TYPEDIALOG_VERSION" ]]; then
        TYPEDIALOG_VERSION=$(extract_version_from_ncl "typedialog")
        if [[ -z "$TYPEDIALOG_VERSION" ]]; then
            print_error "Could not determine TypeDialog version"
            print_info "Please specify with: --version X.Y.Z"
            exit 1
        fi
    fi
    print_info "Version: $TYPEDIALOG_VERSION"

    # Determine install directory
    if [[ -z "$INSTALL_DIR" ]]; then
        INSTALL_DIR="${TYPEDIALOG_INSTALL_DIR:-$HOME/.local/bin}"
    fi
    print_info "Install directory: $INSTALL_DIR"

    # Display what will be installed
    print_info "Components to install: $INSTALL_COMPONENTS"
    echo ""

    # Add install directory to PATH if not already there
    if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
        export PATH="${INSTALL_DIR}:$PATH"
        debug "Added $INSTALL_DIR to PATH"
    fi

    # Ensure install directory exists
    ensure_install_dir "$INSTALL_DIR" || exit 1

    # Install selected components
    install_components "$INSTALL_COMPONENTS" "$TYPEDIALOG_VERSION" "$INSTALL_DIR" "$os" "$arch" || true

    # Validate installation
    if [[ "$SKIP_VALIDATION" != "true" ]]; then
        validate_all "$INSTALL_DIR" || {
            print_warning "Validation failed, but TypeDialog may still be functional"
        }
    fi

    echo ""
    print_success "Installation complete!"
    echo ""
    print_info "Next steps:"
    print_info "  1. Verify: typedialog --version && typedialog-tui --version && typedialog-prov-gen --version"
    print_info "  2. Setup: provisioning/scripts/setup-platform-config.sh"
    print_info "  3. Test forms: typedialog form <config.toml>"
    print_info "  4. Generate configs: typedialog-prov-gen generate --help"
    print_info "  5. Use AI assistant: typedialog-ai serve"
    echo ""
    print_info "Documentation:"
    print_info "  - provisioning/.typedialog/platform/README.md"
    print_info "  - provisioning/.typedialog/provisioning/form.toml"
    echo ""

    return 0
}

# Run main function
main "$@"
