#!/usr/bin/env bash
# Deterministic synthetic repo for token benchmarking.
set -euo pipefail
export LC_ALL=C
export TZ=UTC
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
BASE="$(cd "$(dirname "$0")" && pwd)"
REPO="$BASE/repo"
ORIGIN="$BASE/origin.git"
rm -rf "$REPO" "$ORIGIN"
mkdir -p "$REPO"
cd "$REPO"
git init -q -b main
git config user.name "Benchmark Author"
git config user.email "bench@example.com"
git config commit.gpgsign false
git config tag.gpgSign false
git config core.autocrlf false
git config core.fileMode false
git config core.safecrlf false
git config advice.detachedHead false
export GIT_AUTHOR_DATE="2026-06-01T09:00:00Z"
export GIT_COMMITTER_DATE="2026-06-01T09:00:00Z"

tick() {
  # advance the clock 1h per commit, deterministically
  N=$1
  H=$(( 9 + N ))
  D=$(( 1 + H / 24 ))
  HH=$(( H % 24 ))
  export GIT_AUTHOR_DATE=$(printf "2026-06-%02dT%02d:00:00Z" "$D" "$HH")
  export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
}

mkdir -p src/api src/auth src/billing src/ui/components src/ui/hooks src/utils tests/unit tests/integration docs config scripts

# seed files (~40 files)
i=0
for f in \
  src/api/client.ts src/api/routes.ts src/api/middleware.ts src/api/errors.ts \
  src/auth/session.ts src/auth/oauth.ts src/auth/tokens.ts \
  src/billing/invoice.ts src/billing/subscription.ts src/billing/webhooks.ts \
  src/ui/components/Button.tsx src/ui/components/Modal.tsx src/ui/components/Table.tsx \
  src/ui/components/Form.tsx src/ui/components/Toast.tsx \
  src/ui/hooks/useFetch.ts src/ui/hooks/useAuth.ts src/ui/hooks/useDebounce.ts \
  src/utils/dates.ts src/utils/currency.ts src/utils/validation.ts src/utils/logger.ts \
  tests/unit/auth.test.ts tests/unit/billing.test.ts tests/unit/utils.test.ts \
  tests/integration/api.test.ts tests/integration/checkout.test.ts \
  docs/ARCHITECTURE.md docs/CONTRIBUTING.md docs/API.md \
  config/default.json config/production.json config/staging.json \
  scripts/build.sh scripts/deploy.sh scripts/migrate.sh \
  package.json tsconfig.json README.md .env.example ; do
  mkdir -p "$(dirname "$f")"
  {
    echo "// $f"
    for l in $(seq 1 30); do
      echo "export const line_${l} = 'content of $f line $l with some realistic-length text padding here';"
    done
  } > "$f"
done

git add -A
tick 0
git commit -qm "chore: initial project scaffold

Set up TypeScript project structure with api, auth, billing and ui modules."

MSGS=(
"feat(auth): add session refresh with sliding expiry"
"fix(api): handle 429 retry-after header in client"
"feat(billing): implement invoice proration for plan changes"
"refactor(ui): extract Modal focus trap into hook"
"fix(auth): clear tokens on logout race condition"
"feat(api): add request-id middleware for tracing"
"docs: document webhook signature verification"
"test(billing): cover subscription downgrade edge cases"
"feat(ui): add Toast queue with auto-dismiss"
"fix(utils): timezone-safe date range comparisons"
"perf(api): memoize route matcher compilation"
"feat(auth): OAuth PKCE flow for native clients"
"fix(billing): round currency at aggregation, not per line"
"refactor(api): split error mapping from transport layer"
"feat(ui): Table column sorting with stable comparator"
"chore: bump dependencies and fix lockfile drift"
"fix(ui): Form validation message i18n keys"
"feat(billing): dunning email schedule after failed charge"
"test(integration): checkout happy path with mocked gateway"
"fix(api): stream large responses instead of buffering"
"feat(utils): structured logger with redaction rules"
"docs: architecture decision record for queue choice"
"fix(auth): rotate refresh tokens on every use"
"feat(api): pagination cursors for list endpoints"
"refactor(billing): isolate tax calculation behind interface"
"fix(ui): debounce search input to 250ms"
"feat(auth): device fingerprint on suspicious login"
"chore(scripts): idempotent migrate script with lock"
"fix(billing): webhook replay protection window"
"feat(ui): skeleton loading states for Table"
"test(unit): property tests for currency utils"
"fix(api): normalize trailing slashes in routes"
"feat(billing): usage-based metering hooks"
"refactor(utils): consolidate validation error shapes"
"fix(auth): session fixation on privilege elevation"
"docs(api): OpenAPI examples for error envelope"
"feat(api): conditional requests with ETag support"
"fix(ui): Modal scroll lock on iOS Safari"
"chore: prettier + eslint config alignment"
"feat(billing): credit notes for refund flows"
"fix(utils): logger drops circular references safely"
"test(integration): api contract tests against fixtures"
)

FILES=(src/api/client.ts src/auth/session.ts src/billing/invoice.ts src/ui/components/Modal.tsx src/utils/dates.ts src/api/routes.ts src/auth/oauth.ts src/billing/webhooks.ts src/ui/hooks/useFetch.ts src/utils/logger.ts)

n=1
for msg in "${MSGS[@]}"; do
  f="${FILES[$(( n % 10 ))]}"
  echo "// change $n: ${msg%%$'\n'*}" >> "$f"
  # touch a second file on every third commit
  if (( n % 3 == 0 )); then
    f2="${FILES[$(( (n+4) % 10 ))]}"
    echo "// companion change $n" >> "$f2"
    git add "$f2"
  fi
  git add "$f"
  tick "$n"
  git commit -qm "$msg"
  n=$((n+1))
done

# tags
git tag -a v0.1.0 -m "First internal milestone" "$(git rev-list --max-count=1 HEAD~30)"
git tag -a v0.2.0 -m "Billing beta" "$(git rev-list --max-count=1 HEAD~10)"

# branches
git branch release/0.2 v0.2.0

git checkout -qb feature/usage-metering
for k in 1 2 3; do
  echo "// metering work $k" >> src/billing/subscription.ts
  git add src/billing/subscription.ts
  tick $(( n + k ))
  git commit -qm "feat(billing): metering aggregation step $k"
done

git checkout -q main
git checkout -qb fix/session-leak
echo "// leak fix wip" >> src/auth/session.ts
git add src/auth/session.ts
tick $(( n + 5 ))
git commit -qm "fix(auth): plug session listener leak on hot reload"
git checkout -q main

# Push the shared base first. The following local-only commit leaves main one
# commit ahead of origin and changes the same end-of-file region as the feature
# branch, producing the benchmark's intentional conflict.
git init -q --bare "$ORIGIN"
git remote add origin "$ORIGIN"
git push -q origin main feature/usage-metering release/0.2 --follow-tags
git branch -q --set-upstream-to=origin/main main

echo "// enforce metering batch size cap at 500" >> src/billing/subscription.ts
git add src/billing/subscription.ts
tick $(( n + 6 ))
git commit -qm "fix(billing): cap metering batch size to 500"

# a stash
echo "// experimental stash content" >> src/utils/currency.ts
git stash push -q -m "wip: currency experiment"

# staged changes
echo "// staged: new validation rule for IBAN" >> src/utils/validation.ts
cat >> src/api/errors.ts <<'EOF'
// staged: add ErrorEnvelope type
export interface ErrorEnvelope { code: string; message: string; requestId: string; }
EOF
git add src/utils/validation.ts src/api/errors.ts

# unstaged changes
for l in 1 2 3 4 5 6 7 8; do
  echo "// unstaged edit line $l refining oauth scopes handling" >> src/auth/oauth.ts
done
echo "// unstaged tweak to Toast timing" >> src/ui/components/Toast.tsx
echo "// untracked scratch file" > scripts/scratch-notes.md

echo "REPO READY: $REPO"
printf 'main commits: '
git rev-list --count main
printf 'branch-reachable commits: '
git rev-list --branches --count
printf 'tracked files: '
git ls-files | wc -l | tr -d ' '
printf 'tracked-file directories: '
git ls-files | awk -F/ 'NF > 1 { NF--; print $0 }' OFS=/ | sort -u | wc -l | tr -d ' '
