#!/bin/sh

# Fail before minting a commit if this clone still has a test-fixture Git identity.
# A leftover repo-local user.email (Ratchet Test / *.invalid) overrides the global
# identity, and GitHub then will not attribute the commit to the person who pushed.
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
python3 "$ROOT/.github/scripts/check_git_author_identity.py" --pending || exit 1

# Universal source hygiene: fail fast on unresolved merge conflict markers.
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)

if [ -n "$STAGED_FILES" ]; then
  conflict_found=0
  while IFS= read -r file; do
    [ -n "$file" ] || continue
    if git grep --cached -n -I -E '^(<<<<<<<|>>>>>>>)' -- "$file"; then
      conflict_found=1
    fi
  done <<EOF
$STAGED_FILES
EOF

  if [ "$conflict_found" -eq 1 ]; then
    echo "Unresolved merge conflict markers found in staged files" >&2
    exit 1
  fi
fi

# Dart formatting for app/
STAGED_DART_FILES=$(git diff --cached --name-only --diff-filter=ACM "app/**.dart" | grep -v -e '\.gen\.dart$' -e '\.g\.dart$' -e '^app/lib/l10n/app_localizations.*\.dart$')

if [ -n "$STAGED_DART_FILES" ] && [ "${OMI_SKIP_DART_FORMAT:-}" = "1" ]; then
  echo "OMI_SKIP_DART_FORMAT=1: leaving staged Dart files unformatted."
  STAGED_DART_FILES=""
fi

if [ -n "$STAGED_DART_FILES" ]; then
  ROOT="$(git rev-parse --show-toplevel)"
  PINNED_FLUTTER=$(git show :.github/workflows/repo-checks.yml 2>/dev/null | sed -n 's/^[[:space:]]*flutter-version:[[:space:]]*//p' | head -1 | tr -d "\"' ")
  if [ -z "$PINNED_FLUTTER" ]; then
    PINNED_FLUTTER=$(sed -n 's/^[[:space:]]*flutter-version:[[:space:]]*//p' "$ROOT/.github/workflows/repo-checks.yml" 2>/dev/null | head -1 | tr -d "\"' ")
  fi
  if [ -z "$PINNED_FLUTTER" ]; then
    echo "Could not read the pinned flutter-version from .github/workflows/repo-checks.yml." >&2
    echo "Refusing to run 'dart format' with an unknown toolchain. Set OMI_SKIP_DART_FORMAT=1 to commit unformatted." >&2
    exit 1
  fi
  if command -v flutter >/dev/null 2>&1; then
    # Git exports linked-worktree metadata to hooks. Flutter resolves its own
    # SDK version through Git, so those variables must not leak into the probe.
    LOCAL_FLUTTER=$(
      unset GIT_DIR GIT_WORK_TREE
      flutter --version 2>/dev/null | sed -n 's/^Flutter \([0-9][^ ]*\).*/\1/p' | head -1
    )
  else
    LOCAL_FLUTTER=""
  fi
  if [ "$LOCAL_FLUTTER" != "$PINNED_FLUTTER" ]; then
    echo "Dart formatter toolchain mismatch: repo pins Flutter $PINNED_FLUTTER, found ${LOCAL_FLUTTER:-no flutter on PATH}." >&2
    echo "A different Dart SDK reformats untouched files into a shape CI rejects, so formatting is refused." >&2
    echo "Install Flutter $PINNED_FLUTTER (fvm use $PINNED_FLUTTER), or set OMI_SKIP_DART_FORMAT=1 to commit unformatted." >&2
    exit 1
  fi
  DART_BIN="$(dirname "$(command -v flutter)")/dart"
  if [ ! -x "$DART_BIN" ]; then
    echo "Dart formatter sibling not found: expected $DART_BIN next to the validated flutter." >&2
    echo "Refusing to run an unrelated 'dart' from PATH. Set OMI_SKIP_DART_FORMAT=1 to commit unformatted." >&2
    exit 1
  fi
  echo "Formatting staged Dart files in app/ with Flutter $PINNED_FLUTTER..."
  echo "$STAGED_DART_FILES" | xargs "$DART_BIN" format --line-length 120
  echo "$STAGED_DART_FILES" | xargs git add
fi

# Python formatting for backend/
STAGED_PYTHON_FILES=$(git diff --cached --name-only --diff-filter=ACM "backend/**.py")

if [ -n "$STAGED_PYTHON_FILES" ]; then
  echo "Formatting staged Python files in backend/ with the pinned formatter..."
  echo "$STAGED_PYTHON_FILES" | xargs "$ROOT/scripts/backend-python-format" --write
  echo "$STAGED_PYTHON_FILES" | xargs git add
fi

# ARB (l10n JSON) formatting for app/lib/l10n/
STAGED_ARB_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.arb$')

if [ -n "$STAGED_ARB_FILES" ]; then
  if command -v jq >/dev/null 2>&1; then
    echo "Formatting ARB files to 4-space JSON indent..."
    for f in $STAGED_ARB_FILES; do
      jq --indent 4 '.' "$f" > "$f.tmp" && mv "$f.tmp" "$f"
    done
    echo "$STAGED_ARB_FILES" | xargs git add
  else
    echo "jq is not installed. Please run 'sudo apt install jq' or 'brew install jq'" >&2
    exit 1
  fi
fi

# Web (JS/TS/JSX/TSX) formatting with Prettier
# Auto-generated TypeScript (e.g. the admin OpenAPI client) is excluded: a
# regenerated artifact must not be swept through Prettier's format-and-add.
STAGED_WEB_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx)$' | grep -E '^web/' | grep -v '\.generated\.ts$')

if [ -n "$STAGED_WEB_FILES" ] && [ "${OMI_SKIP_WEB_FORMAT:-}" = "1" ]; then
  echo "OMI_SKIP_WEB_FORMAT=1: leaving staged web files unformatted."
  STAGED_WEB_FILES=""
fi

if [ -n "$STAGED_WEB_FILES" ]; then
  echo "Formatting staged web files with Prettier..."
  for dir in $(echo "$STAGED_WEB_FILES" | cut -d/ -f1-2 | sort -u); do
    DIR_FILES=$(echo "$STAGED_WEB_FILES" | grep "^$dir/")
    if [ -z "$DIR_FILES" ]; then
      continue
    fi
    PINNED=$(git show :"$dir/package.json" 2>/dev/null | sed -n 's/.*"prettier"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
    if [ -z "$PINNED" ]; then
      PINNED=$(sed -n 's/.*"prettier"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$dir/package.json" 2>/dev/null | head -1)
    fi
    if [ -z "$PINNED" ]; then
      echo "$dir/package.json does not pin prettier; refusing to format $dir." >&2
      echo "Pin prettier there, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
      exit 1
    fi
    PRETTIER_BIN="$dir/node_modules/.bin/prettier"
    if [ -x "$PRETTIER_BIN" ]; then
      LOCAL_VERSION=$("$PRETTIER_BIN" --version 2>/dev/null)
    else
      LOCAL_VERSION=""
    fi
    RESOLVED_VERSION=$(git show :"$dir/package-lock.json" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print((d.get('packages',{}).get('node_modules/prettier') or {}).get('version',''))" 2>/dev/null)
    if [ -n "$RESOLVED_VERSION" ]; then
      if [ -z "$LOCAL_VERSION" ] || [ "$LOCAL_VERSION" != "$RESOLVED_VERSION" ]; then
        echo "Prettier toolchain mismatch in $dir: package-lock resolves $RESOLVED_VERSION, found ${LOCAL_VERSION:-no $dir/node_modules/.bin/prettier}." >&2
        echo "A floating prettier reformats files into a shape CI rejects, so formatting is refused." >&2
        echo "Run 'npm ci' in $dir, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
        exit 1
      fi
    else
      echo "Prettier lockfile pin missing or unresolvable in $dir: refusing to format $dir." >&2
      echo "A missing, empty, or unparseable package-lock.json lets a floating prettier reformat files into a shape CI rejects." >&2
      echo "Run 'npm ci' in $dir, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
      exit 1
    fi
    for plugin in prettier-plugin-tailwindcss; do
      PLUGIN_RESOLVED=$(git show :"$dir/package-lock.json" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print((d.get('packages',{}).get('node_modules/' + sys.argv[1]) or {}).get('version',''))" "$plugin" 2>/dev/null)
      PLUGIN_DECLARED=$(git show :"$dir/package.json" 2>/dev/null | sed -n "s/.*\"$plugin\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -1)
      if [ -z "$PLUGIN_DECLARED" ]; then
        PLUGIN_DECLARED=$(sed -n "s/.*\"$plugin\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$dir/package.json" 2>/dev/null | head -1)
      fi
      if [ -z "$PLUGIN_RESOLVED" ]; then
        if [ -n "$PLUGIN_DECLARED" ]; then
          echo "Prettier plugin toolchain unresolved in $dir: package.json declares $plugin $PLUGIN_DECLARED, package-lock.json has no entry for it." >&2
          echo "Prettier auto-loads any installed plugin, so a stale or missing one reformats files into a shape CI rejects; formatting is refused." >&2
          echo "Run 'npm ci' in $dir, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
          exit 1
        fi
        continue
      fi
      PLUGIN_PKG="$dir/node_modules/$plugin/package.json"
      if [ -f "$PLUGIN_PKG" ]; then
        PLUGIN_LOCAL=$(python3 -c "import json,sys; print(json.load(open(sys.argv[1])).get('version',''))" "$PLUGIN_PKG" 2>/dev/null)
      else
        PLUGIN_LOCAL=""
      fi
      if [ -z "$PLUGIN_LOCAL" ] || [ "$PLUGIN_LOCAL" != "$PLUGIN_RESOLVED" ]; then
        echo "Prettier plugin toolchain mismatch in $dir: package-lock resolves $plugin $PLUGIN_RESOLVED, found ${PLUGIN_LOCAL:-no $dir/node_modules/$plugin}." >&2
        echo "A missing or stale plugin reformats files into a shape CI rejects, so formatting is refused." >&2
        echo "Run 'npm ci' in $dir, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
        exit 1
      fi
    done
    for file in $DIR_FILES; do
      if ! git diff --quiet -- "$file"; then
        echo "$file has unstaged edits; refusing to format-and-add because it would sweep them into the commit." >&2
        echo "Stage or commit the remaining edits first, or set OMI_SKIP_WEB_FORMAT=1 to commit unformatted." >&2
        exit 1
      fi
    done
    echo "$DIR_FILES" | xargs "$PRETTIER_BIN" --write
    echo "$DIR_FILES" | xargs git add
  done
fi

# C/C++ formatting for firmware/
STAGED_C_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(c|cpp|cc|cxx|h|hpp)$' | grep -E '^(omi/|omiGlass/)')

if [ -n "$STAGED_C_FILES" ]; then
  echo "Formatting staged C/C++ files in firmware..."
  if ! command -v clang-format >/dev/null 2>&1; then
    echo "clang-format is not installed. Please install it first" >&2
    exit 1
  fi
  echo "$STAGED_C_FILES" | xargs clang-format -i
  echo "$STAGED_C_FILES" | xargs git add
fi

# Swift formatting for desktop/macos/Desktop/
STAGED_SWIFT_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^desktop/macos/Desktop/.*\.swift$' | grep -v '/Generated/' || true)

if [ -n "$STAGED_SWIFT_FILES" ]; then
  echo "Formatting staged Swift files in desktop/macos/Desktop/..."
  if ! command -v xcrun >/dev/null 2>&1; then
    echo "xcrun not found — Swift formatting requires macOS with Xcode" >&2
    echo "Bootstrap: desktop/macos/scripts/swift-format-wrapper.sh bootstrap" >&2
    exit 1
  fi
  ROOT="$(git rev-parse --show-toplevel)"
  WRAPPER="$ROOT/desktop/macos/scripts/swift-format-wrapper.sh"
  echo "$STAGED_SWIFT_FILES" | xargs "$WRAPPER" format -i
  echo "$STAGED_SWIFT_FILES" | xargs git add
fi
exit 0