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

ACTION="${1:-setup}"
LAB_ROOT="${2:-/tmp/soria-git-foundations-${USER:-student}}"
MARKER_NAME=".soria-git-foundations"

fail() {
  printf 'ERROR: %s\n' "$*" >&2
  exit 1
}

resolve_safe_root() {
  case "$LAB_ROOT" in
    /tmp/soria-git-*|"${HOME}"/soria-git-*) ;;
    *) fail "refused lab root: $LAB_ROOT" ;;
  esac

  [ "$LAB_ROOT" != "/tmp" ] || fail "refused root: /tmp"
  [ "$LAB_ROOT" != "$HOME" ] || fail "refused root: $HOME"
}

require_marker() {
  [ -f "$LAB_ROOT/$MARKER_NAME" ] || fail "missing marker: $LAB_ROOT/$MARKER_NAME"
}

configure_repo_identity() {
  local repo="$1"
  git -C "$repo" config user.name "SORIA Student"
  git -C "$repo" config user.email "student@soria.invalid"
  git -C "$repo" config init.defaultBranch main
}

create_starter_repo() {
  local repo="$LAB_ROOT/starter"
  mkdir -p "$repo/docs" "$repo/config"
  git -C "$repo" init -q -b main
  configure_repo_identity "$repo"

  cat > "$repo/README.md" <<'TXT'
# SORIA Git Foundations

Repository used to observe the working tree, index and commit history.
TXT

  cat > "$repo/.gitignore" <<'TXT'
.env
*.log
.DS_Store
TXT

  cat > "$repo/config/app.env.example" <<'TXT'
APP_ENV=development
APP_PORT=8080
TXT

  git -C "$repo" add README.md .gitignore config/app.env.example
  git -C "$repo" commit -q -m "chore: initialize Git foundations lab"

  cat >> "$repo/README.md" <<'TXT'

## Workflow

Inspect changes before staging and commit one coherent intention at a time.
TXT

  cat > "$repo/docs/observations.md" <<'TXT'
# Observations

- Working tree: files currently visible on disk.
- Index: exact snapshot prepared for the next commit.
- Repository: committed history stored in .git.
TXT

  cat > "$repo/.env" <<'TXT'
APP_SECRET=training-only-do-not-commit
TXT
}

create_reference_repo() {
  local repo="$LAB_ROOT/reference"
  rm -rf "$repo"
  mkdir -p "$repo/docs" "$repo/config" "$repo/scripts"
  git -C "$repo" init -q -b main
  configure_repo_identity "$repo"

  cat > "$repo/README.md" <<'TXT'
# SORIA Git Foundations

Repository used to observe the working tree, index and commit history.
TXT

  cat > "$repo/.gitignore" <<'TXT'
.env
*.log
.DS_Store
TXT

  cat > "$repo/config/app.env.example" <<'TXT'
APP_ENV=development
APP_PORT=8080
TXT

  git -C "$repo" add README.md .gitignore config/app.env.example
  git -C "$repo" commit -q -m "chore: initialize Git foundations lab"

  cat >> "$repo/README.md" <<'TXT'

## Workflow

Inspect changes before staging and commit one coherent intention at a time.
TXT
  git -C "$repo" add README.md
  git -C "$repo" commit -q -m "docs: explain the repository workflow"

  cat > "$repo/docs/observations.md" <<'TXT'
# Observations

- Working tree: files currently visible on disk.
- Index: exact snapshot prepared for the next commit.
- Repository: committed history stored in .git.
TXT
  git -C "$repo" add docs/observations.md
  git -C "$repo" commit -q -m "docs: record the three Git areas"

  cat > "$repo/scripts/check-repository.sh" <<'TXT'
#!/usr/bin/env bash
set -Eeuo pipefail
git status --short
git log --oneline --decorate -5
TXT
  chmod +x "$repo/scripts/check-repository.sh"
  git -C "$repo" add scripts/check-repository.sh
  git -C "$repo" commit -q -m "feat: add repository inspection script"
}

show_status() {
  require_marker
  for name in starter reference; do
    local repo="$LAB_ROOT/$name"
    if [ -d "$repo/.git" ]; then
      printf '\n[%s]\n' "$name"
      git -C "$repo" status --short --branch
      git -C "$repo" log --oneline --decorate -5
    else
      printf '\n[%s]\nnot created\n' "$name"
    fi
  done
}

validate_reference() {
  require_marker
  local repo="$LAB_ROOT/reference"
  [ -d "$repo/.git" ] || fail "reference repository missing; run action 'run'"

  [ "$(git -C "$repo" rev-list --count HEAD)" -eq 4 ] || fail "expected four commits"
  [ -z "$(git -C "$repo" status --porcelain)" ] || fail "reference repository is not clean"
  [ "$(git -C "$repo" branch --show-current)" = "main" ] || fail "expected main branch"

  local expected actual
  expected=$'feat: add repository inspection script\ndocs: record the three Git areas\ndocs: explain the repository workflow\nchore: initialize Git foundations lab'
  actual="$(git -C "$repo" log --format='%s' -4)"
  [ "$actual" = "$expected" ] || fail "unexpected commit history"

  git -C "$repo" check-ignore -q .env || fail ".env is not ignored"
  ! git -C "$repo" ls-files --error-unmatch .env >/dev/null 2>&1 || fail ".env is tracked"
  [ -x "$repo/scripts/check-repository.sh" ] || fail "inspection script is not executable"

  printf 'Validation successful: clean repository, four atomic commits, ignored secret file.\n'
}

resolve_safe_root

case "$ACTION" in
  setup)
    if [ -e "$LAB_ROOT" ]; then
      require_marker
      rm -rf "$LAB_ROOT/starter" "$LAB_ROOT/reference"
    else
      mkdir -p "$LAB_ROOT"
      : > "$LAB_ROOT/$MARKER_NAME"
    fi
    create_starter_repo
    cat > "$LAB_ROOT/README.txt" <<'TXT'
Commands:
  setup     create the starter repository
  status    inspect starter and reference repositories
  run       build the complete reference history
  validate  verify the reference history and safety rules
  reset     delete this marked lab directory
TXT
    printf 'Starter laboratory ready: %s\n' "$LAB_ROOT"
    ;;
  status)
    show_status
    ;;
  run)
    require_marker
    create_reference_repo
    printf 'Reference history created: %s/reference\n' "$LAB_ROOT"
    ;;
  validate)
    validate_reference
    ;;
  reset)
    if [ ! -e "$LAB_ROOT" ]; then
      printf 'Nothing to remove: %s\n' "$LAB_ROOT"
      exit 0
    fi
    require_marker
    rm -rf "$LAB_ROOT"
    printf 'Laboratory removed: %s\n' "$LAB_ROOT"
    ;;
  *)
    fail "unknown action '$ACTION' (setup|status|run|validate|reset)"
    ;;
esac
