# Shell experience — zsh (the default login shell, set system-side) with
# autosuggestions + syntax highlighting, a themed starship prompt, and
# modern CLI tools wired in: bat (cat), eza (ls), zoxide (cd). bat uses
# the "ansi" theme so it follows the terminal palette (Ghostty is themed
# from the same JSON); starship is themed from the palette directly.
#
# home.shell.enableZshIntegration = true is the single lever that makes
# every integrating program (starship, eza, zoxide, ghostty, yazi) emit
# its zsh hooks — no per-module flags needed.
{ config, lib, pkgs, ... }:

let
  cfg = config.nomarchy;
  t = cfg.theme;
  c = t.colors;
in
{
  config = lib.mkIf cfg.shell.enable {
    home.shell.enableZshIntegration = true;

    # rg/fd as themselves (NOT aliased over grep/find — their flags
    # differ enough to surprise). Available regardless of yazi/rofi.
    home.packages = with pkgs; [ ripgrep fd ];

    programs.zsh = {
      enable = true;
      enableCompletion = true;
      autosuggestion.enable = true;
      syntaxHighlighting.enable = true;
      autocd = true;
      history = {
        size = 50000;
        save = 50000;
        ignoreDups = true;
        ignoreSpace = true;
        expireDuplicatesFirst = true;
      };
      # Curated, on by default. The rule (same as rg/fd above): short where
      # it helps, but never shadow a real binary — so the git block keeps off
      # `gs` (ghostscript), and nothing here masks a coreutil.
      shellAliases = {
        cat = "bat --paging=never";
        less = "bat";
        grep = "grep --color=auto";
        # eza enableZshIntegration aliases ls/ll/la; add a couple extras.
        lt = "eza --tree --level=2 --icons=auto --group-directories-first";
        tree = "eza --tree --icons=auto --group-directories-first";

        # Navigation — climb without counting dots.
        ".." = "cd ..";
        "..." = "cd ../..";
        "...." = "cd ../../..";

        # Git — the verbs you retype all day.
        g = "git";
        gst = "git status -sb";
        ga = "git add";
        gaa = "git add -A";
        gc = "git commit";
        gcm = "git commit -m";
        gco = "git checkout";
        gsw = "git switch";
        gb = "git branch";
        gd = "git diff";
        gds = "git diff --staged";
        gl = "git log --oneline --graph --decorate -20";
        glg = "git log --oneline --graph --decorate --all";
        gp = "git push";
        gpl = "git pull";
        gf = "git fetch --all --prune";

        # Nix — the flake/store verbs (system/home rebuilds already have the
        # sys-update / home-update commands, so they're not re-aliased here).
        ns = "nix shell"; # ns nixpkgs#ripgrep
        nr = "nix run"; # nr nixpkgs#cowsay
        nfu = "nix flake update";
        nfc = "nix flake check";
        nsearch = "nix search nixpkgs";
        ngc = "nix-collect-garbage -d"; # user generations; sudo for system roots

        # Misc.
        path = "echo $PATH | tr ':' '\\n'";
        reload = "exec zsh";
      };
    };

    programs.starship = {
      enable = true;
      settings = {
        add_newline = false;
        palette = "nomarchy";
        # starship wants full #rrggbb (or names) — keep the leading #.
        palettes.nomarchy = {
          inherit (c) base text accent good warn bad subtext;
        };
        # Flat prompt — colored text only, no powerline separators or
        # background fills. Each module emits its own trailing space so
        # there are no stray gaps when git/duration are absent.
        format = lib.concatStrings [
          "$directory"
          "$git_branch"
          "$git_status"
          "$cmd_duration"
          "$character"
        ];
        directory = {
          style = "bold accent";
          format = "[$path]($style) ";
          truncation_length = 3;
          truncate_to_repo = true;
        };
        git_branch = {
          style = "warn";
          format = "[$symbol$branch]($style) ";
          symbol = " ";
        };
        git_status = {
          style = "subtext";
          # Parenthesised → the segment (and its trailing space) only
          # render when there's actually a status to show.
          format = "([$all_status$ahead_behind]($style) )";
        };
        character = {
          success_symbol = "[❯](good)";
          error_symbol = "[❯](bad)";
        };
        cmd_duration = {
          min_time = 2000;
          style = "subtext";
          format = "[ $duration]($style) ";
        };
      };
    };

    # bat: "ansi" follows the terminal's 16-color palette → tracks the
    # active Nomarchy theme (Ghostty bakes it) with no per-theme config.
    programs.bat = {
      enable = true;
      config = {
        theme = "ansi";
        style = "numbers,changes,header";
      };
    };

    programs.eza = {
      enable = true;
      icons = "auto";
      git = true;
      extraOptions = [ "--group-directories-first" ];
    };

    programs.zoxide = {
      enable = true;
      options = [ "--cmd cd" ]; # `cd` becomes the smart jumper (z under the hood)
    };
  };
}
