#!/bin/bash
# combine-files.sh — Fasst alle Projektdateien in Textdateien zusammen
# für die Zusammenarbeit mit Perplexity.
#
# Aufruf:
#   ./combine-files.sh [projektverzeichnis]
#
# Standard:
#   ./combine-files.sh .
#
# Die Ausgabedateien werden immer im aktuellen Verzeichnis (dort, wo
# das Skript aufgerufen wird) erzeugt – nicht im Projektverzeichnis.
# Die erste Datei heißt combine.txt. Sobald der Inhalt 100 KB
# überschreiten würde, wird eine neue Datei begonnen (combine2.txt,
# combine3.txt, …).

set -euo pipefail

# ── Parameter ────────────────────────────────────────────────────────────
SRC_DIR="${1:-.}"

# Ausgabeverzeichnis = aktuelles Verzeichnis (vor dem cd ins SRC_DIR)
OUTPUT_DIR="$(pwd)"
MAX_SIZE=$((100 * 1024))  # 100 KB

# ── Konfiguration: Welche Dateien sollen erfasst werden? ────────────────
# Dateiendungen, die berücksichtigt werden (case-insensitive)
EXTENSIONS=(
  js html css json mjs
)

# Dateinamen, die immer erfasst werden (auch ohne bekannte Endung)
EXACT_NAMES=(
  manifest.json
)

# Verzeichnisse, die ignoriert werden
IGNORE_DIRS=(
  node_modules dist .git wasm
)

# Dateien, die ignoriert werden
IGNORE_FILES=(
  combine.txt
)

# ── Hilfsfunktionen ──────────────────────────────────────────────────────
should_ignore_dir() {
  local name
  name="$(basename "$1")"
  for d in "${IGNORE_DIRS[@]}"; do
    [[ "$name" == "$d" ]] && return 0
  done
  return 1
}

should_ignore_file() {
  local name
  name="$(basename "$1")"
  for f in "${IGNORE_FILES[@]}"; do
    [[ "$name" == "$f" ]] && return 0
  done
  # Auch combine2.txt, combine3.txt, … ignorieren
  [[ "$name" =~ ^combine[0-9]*\.txt$ ]] && return 0
  return 1
}

has_valid_extension() {
  local name
  name="$(basename "$1")"
  local lower="${name,,}"
  for ext in "${EXTENSIONS[@]}"; do
    [[ "$lower" == *.$ext ]] && return 0
  done
  for exact in "${EXACT_NAMES[@]}"; do
    [[ "$lower" == "$exact" ]] && return 0
  done
  return 1
}

detect_language() {
  local name
  name="$(basename "$1")"
  local lower="${name,,}"
  case "$lower" in
    *.js)  echo "javascript" ;;
    *.mjs) echo "javascript" ;;
    *.html|*.htm) echo "html" ;;
    *.css) echo "css" ;;
    *.json) echo "json" ;;
    *) echo "text" ;;
  esac
}

# ── Split-Logik ──────────────────────────────────────────────────────────
part=1
current_out=""

get_part_path() {
  if [[ $part -eq 1 ]]; then
    echo "$OUTPUT_DIR/combine.txt"
  else
    echo "$OUTPUT_DIR/combine${part}.txt"
  fi
}

# Alte Ausgabedateien entfernen
rm -f "$OUTPUT_DIR"/combine*.txt 2>/dev/null || true

# Erste Ausgabedatei anlegen und Header schreiben
current_out="$(get_part_path)"
{
  echo "# Zusammengefasste Projektdateien"
  echo "# Erstellt am: $(date -Iseconds)"
  echo "# Quellverzeichnis: $(cd "$SRC_DIR" && pwd)"
  echo "#"
  echo "# Diese Datei wurde von combine-files.sh erzeugt."
  echo "# Bei Bedarf automatisch auf mehrere Dateien aufgespalten (max. 100 KB pro Datei)."
  echo "# Jede Quelldatei ist mit einem Trenner markiert:"
  echo "#   ================ FILE: <relativer/pfad> ================"
  echo "#   \`\`\`<sprache>"
  echo "#   <inhalt>"
  echo "#   \`\`\`"
  echo "#"
  echo "# Am Ende der letzten Datei steht eine Zusammenfassung mit Größen."
  echo ""
} > "$current_out"

# Schreibt einen Datei-Block; wechselt bei Bedarf zur nächsten Datei
write_file_block() {
  local file="$1"
  local rel="${file#./}"
  local lang
  lang="$(detect_language "$file")"
  local file_size
  file_size="$(wc -c < "$file" | tr -d ' ')"

  # Block-Größe schätzen (Header ~210 Byte + Inhalt + Fence ~10 Byte)
  local estimated=$((file_size + 220))

  # Aktuelle Dateigröße der Ausgabedatei
  local current_size
  current_size="$(wc -c < "$current_out" | tr -d ' ')"

  # Neue Datei beginnen, wenn das Limit überschritten würde
  # (aber nicht bei leerer aktueller Datei – verhindert Endlosschleife
  #  bei Einzeldateien, die selbst größer als 100 KB sind)
  if [[ "$current_size" -gt 0 ]] && [[ $((current_size + estimated)) -gt $MAX_SIZE ]]; then
    part=$((part + 1))
    current_out="$(get_part_path)"
    : > "$current_out"
  fi

  {
    echo ""
    echo "================================================================"
    echo "FILE: $rel"
    echo "Size: $file_size bytes"
    echo "================================================================"
    echo '```'"$lang"
    cat "$file"
    echo ""
    echo '```'
  } >> "$current_out"
}

# ── Hauptlogik ──────────────────────────────────────────────────────────
cd "$SRC_DIR"

# Dateien sammeln
file_list=()
while IFS= read -r -d '' file; do
  if ! should_ignore_file "$file" && has_valid_extension "$file"; then
    file_list+=("$file")
  fi
done < <(
  find . \
    -type d \( \
      -name node_modules -o \
      -name dist -o \
      -name .git -o \
      -name wasm \
    \) -prune \
    -o -type f -print0
)

# Nach Pfad sortieren
IFS=$'\n' sorted=($(printf '%s\n' "${file_list[@]}" | sort)); unset IFS

# ── Ausgabe ─────────────────────────────────────────────────────────────
for file in "${sorted[@]}"; do
  write_file_block "$file"
done

# ── Zusammenfassung am Ende der letzten Datei ───────────────────────────
{
  echo ""
  echo "================================================================"
  echo "ZUSAMMENFASSUNG"
  echo "================================================================"
  echo ""
  printf '%-50s %10s\n' "Datei" "Größe"
  printf '%-50s %10s\n' "--------------------------------------------------" "----------"
  total=0
  for file in "${sorted[@]}"; do
    rel="${file#./}"
    size="$(wc -c < "$file" | tr -d ' ')"
    printf '%-50s %10s\n' "$rel" "$size B"
    total=$((total + size))
  done
  echo ""
  printf '%-50s %10s\n' "GESAMT" "$(numfmt --to=iec "$total" 2>/dev/null || echo "${total} B")"
  echo ""
  echo "Anzahl Quelldateien: ${#sorted[@]}"
  echo ""
  echo "Aufgeteilt auf $part Datei(en):"
  for ((i = 1; i <= part; i++)); do
    if [[ $i -eq 1 ]]; then
      pname="combine.txt"
    else
      pname="combine${i}.txt"
    fi
    psize="$(wc -c < "$OUTPUT_DIR/$pname" | tr -d ' ')"
    echo "  $pname  ($(numfmt --to=iec "$psize" 2>/dev/null || echo "${psize} B"))"
  done
} >> "$current_out"

# ── Terminal-Ausgabe ────────────────────────────────────────────────────
echo "✓ Fertig"
echo "  ${#sorted[@]} Quelldateien, insgesamt $(numfmt --to=iec "$total" 2>/dev/null || echo "${total} B")"
echo "  Aufgeteilt auf $part Datei(en) in: $OUTPUT_DIR"
for ((i = 1; i <= part; i++)); do
  if [[ $i -eq 1 ]]; then
    pname="combine.txt"
  else
    pname="combine${i}.txt"
  fi
  psize="$(wc -c < "$OUTPUT_DIR/$pname" | tr -d ' ')"
  echo "    $pname  ($(numfmt --to=iec "$psize" 2>/dev/null || echo "${psize} B"))"
done
echo ""
echo "Datei(en) zum Hochladen bereit."
