#!/usr/bin/env bash
set -euo pipefail

if (( $# < 2 )); then
  echo "Usage: $0 <path> <pattern1> [pattern2 ...]" >&2
  echo "Example: $0 . '*.lua' '*.vim' '*.py'" >&2
  exit 1
fi

root=$1
shift

if [[ ! -d "$root" ]]; then
  echo "Error: not a directory: $root" >&2
  exit 1
fi

get_lang() {
  local file=$1
  local base ext

  base=$(basename -- "$file")
  ext=${base##*.}

  # no extension
  if [[ "$base" == "$ext" ]]; then
    printf ''
    return
  fi

  case "${ext,,}" in
    sh|bash) printf 'bash' ;;
    zsh) printf 'zsh' ;;
    fish) printf 'fish' ;;
    ps1) printf 'powershell' ;;
    bat|cmd) printf 'bat' ;;

    js|mjs|cjs) printf 'javascript' ;;
    ts|mts|cts) printf 'typescript' ;;
    jsx) printf 'jsx' ;;
    tsx) printf 'tsx' ;;

    py) printf 'python' ;;
    rb) printf 'ruby' ;;
    php) printf 'php' ;;
    pl) printf 'perl' ;;
    lua) printf 'lua' ;;
    vim) printf 'vim' ;;

    c) printf 'c' ;;
    h) printf 'c' ;;
    cpp|cc|cxx|hpp|hh|hxx) printf 'cpp' ;;
    cs) printf 'csharp' ;;
    java) printf 'java' ;;
    kt|kts) printf 'kotlin' ;;
    go) printf 'go' ;;
    rs) printf 'rust' ;;
    swift) printf 'swift' ;;

    sql) printf 'sql' ;;
    xml) printf 'xml' ;;
    html|htm) printf 'html' ;;
    css) printf 'css' ;;
    scss) printf 'scss' ;;
    json) printf 'json' ;;
    yaml|yml) printf 'yaml' ;;
    toml) printf 'toml' ;;
    ini|cfg) printf 'ini' ;;
    conf) printf 'conf' ;;

    md) printf 'markdown' ;;
    tex) printf 'tex' ;;

    dockerfile) printf 'dockerfile' ;;
    *) printf '%s' "${ext,,}" ;;
  esac
}

find_args=( "$root" -type f '(' )
first=1

for pattern in "$@"; do
  if (( first )); then
    first=0
  else
    find_args+=( -o )
  fi
  find_args+=( -name "$pattern" )
done

find_args+=( ')' -print0 )

find "${find_args[@]}" |
while IFS= read -r -d '' file; do
  lang=$(get_lang "$file")
  printf '### %s\n' "$file"
  printf '```%s\n' "$lang"
  cat -- "$file"
  if [[ -s "$file" && $(tail -c1 -- "$file" | wc -l) -eq 0 ]]; then
    printf '\n'
  fi

  printf '```\n\n'
done
