-- Lua snippets
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local f = ls.function_node
local c = ls.choice_node
local d = ls.dynamic_node
local sn = ls.snippet_node
local fmt = require("luasnip.extras.fmt").fmt
local rep = require("luasnip.extras").rep

-- Return a table of snippets for Bash
-- stylua: ignore start
return {
  -- Shebang
  s("shebang", {
    t("#!/usr/bin/env bash"),
  }),

  -- Bash strict mode
  s("strict", fmt([[
  set -euo pipefail
  IFS=$'\n\t'
  ]], {})),

  -- Function definition
  s("func", fmt([[
  {}() {{
      {}
  }}
  ]], {
    i(1, "function_name"),
    i(2, "# function body"),
  })),

  -- If statement
  s("if", fmt([[
  if [ {} ]; then
      {}
  fi
  ]], {
    i(1, "condition"),
    i(2, "# code"),
  })),

  -- If-else statement
  s("ifelse", fmt([[
  if [ {} ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "condition"),
    i(2, "# if code"),
    i(3, "# else code"),
  })),

  -- If-elif-else statement
  s("ifelif", fmt([[
  if [ {} ]; then
      {}
  elif [ {} ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "condition1"),
    i(2, "# if code"),
    i(3, "condition2"),
    i(4, "# elif code"),
    i(5, "# else code"),
  })),

  -- For loop
  s("for", fmt([[
  for {} in {}; do
      {}
  done
  ]], {
    i(1, "item"),
    i(2, "items"),
    i(3, "# loop body"),
  })),

  -- For loop with range
  s("fori", fmt([[
  for ((i={}; i<{}; i++)); do
      {}
  done
  ]], {
    i(1, "0"),
    i(2, "10"),
    i(3, "# loop body"),
  })),

  -- While loop
  s("while", fmt([[
  while [ {} ]; do
      {}
  done
  ]], {
    i(1, "condition"),
    i(2, "# loop body"),
  })),

  -- Until loop
  s("until", fmt([[
  until [ {} ]; do
      {}
  done
  ]], {
    i(1, "condition"),
    i(2, "# loop body"),
  })),

  -- Case statement
  s("case", fmt([[
  case {} in
      {})
          {}
          ;;
      {})
          {}
          ;;
      *)
          {}
          ;;
  esac
  ]], {
    i(1, "variable"),
    i(2, "pattern1"),
    i(3, "# code for pattern1"),
    i(4, "pattern2"),
    i(5, "# code for pattern2"),
    i(6, "# default code"),
  })),

  -- Read input
  s("read", fmt([[
  read -p "{}" {}
  ]], {
    i(1, "Enter value: "),
    i(2, "variable"),
  })),

  -- Command substitution
  s("cmd", fmt([[
  {}=$({}$)
  ]], {
    i(1, "result"),
    i(2, "command"),
  })),

  -- Variable declaration
  s("var", fmt([[
  {}="{}"
  ]], {
    i(1, "variable"),
    i(2, "value"),
  })),

  -- Array declaration
  s("array", fmt([[
  {}=({})
  ]], {
    i(1, "array"),
    i(2, "item1 item2 item3"),
  })),

  -- Check if command exists
  s("cmdexists", fmt([[
  if command -v {} &> /dev/null; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "command"),
    i(2, "# command exists"),
    i(3, "# command does not exist"),
  })),

  -- Check if file exists
  s("fileexists", fmt([[
  if [ -f {} ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "file"),
    i(2, "# file exists"),
    i(3, "# file does not exist"),
  })),

  -- Check if directory exists
  s("direxists", fmt([[
  if [ -d {} ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "directory"),
    i(2, "# directory exists"),
    i(3, "# directory does not exist"),
  })),

  -- Check if variable is empty
  s("isempty", fmt([[
  if [ -z "${{{}}}" ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "variable"),
    i(2, "# variable is empty"),
    i(3, "# variable is not empty"),
  })),

  -- Check if variable is not empty
  s("isnotempty", fmt([[
  if [ -n "${{{}}}" ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "variable"),
    i(2, "# variable is not empty"),
    i(3, "# variable is empty"),
  })),

  -- Error handling
  s("error", fmt([[
  error() {{
      echo "[ERROR] $1" >&2
      exit 1
  }}
  ]], {})),

  -- Parse command line arguments
  s("getopts", fmt([[
  while getopts ":{}:" opt; do
      case $opt in
          {})
              {}
              ;;
          {})
              {}
              ;;
          \?)
              echo "Invalid option: -$OPTARG" >&2
              exit 1
              ;;
          :)
              echo "Option -$OPTARG requires an argument." >&2
              exit 1
              ;;
      esac
  done
  shift $((OPTIND-1))
  ]], {
    i(1, "ab:c:"),
    i(2, "a"),
    i(3, "# handle option a"),
    i(4, "b"),
    i(5, "# handle option b with value in $OPTARG"),
  })),

  -- Trap signals
  s("trap", fmt([[
  trap '{}' {}
  ]], {
    i(1, "echo 'Caught signal, cleaning up...; exit 1'"),
    i(2, "SIGINT SIGTERM"),
  })),

  -- Cleanup function with trap
  s("cleanup", fmt([[
  cleanup() {{
      {}
  }}

  trap cleanup EXIT
  ]], {
    i(1, "# cleanup code here"),
  })),

  -- Redirect stdout and stderr to file
  s("redirect", fmt([[
  {} > {} 2>&1
  ]], {
    i(1, "command"),
    i(2, "logfile.log"),
  })),

  -- Check exit status
  s("checkstatus", fmt([[
  if [ $? -eq 0 ]; then
      {}
  else
      {}
  fi
  ]], {
    i(1, "# success"),
    i(2, "# failure"),
  })),

  -- Here document
  s("heredoc", fmt([[
  cat << EOF > {}
  {}
  EOF
  ]], {
    i(1, "output.txt"),
    i(2, "content goes here"),
  })),

  -- Here string
  s("herestring", fmt([[
  {} <<< "{}"
  ]], {
    i(1, "command"),
    i(2, "string"),
  })),

  -- Script usage/help
  s("usage", fmt([[
  usage() {{
      cat << EOF
  Usage: $(basename $0) [options] <arguments>

  Options:
    -h, --help     Show this help message and exit
    -v, --verbose  Enable verbose output
    {}

  Examples:
    $(basename $0) {}
  EOF
      exit ${1:-0}
  }}
  ]], {
    i(1, "-o, --option    Description of option"),
    i(2, "example_argument"),
  })),
}
-- stylua: ignore end
