{config, pkgs, ...}:
{
  # ── Identity ────────────────────────────────────────────────────────────────
  home.username = "ulve";
  home.homeDirectory = "/home/ulve";
  home.stateVersion = "26.05";

  # ── Shell ───────────────────────────────────────────────────────────────────
  programs.bash = {
    enable = true;
    shellAliases = {
      n = "nvim";
      rebuild = "sudo nixos-rebuild switch --flake ~/nixos-dotfiles";
    };
  };

  programs.zsh = {
    enable = true;
    syntaxHighlighting.enable = true;
    plugins = [
      {
        name = "fzf-tab";
        src = "${pkgs.zsh-fzf-tab}/share/fzf-tab";
      }
    ];
    shellAliases = {
      n = "nvim";
      rebuild = "sudo nixos-rebuild switch --flake ~/nixos-dotfiles";
      tree = "eza --tree --level=2";
      ls = "eza --icons --all --header --long --git";
    };
    history = {
      size = 10000;
      save = 10000;
      ignoreDups = true;
      share = true;
      extended = true;
    };
    initContent = ''
      zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'

      autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
      zle -N up-line-or-beginning-search
      zle -N down-line-or-beginning-search
      bindkey "^[[A" up-line-or-beginning-search
      bindkey "^[[B" down-line-or-beginning-search
      bindkey "^[OA" up-line-or-beginning-search
      bindkey "^[OB" down-line-or-beginning-search

      function mkenv() {
        local template="$HOME/nixos-dotfiles/templates/shell-''${1}.nix"
        if [[ -z "$1" ]]; then
          echo "Usage: mkenv <python|go|ts|csharp>"
          return 1
        fi
        if [[ ! -f "$template" ]]; then
          echo "No template for '$1'. Available: python, go, ts, csharp"
          return 1
        fi
        if [[ -f shell.nix ]]; then
          echo "shell.nix already exists"
          return 1
        fi
        cp "$template" shell.nix
        echo "use nix" > .envrc
        direnv allow
        echo "Created shell.nix and .envrc for $1"
      }

      function y() {
        local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd
        command yazi "$@" --cwd-file="$tmp"
        IFS= read -r -d "" cwd < "$tmp"
        [ -n "$cwd" ] && [ "$cwd" != "$PWD" ] && builtin cd -- "$cwd"
        rm -f -- "$tmp"
      }
    '';
  };

  programs.starship = {
    enable = true;
    enableZshIntegration = true;
    settings = {
      format = "$hostname$directory$git_branch$git_status$direnv$line_break$character";
      right_format = "$time";

      hostname = {
        ssh_only = true;
        format = "[$hostname]($style) ";
        style = "bold green";
      };

      directory = {
        truncation_length = 3;
        truncate_to_repo = false;
        style = "bold cyan";
      };

      git_branch = {
        format = "[$symbol$branch]($style) ";
        style = "bold purple";
      };

      git_status = {
        format = "([\\[$all_status$ahead_behind\\]]($style) )";
        style = "bold red";
        ahead = "⇡$count";
        behind = "⇣$count";
        diverged = "⇕⇡$ahead_count⇣$behind_count";
        modified = "!$count";
        untracked = "?$count";
        staged = "+$count";
        deleted = "✘$count";
      };

      time = {
        disabled = false;
        format = "[$time]($style)";
        style = "dimmed white";
        time_format = "%H:%M:%S";
      };

      direnv = {
        disabled = false;
        format = "[$symbol$loaded/$allowed]($style) ";
        symbol = "direnv ";
        style = "bold yellow";
        allowed_msg = "on";
        not_allowed_msg = "off";
        denied_msg = "denied";
        loaded_msg = "loaded";
        unloaded_msg = "not loaded";
      };

      character = {
        success_symbol = "[❯](bold green)";
        error_symbol = "[❯](bold red)";
      };
    };
  };

  # ── CLI tools ────────────────────────────────────────────────────────────────
  programs.fzf = {
    enable = true;
    enableZshIntegration = true;
  };

  programs.zoxide = {
    enable = true;
    enableZshIntegration = true;
    options = [ "--cmd z" ];
  };

  programs.eza = {
    enable = true;
    enableZshIntegration = false;
    git = true;
    icons = "auto";
  };

  programs.bat = {
    enable = true;
  };

  programs.direnv = {
    enable = true;
    enableZshIntegration = true;
    nix-direnv.enable = true;
  };

  home.sessionVariables = {
    _ZO_FZF_OPTS = "--preview 'eza --tree --level=2 --color=always {2..}' --preview-window=right:40%";
    NIX_BUILD_SHELL = "zsh";
  };

  # ── Git ─────────────────────────────────────────────────────────────────────
  programs.git = {
    enable = true;
    settings = {
      user.name = "ulve";
      user.email = "johansson.olov@gmail.com";
    };
    includes = [
      {
        condition = "gitdir:~/code/";
        path = "~/.config/git/work";
      }
    ];
  };

  home.file.".config/git/work".text = ''
    [user]
      name = olov johansson
      email = olov.johansson@futureordering.com
    [credential "https://dev.azure.com"]
      helper = manager
      useHttpPath = true
    [credential]
      credentialStore = gpg
  '';

  programs.gpg.enable = true;

  services.gpg-agent = {
    enable = true;
    pinentry.package = pkgs.pinentry-curses;
  };

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

  # ── SSH ─────────────────────────────────────────────────────────────────────
  programs.ssh = {
    enable = true;
    enableDefaultConfig = false;
    settings = {
      "Host codeberg.org" = {
        IdentityFile = "~/.ssh/id_ed25519_codeberg";
      };
      "Host macbook" = {
        HostName = "192.168.50.205";
        User = "olovjohansson";
        IdentityFile = "~/.ssh/id_ed25519";
      };
    };
  };

  # ── Config files ─────────────────────────────────────────────────────────────
  xdg.configFile."fuzzel/fuzzel.ini".source = ./config/fuzzel/fuzzel.ini;
  xdg.configFile."nvim" = {
    source = config.lib.file.mkOutOfStoreSymlink "/home/ulve/nixos-dotfiles/config/nvim";
  };
  xdg.configFile."sway".source = ./config/sway;
  xdg.configFile."waybar".source = ./config/waybar;
  xdg.configFile."foot".source = ./config/foot;

  # ── Notifications ────────────────────────────────────────────────────────────
  services.mako = {
    enable = true;
    settings = {
      background-color = "#0a0a0a";
      text-color = "#f3eeea";
      border-color = "#cd0a00";
      border-radius = 4;
      border-size = 2;
      default-timeout = 5000;
      max-icon-size = 48;
      padding = "10,14";
    };
  };

  # ── Packages ─────────────────────────────────────────────────────────────────
  home.packages = with pkgs; [
    # general
    claude-code                  # ai coding assistant
    azure-cli                    # az cli
    git-credential-manager       # git credential helper (azure devops PAT)
    pass                         # password store (used by GCM gpg backend)
    brave                        # browser
    fastfetch                    # vanity
    jq                           # json processor
    powershell                   # yes
    teams-for-linux              # teams

    # desktop / wayland
    libnotify                    # notify-send
    wl-clipboard                 # wayland copy utils
    slurp                        # select region in wayland for copy
    grim                         # grab images from wayland
    satty                        # screenshot annotation
    wlogout                      # logout menu
    fuzzel                        # wayland launcher
    swaylock                     # lock screen
    swayidle                     # idle management (dims/locks/sleeps)
    brightnessctl                # screen brightness control
    waybar                       # status bar with left/center/right sections
    lxqt.lxqt-policykit          # polkit authentication agent

    telegram-desktop             # Messaging
    signal-desktop               # Messaging

    # terminal
    foot                         # terminal
    tmux                         # terminal multiplexer
    btop                         # resource monitor
    htop                         # process viewer
    fd                           # fast find alternative
    ripgrep                      # fast grep alternative

    # file managers
    yazi                         # terminal file manager
    thunar                       # gui file manager

    # editors
    neovim                       # editor

    # compilers / runtimes
    gcc                          # c compiler (needed by treesitter)

    # nvim: lsp servers
    tree-sitter                  # parser generator (nvim)
    nil                          # language server for nix
    lua-language-server          # lsp: lua
    bash-language-server         # lsp: bash
    efm-langserver               # lsp: general purpose (runs linters/formatters)

    # nvim: formatters and linters
    nixpkgs-fmt                  # formatter: nix
    stylua                       # formatter: lua
    shfmt                        # formatter: bash/sh
    lua54Packages.luacheck       # linter: lua
    shellcheck                   # linter: bash/sh
  ];
}
