#!/bin/bash
#
# Get Stuff Done (GSD) Launcher
# Sets up environment and launches Claude Code with GSD configuration
#

set -euo pipefail

# =============================================================================
# Path Normalization
# =============================================================================
# Node.js on Windows requires Windows-style paths (C:/...) but POSIX-layer
# shells (MSYS2, Cygwin, MinGW) use POSIX-style paths (/c/...).
#
# This function normalizes paths once at startup so downstream Node.js code
# works correctly. The `cygpath` utility is the standard way to detect and
# convert paths in these environments.
#
# Coverage:
#   - Git Bash, MSYS2, Cygwin, MinGW: cygpath converts /c/... to C:/...
#   - WSL, macOS, Linux: Native paths pass through unchanged
#   - Any terminal emulator (Windows Terminal, ConEmu, iTerm2, etc.): Works
#     automatically based on underlying shell
# =============================================================================
normalize_path() {
    local path="$1"
    if command -v cygpath &>/dev/null; then
        cygpath -m "$path"
    else
        echo "$path"
    fi
}

# Configuration paths (normalized for cross-platform Node.js compatibility)
GSD_HOME="$(normalize_path "${GSD_HOME:-${HOME}/.gsd}")"
GSD_CONFIG="${GSD_CONFIG:-${GSD_HOME}/config.json}"
GSD_PROJECT_CONFIG=".gsd/config.json"

# Colors (if terminal supports)
if [[ -t 1 ]]; then
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[0;33m'
    BLUE='\033[0;34m'
    NC='\033[0m' # No Color
else
    RED='' GREEN='' YELLOW='' BLUE='' NC=''
fi

# Detect GSD installation directory (where this script lives)
# Works with symlinks by resolving the actual script location
GSD_INSTALL_DIR="$(normalize_path "$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || echo "${BASH_SOURCE[0]}")")" && cd .. && pwd)")"

# Log functions
log_info() { echo -e "${BLUE}[GSD]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[GSD]${NC} $1"; }
log_error() { echo -e "${RED}[GSD]${NC} $1" >&2; }

# Read config value using Node.js ConfigLoader (handles JSON5, validation, defaults)
read_config() {
    local key="$1"
    local default="$2"

    GSD_INSTALL_DIR="$GSD_INSTALL_DIR" \
    GSD_CONFIG_KEY="$key" \
    GSD_CONFIG_DEFAULT="$default" \
    node -e '
        const {loadConfig, getConfigValue} = require(process.env.GSD_INSTALL_DIR + "/src/config/ConfigLoader");
        try {
            const config = loadConfig();
            const val = getConfigValue(config, process.env.GSD_CONFIG_KEY, process.env.GSD_CONFIG_DEFAULT);
            console.log(val);
        } catch (e) {
            console.error("Config error:", e.message);
            console.log(process.env.GSD_CONFIG_DEFAULT);
        }
    ' 2>/dev/null || echo "$default"
}

# Ensure config directory exists
ensure_config() {
    if [[ ! -d "$GSD_HOME" ]]; then
        log_info "Creating GSD home directory: $GSD_HOME"
        mkdir -p "$GSD_HOME"
        mkdir -p "$GSD_HOME/hooks"
    fi

    if [[ ! -f "$GSD_CONFIG" ]]; then
        log_info "Creating default configuration"
        cat > "$GSD_CONFIG" << 'EOF'
{
  "version": 1,
  "context_management": {
    "precompact_save_state": true
  },
  "workflow": {
    "pause_between_tasks": false,
    "pause_between_phases": true,
    "auto_checkpoint_interval": 5
  },
  "subagents": {
    "default_model": "sonnet",
    "executor_model": "sonnet",
    "verifier_model": "sonnet",
    "researcher_model": "haiku"
  },
  "ui": {
    "show_progress_bar": true,
    "show_context_usage": true,
    "theme": "aidev"
  }
}
EOF
    fi

    # Migrate legacy configs: add version field if missing
    # Note: GSD_CONFIG is already normalized at startup via normalize_path()
    if [[ -f "$GSD_CONFIG" ]]; then
        local has_version
        has_version=$(GSD_INSTALL_DIR="$GSD_INSTALL_DIR" GSD_CONFIG="$GSD_CONFIG" \
            node -e '
                const JSON5 = require(process.env.GSD_INSTALL_DIR + "/node_modules/json5");
                const fs = require("fs");
                try {
                    const config = JSON5.parse(fs.readFileSync(process.env.GSD_CONFIG, "utf8"));
                    console.log(config.version ? "yes" : "no");
                } catch (e) {
                    console.log("no");
                }
            ' 2>/dev/null || echo "no")

        if [[ "$has_version" == "no" ]]; then
            log_info "Adding version field to config"
            GSD_INSTALL_DIR="$GSD_INSTALL_DIR" GSD_CONFIG="$GSD_CONFIG" \
                node -e '
                    const JSON5 = require(process.env.GSD_INSTALL_DIR + "/node_modules/json5");
                    const fs = require("fs");
                    const config = JSON5.parse(fs.readFileSync(process.env.GSD_CONFIG, "utf8"));
                    config.version = 1;
                    fs.writeFileSync(process.env.GSD_CONFIG, JSON.stringify(config, null, 2));
                ' 2>/dev/null || log_warn "Could not migrate config - please add version: 1 manually"
        fi
    fi
}

# Main
main() {
    ensure_config

    # Read configuration
    local show_context=$(read_config 'ui.show_context_usage' 'true')

    # Note: Autocompact threshold is controlled by Claude Code internally.
    # CLAUDE_AUTOCOMPACT_PCT_OVERRIDE env var exists but has a known bug
    # (https://github.com/anthropics/claude-code/issues/18843).
    # GSD statusline shows proximity to autocompact using Claude's own reporting.

    # Display startup banner
    echo ""
    echo -e "${GREEN}Get Stuff Done${NC} v2.0"
    echo "────────────────────────────────"

    # Check for existing project state
    if [[ -f ".planning/STATE.md" ]]; then
        echo -e "Project state: ${GREEN}Found${NC} (.planning/STATE.md)"
    fi

    if [[ -f ".planning/CONTINUE.md" ]]; then
        echo -e "Continuation: ${YELLOW}Available${NC} (.planning/CONTINUE.md)"
    fi

    echo "────────────────────────────────"
    echo ""

    # Pass through any arguments to claude
    exec claude "$@"
}

main "$@"
