#!/usr/bin/env bash
# Copyright (c) 2015-2026 Dotfiles. All rights reserved.
## Dotfiles Core Commands — Core chezmoi operations for the dot CLI.
##
## Provides apply, sync, update, add, diff, status, remove, cd, and edit
## commands for managing dotfiles through the unified dot interface.
##
## # Requirements
## - chezmoi: Dotfiles manager
## - bash 4+: Shell interpreter
##
## # Usage
## dot apply                   # Apply dotfiles
## dot sync                    # Alias for apply
## dot update                  # Pull and apply updates
## dot add <file>              # Add file to chezmoi
## dot diff                    # Show pending changes
## dot status                  # Show configuration drift
## dot remove <file>           # Remove managed file
## dot cd                      # Print source directory
## dot edit                    # Open source in editor
##
## # Platform Notes
## - All platforms: Full chezmoi support

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=../../../lib/dot/utils.sh
source "$SCRIPT_DIR/../../../lib/dot/utils.sh"

if [[ "${1:-}" != "cd" ]]; then
  dot_ui_command_banner "Core" "${1:-}"
fi

cmd_apply() {
  local src_dir
  src_dir="$(resolve_source_dir)"
  if [ -n "$src_dir" ] && [ -f "$src_dir/scripts/ops/chezmoi-apply.sh" ]; then
    exec bash "$src_dir/scripts/ops/chezmoi-apply.sh" "$@"
  fi
  exec chezmoi apply "$@"
}

cmd_sync() {
  cmd_apply "$@"
}

cmd_update() {
  local src_dir
  src_dir="$(resolve_source_dir)"
  if [ -n "$src_dir" ] && [ -f "$src_dir/scripts/ops/chezmoi-update.sh" ]; then
    exec bash "$src_dir/scripts/ops/chezmoi-update.sh" "$@"
  fi
  echo "Updating Dotfiles..."
  exec chezmoi update "$@"
}

cmd_add() {
  if [ -z "${1:-}" ]; then
    echo "Usage: dot add <file>"
    echo ""
    echo "Add a file to the chezmoi source directory."
    echo "The file will be managed by chezmoi from now on."
    exit 1
  fi
  exec chezmoi add "$@"
}

cmd_diff() {
  local src_dir
  src_dir="$(resolve_source_dir)"
  if [ -n "$src_dir" ] && [ -f "$src_dir/scripts/ops/chezmoi-diff.sh" ]; then
    exec bash "$src_dir/scripts/ops/chezmoi-diff.sh" "$@"
  fi
  exec chezmoi diff "$@"
}

cmd_status() {
  local out rc=0
  # Capture chezmoi's stderr too so an actual tool failure surfaces
  # to the user instead of being indistinguishable from a clean tree.
  out="$(chezmoi status "$@" 2>&1)" || rc=$?
  ui_header "Dotfiles Status"
  if [[ "$rc" -ne 0 ]]; then
    ui_err "chezmoi" "exited $rc"
    [[ -n "$out" ]] && printf "%s\n" "$out"
    return "$rc"
  fi
  if [[ -z "$out" ]]; then
    ui_ok "Clean" "no local drift detected"
  else
    printf "%s\n" "$out"
  fi
}

cmd_remove() {
  run_script "scripts/ops/chezmoi-remove.sh" "Remove helper" "$@"
}

cmd_cd() {
  local src_dir
  src_dir="$(resolve_source_dir)"
  if [ -n "$src_dir" ]; then
    echo "$src_dir"
  else
    echo "Dotfiles source not found." >&2
    exit 1
  fi
}

cmd_edit() {
  local src_dir
  src_dir="$(require_source_dir)"
  if [ -n "${EDITOR:-}" ]; then
    exec "$EDITOR" "$src_dir"
  elif has_command nvim; then
    exec nvim "$src_dir"
  elif has_command vim; then
    exec vim "$src_dir"
  else
    echo "No editor found. Set \$EDITOR to open $src_dir."
    exit 1
  fi
}

cmd_commit() {
  run_script "dot_local/bin/executable_git-ai-commit" "Git AI commit script" "$@"
}

cmd_clean_cache() {
  ui_info "Cache" "Clearing shell initialization caches"
  local cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}"
  rm -rf "$cache_dir/zsh"/*-init.zsh "$cache_dir/zsh"/*.zwc 2>/dev/null || true
  rm -rf "$cache_dir/bash"/*-init.bash 2>/dev/null || true
  rm -rf "$cache_dir/fish"/*-init.fish 2>/dev/null || true
  rm -rf "$cache_dir/nushell"/*.nu 2>/dev/null || true
  ui_info "Cache" "Cleared. Restart shell to regenerate"
}

# Dispatch
case "${1:-}" in
  apply)
    shift
    cmd_apply "$@"
    ;;
  sync)
    shift
    cmd_sync "$@"
    ;;
  update)
    shift
    cmd_update "$@"
    ;;
  add)
    shift
    cmd_add "$@"
    ;;
  diff)
    shift
    cmd_diff "$@"
    ;;
  status)
    shift
    cmd_status "$@"
    ;;
  remove)
    shift
    cmd_remove "$@"
    ;;
  cd)
    shift
    cmd_cd "$@"
    ;;
  edit)
    shift
    cmd_edit "$@"
    ;;
  commit)
    shift
    cmd_commit "$@"
    ;;
  clean-cache)
    shift
    cmd_clean_cache "$@"
    ;;
  *)
    echo "Unknown core command: ${1:-}" >&2
    exit 1
    ;;
esac
