#!/usr/bin/env bash

# Sync only public project defaults and the current project skill catalog into a
# timestamped Codex long-term-memory update. Identical bundles are deduplicated.

set -euo pipefail

dry_run=false
case "${1:-}" in
  '') ;;
  --dry-run) dry_run=true ;;
  -h|--help)
    printf 'Usage: %s [--dry-run]\n' "${0##*/}"
    exit 0
    ;;
  *)
    printf 'Usage: %s [--dry-run]\n' "${0##*/}" >&2
    exit 2
    ;;
esac

for required_command in git rg shasum awk find sort date dirname basename mkdir mktemp mv rm wc tr cat; do
  if ! command -v "$required_command" >/dev/null 2>&1; then
    printf 'ERROR: required command not found: %s\n' "$required_command" >&2
    exit 127
  fi
done

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
memory_source="$repo_root/memory/research-institute-pro-defaults.md"
skill_root="$repo_root/skills"
codex_home="${CODEX_HOME:-$HOME/.codex}"
memory_destination="$codex_home/memories/extensions/ad_hoc/notes"

if [[ ! -f "$memory_source" ]]; then
  printf 'ERROR: public project memory source is missing: %s\n' "$memory_source" >&2
  exit 1
fi

manifest="$(mktemp "${TMPDIR:-/tmp}/research-institute-pro-memory-manifest.XXXXXX")"
note_tmp=""
cleanup() {
  rm -f "$manifest"
  [[ -n "$note_tmp" ]] && rm -f "$note_tmp"
  return 0
}
trap cleanup EXIT

while IFS= read -r -d '' skill_file; do
  relative_path="${skill_file#"$repo_root/"}"
  printf '%s  %s\n' "$(shasum -a 256 "$skill_file" | awk '{print $1}')" "$relative_path"
done < <(find "$skill_root" -mindepth 2 -type f ! -name .DS_Store -print0 | sort -z) > "$manifest"
printf '%s  %s\n' "$(shasum -a 256 "$memory_source" | awk '{print $1}')" "${memory_source#"$repo_root/"}" >> "$manifest"

skill_count="$(find "$skill_root" -mindepth 2 -maxdepth 2 -type f -name SKILL.md | wc -l | tr -d ' ')"
if [[ "$skill_count" == "0" ]]; then
  printf 'ERROR: no project skills found under %s\n' "$skill_root" >&2
  exit 1
fi

bundle_hash="$(shasum -a 256 "$manifest" | awk '{print $1}')"
if [[ -d "$memory_destination" ]] && rg -l -F "skill_bundle_sha256: \`$bundle_hash\`" "$memory_destination" >/dev/null 2>&1; then
  printf 'MEMORY_UP_TO_DATE skills=%s hash=%s destination=%s\n' "$skill_count" "$bundle_hash" "$memory_destination"
  exit 0
fi

if [[ "$dry_run" == true ]]; then
  printf 'WOULD_SYNC_MEMORY skills=%s hash=%s destination=%s\n' "$skill_count" "$bundle_hash" "$memory_destination"
  exit 0
fi

mkdir -p "$memory_destination"
timestamp="$(date '+%Y%m%dT%H%M%S')"
target="$memory_destination/${timestamp}-research-institute-pro-defaults.md"
suffix=1
while [[ -e "$target" ]]; do
  target="$memory_destination/${timestamp}-research-institute-pro-defaults-${suffix}.md"
  suffix=$((suffix + 1))
done
note_tmp="$(mktemp "${TMPDIR:-/tmp}/research-institute-pro-memory-note.XXXXXX")"

{
  printf '# Research Institute PRO project defaults\n\n'
  printf -- '- generated_at: `%s`\n' "$(date '+%F %T %Z')"
  printf -- '- source_commit: `%s`\n' "$(git -C "$repo_root" rev-parse HEAD)"
  printf -- '- skill_bundle_sha256: `%s`\n' "$bundle_hash"
  printf -- '- project_skill_count: `%s`\n\n' "$skill_count"
  cat "$memory_source"
  printf '\n## Installed project skill catalog\n\n'
  while IFS= read -r -d '' skill_file; do
    printf -- '- `%s`\n' "$(basename "$(dirname "$skill_file")")"
  done < <(find "$skill_root" -mindepth 2 -maxdepth 2 -type f -name SKILL.md -print0 | sort -z)
} > "$note_tmp"

mv "$note_tmp" "$target"
note_tmp=""
printf 'MEMORY_SYNC_OK skills=%s hash=%s path=%s\n' "$skill_count" "$bundle_hash" "$target"
