# Version control: git + delta + commitizen + lazygit. Committer identity comes
# from the per-user `identity` arg (the registry). See README "Users".
{
  pkgs,
  lib,
  identity,
  ...
}:
let
  ctp = import ../lib/catppuccin-mocha.nix;
in
{
  home.packages = [
    pkgs.commitizen
  ];

  programs.git = {
    enable = true;
    package = pkgs.gitFull;
    settings = {
      user.name = identity.fullName;
      # mkDefault so a host-specific module can still override it.
      user.email = lib.mkDefault identity.email;
      push.autoSetupRemote = true;
      init.defaultBranch = "main";

      # Rebase-centric pulls (matches the "always a branch, linear history"
      # workflow); stash/restore and reorder fixups automatically.
      pull.rebase = true;
      rebase = {
        autoStash = true;
        autoSquash = true;
      };

      fetch.prune = true; # drop deleted remote-tracking branches
      # Keep the commit-graph current (fast `git log --graph`, used by `lg`).
      fetch.writeCommitGraph = true;
      gc.writeCommitGraph = true;
      merge.conflictStyle = "zdiff3"; # show the common ancestor in conflicts
      diff = {
        algorithm = "histogram";
        colorMoved = "default";
      };
      rerere.enabled = true; # remember + replay conflict resolutions

      # delta pager config (programs.delta is enabled below, with git
      # integration; these keys land under [delta] in the git config).
      # syntax-theme reuses the Catppuccin Mocha tmTheme vendored for bat in
      # shell.nix -- delta reads bat's theme directory.
      delta = {
        syntax-theme = "Catppuccin Mocha";
        navigate = true; # n/N to jump between diff hunks
        line-numbers = true;
        side-by-side = true;
      };
      commit.verbose = true; # full diff in the commit-message editor
      branch.sort = "-committerdate"; # most-recent branches first
      column.ui = "auto";
      help.autocorrect = "prompt";

      alias = {
        st = "status";
        co = "checkout";
        sw = "switch";
        br = "branch";
        ci = "commit";
        last = "log -1 HEAD";
        unstage = "reset HEAD --";
        amend = "commit --amend --no-edit"; # tack staged changes onto HEAD
        fixup = "commit --fixup"; # `git fixup <sha>` -> autosquash on next rebase
        undo = "reset --soft HEAD~1"; # undo last commit, keep the changes staged
        lg = "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' --all";
        # commitizen (Conventional Commits, its default ruleset): `git cz c` ->
        # `cz commit`, `git cz bump`, etc. `git cc` is a shortcut for the prompt.
        cz = "!cz";
        cc = "!cz commit";
      };

      # SSH signing, key from the registry. mkDefault so a host lacking the key
      # in its agent can set gpgsign = false instead of failing every commit.
      gpg.format = "ssh";
      user.signingkey = lib.mkDefault identity.signingKey;
      commit.gpgsign = lib.mkDefault true;
      tag.gpgsign = lib.mkDefault true;
    };

    # Global ignore file (~/.config/git/ignore).
    ignores = [
      "result"
      "result-*"
      ".direnv"
      "*.swp"
      ".DS_Store"
    ];
  };

  programs.delta = {
    enable = true;
    enableGitIntegration = true;
  };

  # lazygit: TUI for staging/rebasing, themed to Catppuccin Mocha to match.
  programs.lazygit = {
    enable = true;
    settings.gui.theme = {
      activeBorderColor = [
        "#${ctp.blue}"
        "bold"
      ];
      inactiveBorderColor = [ "#${ctp.surface1}" ];
      selectedLineBgColor = [ "#${ctp.surface0}" ];
    };
  };
}
