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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
cd "$PROJECT_DIR"

CARGO_TOML="Cargo.toml"
REMOTE="${REMOTE:-origin}"

err() { echo "$*" >&2; exit 1; }

# -- Check prerequisites --
command -v cargo >/dev/null 2>&1 || err "cargo is not installed"
[ -f "$CARGO_TOML" ] || err "$CARGO_TOML not found"

# -- Read current version and name from Cargo.toml --
CRATE_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' "$CARGO_TOML" | head -1)
CURRENT_VER=$(sed -n 's/^version = "\(.*\)"/\1/p' "$CARGO_TOML" | head -1)
[ -n "$CRATE_NAME" ] || err "Could not extract crate name from $CARGO_TOML"
[ -n "$CURRENT_VER" ] || err "Could not extract current version from $CARGO_TOML"

# -- Determine target version --
if [ $# -ge 1 ]; then
    NEW_VER="$1"
else
    NEW_VER="$CURRENT_VER"
fi

echo "Crate:    $CRATE_NAME"
echo "Current:  $CURRENT_VER"
echo "Target:   $NEW_VER"

# -- Bump version in Cargo.toml if different --
if [ "$NEW_VER" != "$CURRENT_VER" ]; then
    echo "Bumping version in $CARGO_TOML..."
    sed -i "s/^version = \"$CURRENT_VER\"/version = \"$NEW_VER\"/" "$CARGO_TOML"
    trap 'git checkout -- "$CARGO_TOML"' ERR
fi

GIT_TAG="v$NEW_VER"

# -- Resolve allow-dirty --
ALLOW_DIRTY_FLAG=""
if [ "${ALLOW_DIRTY:-}" = "1" ]; then
    ALLOW_DIRTY_FLAG="--allow-dirty"
fi
for arg in "$@"; do
    [ "$arg" = "--allow-dirty" ] && ALLOW_DIRTY_FLAG="--allow-dirty"
done

if ! git diff --quiet HEAD; then
    echo "Warning: working tree has uncommitted changes."
    if [ -n "$ALLOW_DIRTY_FLAG" ]; then
        echo "Proceeding with --allow-dirty"
    else
        git status --short
        echo ""
        echo "To skip this check, re-run with ALLOW_DIRTY=1 or --allow-dirty"
        exit 1
    fi
fi

# -- Check if tag already exists --
if git tag -l "$GIT_TAG" | grep -q .; then
    err "Tag $GIT_TAG already exists. Delete it or bump the version."
fi

# -- Check crates.io credentials --
CRED_FILE="$HOME/.cargo/credentials.toml"
if [ ! -f "$CRED_FILE" ]; then
    err "No crates.io token found at $CRED_FILE. Run 'cargo login' first."
fi

# -- Dry-run / validation --
echo "Running cargo package --list to validate..."
cargo package --list ${ALLOW_DIRTY_FLAG:+"$ALLOW_DIRTY_FLAG"} >/dev/null || err "cargo package failed"

echo "Running cargo publish --dry-run..."
cargo publish --dry-run "${ALLOW_DIRTY_FLAG:-}" 2>&1 || {
    echo ""
    echo "Dry-run failed. Likely causes:"
    echo "  - Version $NEW_VER already exists on crates.io (bump the version)"
    echo "  - Package validation errors (see above)"
    exit 1
}

# -- Publish --
echo ""
echo "Publishing $CRATE_NAME v$NEW_VER to crates.io..."
cargo publish "${ALLOW_DIRTY_FLAG:-}"

# -- Tag and push --
echo "Creating git tag $GIT_TAG..."
git tag -a "$GIT_TAG" -m "Release $CRATE_NAME v$NEW_VER"
git push "$REMOTE" "$GIT_TAG"

echo ""
echo "Successfully published $CRATE_NAME v$NEW_VER"
