#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
UNCLUSTERED_DIR="$PKG_DIR/clickhouse/migrations/unclustered"
CLUSTERED_DIR="$PKG_DIR/clickhouse/migrations/clustered"
LOCK_FILE="$PKG_DIR/clickhouse/.migration-lock"

generate_migration_lock() {
  local timestamp
  local hash

  timestamp="$(node -e "console.log(new Date().toISOString())")"
  hash="$(node -e "console.log(require('node:crypto').randomUUID())")"

  cat >"$LOCK_FILE" <<EOF
# Migration Lock File
# This file is auto-generated by the migration script.
# It exists to force git conflicts when multiple developers
# create migrations in parallel, preventing incompatible
# migrations from being merged without conflict resolution.
#
# Generated: $timestamp
# Hash: $hash
# Do not manually edit this file.
EOF

  echo "Migration lock updated: $LOCK_FILE"
}

slugify() {
  printf '%s' "$1" \
    | tr '[:upper:]' '[:lower:]' \
    | sed -E "s/['\"]//g; s/[^a-z0-9]+/_/g; s/^_+//; s/_+$//"
}

max_version_in_dir() {
  local dir="$1"

  find "$dir" -maxdepth 1 -type f -name '[0-9][0-9][0-9][0-9][0-9]_*.sql' -exec basename {} \; \
    | sed -E 's/^([0-9]+)_.*/\1/' \
    | sort -n \
    | tail -n 1
}

fail_if_duplicate_versions() {
  local dir="$1"
  local duplicates

  duplicates="$(find "$dir" -maxdepth 1 -type f -name '[0-9][0-9][0-9][0-9][0-9]_*.sql' -exec basename {} \; \
    | sed -E 's/^([0-9]+)_.*/\1/' \
    | sort \
    | uniq -d)"

  if [ -n "$duplicates" ]; then
    echo "Error: duplicate ClickHouse migration versions in $dir:" >&2
    echo "$duplicates" >&2
    exit 1
  fi
}

if [ "$#" -eq 0 ]; then
  echo "Usage: pnpm ch:create <migration_name>"
  exit 1
fi

MIGRATION_NAME="$(slugify "$*")"
if [ -z "$MIGRATION_NAME" ]; then
  echo "Error: migration name must contain at least one letter or number"
  exit 1
fi

fail_if_duplicate_versions "$UNCLUSTERED_DIR"
fail_if_duplicate_versions "$CLUSTERED_DIR"

UNCLUSTERED_MAX="$(max_version_in_dir "$UNCLUSTERED_DIR")"
CLUSTERED_MAX="$(max_version_in_dir "$CLUSTERED_DIR")"
UNCLUSTERED_MAX="${UNCLUSTERED_MAX:-0}"
CLUSTERED_MAX="${CLUSTERED_MAX:-0}"

if [ "$UNCLUSTERED_MAX" != "$CLUSTERED_MAX" ]; then
  echo "Error: unclustered and clustered migration directories are out of sync:" >&2
  echo "  unclustered max version: $UNCLUSTERED_MAX" >&2
  echo "  clustered max version:   $CLUSTERED_MAX" >&2
  exit 1
fi

NEXT_VERSION="$(printf '%05d' "$((10#$UNCLUSTERED_MAX + 1))")"
CREATED_FILENAME="${NEXT_VERSION}_${MIGRATION_NAME}.sql"
UNCLUSTERED_FILE="$UNCLUSTERED_DIR/$CREATED_FILENAME"
CLUSTERED_FILE="$CLUSTERED_DIR/$CREATED_FILENAME"

if [ -e "$UNCLUSTERED_FILE" ] || [ -e "$CLUSTERED_FILE" ]; then
  echo "Error: migration already exists: $CREATED_FILENAME" >&2
  exit 1
fi

cat >"$UNCLUSTERED_FILE" <<'EOF'
-- +goose NO TRANSACTION
-- +goose Up

-- TODO: add unclustered migration SQL.

-- +goose Down

-- TODO: add unclustered rollback SQL.
EOF

cat >"$CLUSTERED_FILE" <<'EOF'
-- +goose NO TRANSACTION
-- +goose Up

-- TODO: add clustered migration SQL. Use ON CLUSTER default and Replicated* engines where needed.

-- +goose Down

-- TODO: add clustered rollback SQL.
EOF

generate_migration_lock

echo ""
echo "Created migration: $CREATED_FILENAME"
echo "  unclustered: $UNCLUSTERED_FILE"
echo "  clustered:   $CLUSTERED_FILE"
echo ""
echo "Fill in both files:"
echo "  - unclustered: use standard table engines (e.g. ReplacingMergeTree)"
echo "  - clustered:   add ON CLUSTER default and use Replicated* engines"
