# ~/.zshrc
#
# A PLAIN FILE. Not a chezmoi template, deliberately.
#
# Templating this file is what broke sync-back: `chezmoi re-add` silently does
# nothing on a .tmpl, so every edit made here had to be hand-copied into the
# source or lost. Platform differences are handled at runtime below, by zsh,
# which it is perfectly capable of doing.
#
# NO SECRETS LIVE HERE. Keys come from ~/.config/zsh/secrets.zsh, which is
# generated from Bitwarden Secrets Manager, mode 600, and in no repository.
# If that file is absent this shell still works — you just have no API keys.

# ---------------------------------------------------------------- platform ---
# Set before anything else; everything below branches on these instead of on
# chezmoi template conditionals.
typeset -g _mac=0 _lin=0 _wsl=0 _ubuntu=0
[[ $OSTYPE == darwin* ]] && _mac=1
[[ $OSTYPE == linux*  ]] && _lin=1
[[ -n $WSL_DISTRO_NAME || -r /proc/sys/fs/binfmt_misc/WSLInterop ]] && _wsl=1
(( _lin )) && [[ -r /etc/os-release ]] && \
  grep -qi '^ID=ubuntu' /etc/os-release && _ubuntu=1

# ----------------------------------------------------------------- secrets ---
# One guarded source, and it is the only path by which a key enters this shell.
# Regenerate with `dotsecrets`. Never edit by hand, never commit.
[[ -r ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/secrets.zsh ]] && \
  source ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/secrets.zsh

# The bws token itself is a file, not a secret in this file. It is what lets
# `bws` and `dotsecrets` run at all.
[[ -r $HOME/.config/bitwarden/bws-token ]] && \
  export BWS_ACCESS_TOKEN="$(<$HOME/.config/bitwarden/bws-token)"

# --------------------------------------------------------- pre-prompt setup ---
# Anything that must be set before the p10k instant prompt goes here. Nothing
# in this section may write to stdout.
export ZSH_AI_PROVIDER="gemini"
export ZSH_AI_GEMINI_MODEL="gemini-2.5-flash"

# Endpoint, not a credential — the matching key comes from secrets.zsh.
export ZAI_BASE_URL="https://api.z.ai/api/anthropic"

(( _ubuntu )) && {
  export GDK_BACKEND=wayland
  export QT_QPA_PLATFORM=wayland
  export CLUTTER_BACKEND=wayland
  export SDL_VIDEODRIVER=wayland
}

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# -------------------------------------------------------------------- PATH ---
# `typeset -U` makes $path a unique-only array, so ordering is intentional and
# duplicates are impossible — which is what the eight scattered appends and the
# doubled ~/.local/bin used to produce.
typeset -U path PATH
_prepend() { [[ -d $1 ]] && path=("$1" $path) }
_append()  { [[ -d $1 ]] && path=($path "$1") }

_prepend "$HOME/bin"
_prepend "$HOME/.local/bin"
_prepend "$HOME/.npm-global/bin"
_prepend "$HOME/code/speccy/bin"
_append  /usr/local/bin
_append  /usr/local/go/bin

export GOPATH="$HOME/go"
export GOMODCACHE="$GOPATH/pkg/mod"
_prepend "$GOPATH/bin"

_append "$HOME/.cache/lm-studio/bin"

(( _mac )) && {
  _prepend /opt/homebrew/bin
  _prepend /opt/homebrew/sbin
  _prepend /opt/homebrew/opt/hcxtools/bin
  [[ -n $BUN_INSTALL ]] && _prepend "$BUN_INSTALL/bin"
  export TERMINFO=/Applications/Ghostty.app/Contents/Resources/terminfo

  # Garmin Connect IQ SDK (tracks the SDK selected in current-sdk.cfg)
  _ciq="$HOME/Library/Application Support/Garmin/ConnectIQ/current-sdk.cfg"
  [[ -f $_ciq ]] && _append "$(<"$_ciq")bin"
  unset _ciq
}

(( _lin )) && {
  _append /usr/libexec/virtiofsd
  _append "$HOME/code/vp9enc-rs/target/release"
}

(( _ubuntu )) && export LD_LIBRARY_PATH="/opt/Qt-6.7.3/lib:$LD_LIBRARY_PATH"

unfunction _prepend _append

# ------------------------------------------------------------------ limits ---
ulimit -n 65535
(( _mac )) && ulimit -u 2048 || ulimit -u 65535

# ------------------------------------------------------------------ oh-my-zsh -
export ZSH="$HOME/.oh-my-zsh"
export ZSH_CUSTOM="${ZSH_CUSTOM:-$ZSH/custom}"
ZSH_THEME="powerlevel10k/powerlevel10k"

plugins=(git zsh-autosuggestions sudo web-search dirhistory history)
(( _mac )) && plugins+=(docker)

# zsh-ai is loaded HERE and only here. It used to be added to this array on
# every platform AND separately sourced from /opt/homebrew on macOS, so it
# loaded twice on mac. The existence guard also stops the array referencing a
# plugin that was never installed.
[[ -z $ZSH_AI_DISABLE && -d $ZSH_CUSTOM/plugins/zsh-ai ]] && plugins+=(zsh-ai)

# Guarded. Unguarded, a clean bootstrap produces a broken login shell and
# nothing tells you why.
if [[ -r $ZSH/oh-my-zsh.sh ]]; then
  source $ZSH/oh-my-zsh.sh
else
  print -u2 "zshrc: oh-my-zsh missing at $ZSH — run dotup to install it"
fi

zle -N create_completion
bindkey '^B' create_completion

[[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh

# ----------------------------------------------------------------- aliases ---
(( _ubuntu )) && alias fd=fdfind
(( _mac )) && {
  alias py="/opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13/bin/python3"
  alias tailscale="/Applications/Tailscale.app/Contents/MacOS/Tailscale"
}

alias umpv="$HOME/code/mpv/TOOLS/umpv"
(( _lin )) && {
  alias lada-runner="LADA_RUNNER_CONCURRENCY=2 uv --directory $HOME/tools/lada-runner run lada-runner tui"
  alias lada-cli="flatpak run --filesystem=host --command=lada-cli io.github.ladaapp.lada"
}

# Work Claude account — separate creds/history/projects, shared CLAUDE.md+rules+skills+agents
alias wclaude='CLAUDE_CONFIG_DIR=$HOME/.claude-work claude'

# A function, not an alias. As an alias the token was expanded into the alias
# body at definition time, so `alias` printed the key in full to anyone who ran
# it. A function defers expansion to call time.
glm() {
  ANTHROPIC_BASE_URL="$ZAI_BASE_URL" ANTHROPIC_AUTH_TOKEN="$ZAI_API_KEY" \
    claude --dangerously-skip-permissions \
           --settings "$HOME/.claude/settings-glm.json" "$@"
}

_open() { (( _mac )) && open "$1" || xdg-open "$1" >/dev/null 2>&1 }

# ------------------------------------------------------------------- local ---
# Identity-bearing shell config -- the gitea aliases and their WAN/LAN hosts,
# work shortcuts, anything naming a host you own -- lives in the PRIVATE tier,
# which writes this file. It is absent on a public-only machine, and the guard
# makes that a silent no-op. `_mac` and `_open` above are still in scope here,
# so a moved alias needs no rewriting.
[[ -r ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/local.zsh ]] && \
  source ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/local.zsh

# ---------------------------------------------------------------- homebrew ---
if (( _mac )); then
  eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv)"
elif [[ -x /home/linuxbrew/.linuxbrew/bin/brew ]]; then
  eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
fi

# ---------------------------------------------------------------- bitwarden ---
# Interactive personal-vault unlock. Nothing automated depends on this; the
# unattended path is bws + the token file above.
if command -v bw >/dev/null 2>&1; then
  bwunlock() {
    export BW_SESSION="$(bw unlock --raw)"
    print "Bitwarden unlocked. Session expires based on your timeout setting."
  }
fi

export ZSH_CODEX_PYTHON="$HOME/.local/venvs/codex/bin/python"

# iris was removed here. Do NOT add `eval "$(iris init zsh)"` — it emits
# `exec iris`, which replaces every interactive shell, and combined with the
# p10k instant prompt above (upstream #55) logins fork-cascade until SSH
# appears frozen. See the sysjournal note before reintroducing it.

unset _mac _lin _wsl _ubuntu
