#!/bin/zsh

# NAVIGATION AND FILE SYSTEM
z() {
  unfunction "$0"
  eval "$(zoxide init zsh)"
  $0 "$@"
}

zi() { z "$@" }
za() { z "$@" }
zrm() { zoxide remove "$@" }

function open {
  for i in $*; do
    setsid nohup xdg-open $i > /dev/null 2> /dev/null
  done
}

function fopen() {
  local selected
  selected=$(fd "$@" | fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}')
  [[ -n "$selected" ]] && setsid nohup xdg-open "$selected" >/dev/null 2>&1 &
}

# DEVELOPMENT TOOLS
# Package manager detection with caching
function _package_manager {
  local pkg_manager=""
  if [[ -f bun.lockb ]]; then
    pkg_manager="bun"
  elif [[ -f pnpm-lock.yaml ]]; then
    pkg_manager="pnpm"
  elif [[ -f yarn.lock ]]; then
    pkg_manager="yarn"
  elif [[ -f package-lock.json ]]; then
    pkg_manager="npm"
  else
    pkg_manager="pnpm"
  fi

  if [[ -f package.json ]] && [[ $1 != "run" ]] && [[ $1 != "install" ]] && [[ $1 != "add" ]] && [[ $1 != "remove" ]] && [[ $1 != "i" ]] && [[ $1 != "rm" ]]; then
    if jq -e ".scripts[\"$1\"] != null" package.json >/dev/null 2>&1; then
      set -- "run" "$@"
    fi
  fi

  if command -v corepack >/dev/null 2>&1; then
    corepack ${pkg_manager} "$@"
  else
    command ${pkg_manager} "$@"
  fi
}

# Improved development commit with optional message
function dc() {
  if ! git rev-parse --is-inside-work-tree &>/dev/null; then
    echo "Error: Not in a git repository"
    return 1
  fi

  if [[ -z $(git status --porcelain) ]]; then
    echo "No changes to commit"
    return 0
  fi

  git add .

  local commit_msg
  if [[ -n "$1" ]]; then
    commit_msg="$1"
  else
    local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    commit_msg="dev: automated commit - ${timestamp}"
  fi

  git commit -m "$commit_msg" --no-gpg-sign
  git push &>/dev/null || { echo "Push failed"; return 1; }
}

# Git branch cleanup helper
function git-clean() {
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  local branches_to_delete=$(git branch --merged | grep -v "^\*" | grep -v "master" | grep -v "main" | grep -v "develop")

  if [[ -z "$branches_to_delete" ]]; then
    echo "No merged branches to clean up"
    return 0
  fi

  echo "The following merged branches will be deleted:"
  echo "$branches_to_delete"
  echo -n "Continue? [y/N] "
  read confirm

  if [[ "$confirm" =~ ^[Yy]$ ]]; then
    echo "$branches_to_delete" | xargs git branch -d
    echo "Branches deleted locally"

    echo -n "Delete remote branches too? [y/N] "
    read confirm_remote

    if [[ "$confirm_remote" =~ ^[Yy]$ ]]; then
      echo "$branches_to_delete" | xargs -I{} git push origin --delete {}
      echo "Remote branches deleted"
    fi
  fi
}

function sm { /opt/sublime_merge/sublime_merge $1; }

function vimrc {
  cd $XDG_CONFIG_HOME/nvim
  nvim
  cd - >/dev/null
}

function zshrc {
  cd $XDG_CONFIG_HOME/zsh
  nvim
  cd - >/dev/null
}

# FILE SHARING AND NETWORKING
function upload_file() {
  local usage="Usage: $0 [-o] <file>"
  local one_time=true

  # Parse options
  while getopts ":o" opt; do
    case ${opt} in
      o ) one_time=false ;;
      \? )
        echo "Invalid option: -$OPTARG" >&2
        echo $usage
        return 1 ;;
    esac
  done
  shift $((OPTIND -1))

  # Check file argument
  if [[ -z "$1" ]]; then
    echo $usage
    return 1
  fi
  if [[ ! -f "$1" ]]; then
    echo "Error: File not found: $1"
    return 1
  fi

  local url="https://drop.mz.uy"
  echo "Uploading $1 to $url... (one-time: ${one_time})"

  # Prepare upload options
  local form_data=("-F" "file=@$1")
  if $one_time; then
    form_data+=("-F" "one_time=")
  fi

  # Try up to 3 times with a short delay between attempts
  local max_attempts=3
  local attempt=1
  local success=false

  while (( attempt <= max_attempts )) && ! $success; do
    if (( attempt > 1 )); then
      echo "Retry attempt $attempt of $max_attempts..."
      sleep 1
    fi

    local full_response=$(curl -i "${form_data[@]}" "$url" 2>/dev/null)
    local curl_status=$?

    if [[ $curl_status -eq 0 ]]; then
      local url_response=$(echo "$full_response" | tail -n 1)
      local token=$(echo "$full_response" | grep -i "X-Token:" | awk '{print $2}' | tr -d '\r')

      if [[ -n "$url_response" ]]; then
        echo -n "$url_response" | wl-copy
        echo "✓ Uploaded: $url_response (copied to clipboard)"

        if [[ -n "$token" ]]; then
          echo "Management token: $token"
        fi

        success=true
        break
      fi
    fi

    (( attempt++ ))
  done

  if ! $success; then
    echo "× Failed to upload file after $max_attempts attempts"
    return 1
  fi
}

function expose() {
  if [ -z "$1" ]; then
    echo "Usage: expose <port>"
    return 1
  fi
  ssh marianozunino@srv.us -R 1:localhost:$1
}

function ppid {
  lsof -i :$1
}

alias pport="ppid"

# KUBERNETES AND DEVOPS
function kf {
  if [ -z "$1" ]; then
    echo "Usage: kf <cluster> [service-name]"
    return 1
  fi

  local namespace="oc-app"
  local cluster="oc-$1-eks-cluster"
  local svc_filter=""

  if [ ! -z "$2" ]; then
    svc_filter="-l app.kubernetes.io/instance=$2"
  fi

  sudo -E kubefwd svc -n ${namespace} -x ${cluster} ${svc_filter}
}

# SYSTEM AND UTILITY FUNCTIONS
# Lazy-load handler for heavy tools
function _lazy_load() {
  local cmd="$1"
  local loader="$2"

  eval "${cmd}() {
    unfunction $cmd
    eval \"\$($loader)\"
    $cmd \"\$@\"
  }"
}

# Example: lazy load kubectl completion
_lazy_load kubectl "kubectl completion zsh"

function wacom {
    if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
        systemctl --user enable opentabletdriver --now
        otd loadsettings ~/Sync/wacom/wacom.json
    else
        xsetwacom --set "Wacom One by Wacom S Pen stylus" ResetArea
        xsetwacom --set "Wacom One by Wacom S Pen stylus" MapToOutput DisplayPort-0
        xsetwacom --set "Wacom One by Wacom S Pen stylus" Rotate half

        xsetwacom --set "Wacom One by Wacom S Pen eraser" ResetArea
        xsetwacom --set "Wacom One by Wacom S Pen eraser" MapToOutput DisplayPort-0
    fi
}

function cat {
    if [ -n "$SSH_TTY" ] || [ -n "$SSH_CLIENT" ] || [ -n "$SSH_CONNECTION" ]; then
        bat --plain --paging=never "$@"
    else
        bat "$@"
    fi
}

function _has {
  return $( whence $1 >/dev/null )
}

# History-based directory navigation
function cdr {
  local dir
  dir=$(dirs -pl | awk '!x[$0]++' | fzf --height 40% --reverse)
  [[ -n "$dir" ]] && cd "$dir"
}

if [[ -v TMUX ]]; then
  function swaymsg {
    export SWAYSOCK=$XDG_RUNTIME_DIR/sway-ipc.$UID.$(pgrep -x sway).sock
    command swaymsg "$@"
  }
fi

# COMPLETIONS
for completion_file in ~/.local/share/zsh/*-autocomplete.zsh; do
    echo $completion_file
    if [ -f "$completion_file" ]; then
        source "$completion_file"
    fi
done

if command -v rop &> /dev/null; then eval "$(rop completion zsh)"; fi
if command -v goq &> /dev/null; then eval "$(goq completion zsh)"; fi
if command -v kubefwd &> /dev/null; then eval "$(kubefwd completion zsh)"; fi
if command -v bombadil &> /dev/null; then eval "$(bombadil generate-completions zsh)"; fi
if command -v eza &> /dev/null; then compdef eza=ls; fi

alias dev='~/Dev/marianozunino/dev/dev'
alias p='_package_manager'
alias fo='fopen'
alias drop='upload_file'
alias dump='upload_file'
alias pport=ppid
alias unChonk="echo '🧹 Starting the great node_modules purge...' && find . -name 'node_modules' -type d -prune -exec sh -c 'echo \"💥 Deleting {}\" && rm -rf \"{}\"' \;"
