#!/usr/bin/env bash
#
# dotfiles-link - Symlink dotfiles without Nix
#
# Usage: dotfiles-link [--dry-run] [--force]
#
# Reads MANIFEST file from dotfiles root and creates symlinks accordingly.
# Works on both Linux and macOS (Darwin).
#

set -euo pipefail

# ============================================================================
# Configuration
# ============================================================================

DOTFILES_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CONFIG_DIR="${DOTFILES_DIR}/config"
MANIFEST="${DOTFILES_DIR}/MANIFEST"

# Detect OS
case "$(uname -s)" in
Darwin) OS="darwin" ;;
Linux) OS="linux" ;;
*)
    echo "Unsupported OS: $(uname -s)" >&2
    exit 1
    ;;
esac

# XDG config directory
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"

# ============================================================================
# Functions
# ============================================================================

DRY_RUN=true
FORCE=false

usage() {
    echo "Usage: $(basename "$0") [--apply] [--force]"
    echo ""
    echo "Options:"
    echo "  --apply    Actually create symlinks (dry-run is default)"
    echo "  --force    Remove existing files/symlinks before linking"
    echo ""
    echo "Manifest: ${MANIFEST}"
    echo "Detected OS: ${OS}"
}

log() {
    echo "[dotfiles-link] $*"
}

# Expand variables in target path
expand_path() {
    local path="$1"
    # Use eval to expand $HOME and $XDG_CONFIG_HOME
    eval echo "$path"
}

create_symlink() {
    local source="$1"
    local target="$2"
    local target_dir
    target_dir="$(dirname "$target")"

    # Check if source exists
    if [[ ! -e $source ]]; then
        log "SKIP: Source does not exist: $source"
        return
    fi

    # Create parent directory if needed
    if [[ ! -d $target_dir ]]; then
        if $DRY_RUN; then
            log "WOULD CREATE DIR: $target_dir"
        else
            log "CREATE DIR: $target_dir"
            mkdir -p "$target_dir"
        fi
    fi

    # Handle existing target
    if [[ -e $target || -L $target ]]; then
        if [[ -L $target ]] && [[ "$(readlink "$target")" == "$source" ]]; then
            log "OK: $target (already linked)"
            return
        fi

        if $FORCE; then
            if $DRY_RUN; then
                log "WOULD REMOVE: $target"
            else
                log "REMOVE: $target"
                rm -rf "$target"
            fi
        else
            log "SKIP: $target exists (use --force to override)"
            return
        fi
    fi

    # Create symlink
    if $DRY_RUN; then
        log "WOULD LINK: $target -> $source"
    else
        log "LINK: $target -> $source"
        ln -s "$source" "$target"
    fi
}

process_manifest() {
    if [[ ! -f $MANIFEST ]]; then
        log "ERROR: Manifest not found: $MANIFEST"
        exit 1
    fi

    while IFS= read -r line || [[ -n $line ]]; do
        # Skip comments and empty lines
        [[ -z $line || $line =~ ^[[:space:]]*# ]] && continue

        # Parse: os:source:target
        local entry_os="${line%%:*}"
        local rest="${line#*:}"
        local source="${rest%%:*}"
        local target="${rest#*:}"

        # Check if this entry applies to current OS
        if [[ $entry_os != "common" && $entry_os != "$OS" ]]; then
            continue
        fi

        # Expand variables and create symlink
        target="$(expand_path "$target")"
        create_symlink "${CONFIG_DIR}/${source}" "$target"
    done <"$MANIFEST"
}

# ============================================================================
# Main
# ============================================================================

# Parse arguments
while [[ $# -gt 0 ]]; do
    case "$1" in
    --apply)
        DRY_RUN=false
        shift
        ;;
    --force)
        FORCE=true
        shift
        ;;
    -h | --help)
        usage
        exit 0
        ;;
    *)
        echo "Unknown option: $1"
        usage
        exit 1
        ;;
    esac
done

log "Dotfiles directory: ${DOTFILES_DIR}"
log "OS: ${OS}"
$DRY_RUN && log "DRY RUN MODE - no changes will be made"
echo ""

process_manifest

echo ""
log "Done!"
