#!/usr/bin/env bash

set -e  # Exit on error

# ============================================================================
# UNIVERSAL PUBLISH SCRIPT
# ============================================================================
# Usage:
#   sh publish.sh beta                   # Run all phases for beta
#   sh publish.sh release                # Run all phases for release
#   sh publish.sh beta check             # Phase 1 only: Check version (beta)
#   sh publish.sh beta maven             # Phase 2 only: Publish to Maven (beta)
#   sh publish.sh beta npm               # Phase 3 only: Publish to NPM (beta)
#   sh publish.sh release check          # Phase 1 only: Check version (release)
#   sh publish.sh release maven          # Phase 2 only: Publish to Maven (release)
#   sh publish.sh release npm            # Phase 3 only: Publish to NPM (release)
#
# Release bump (RELEASE mode only):
#   sh publish.sh release           # default: auto-increment PATCH  (0.161.0 -> 0.161.1)
#   sh publish.sh release --bump    # bump MINOR, reset patch to 0   (0.161.0 -> 0.162.0)
#   BUMP=1 sh publish.sh release    # same as --bump, via env var (handy for CI variables)
# ============================================================================

# ----------------------------------------------------------------------------
# Argument parsing
#   Positional: MODE (beta|release), PHASE (check|maven|npm|all, default all)
#   Flag:       --bump   (no value) -> RELEASE bumps the MINOR (reset patch to 0).
#                                       Without --bump, release auto-increments PATCH.
#               Env var BUMP=<non-empty/1/true/yes/minor> works as a fallback for --bump.
# ----------------------------------------------------------------------------
# Minor bump can be pre-enabled via the BUMP env var (e.g. a GitLab CI variable)
BUMP_MINOR=false
case "${BUMP:-}" in
    1|true|yes|minor) BUMP_MINOR=true ;;
esac

_ARGS=""
while [ $# -gt 0 ]; do
    case "$1" in
        --bump)
            BUMP_MINOR=true
            shift
            ;;
        *)
            _ARGS="$_ARGS $1"
            shift
            ;;
    esac
done
# Re-establish positional parameters without the consumed flags
# shellcheck disable=SC2086
set -- $_ARGS

MODE="${1:-}"
PHASE="${2:-all}"

# Validate MODE
if [ -z "$MODE" ]; then
    echo "❌ Error: MODE is required"
    echo ""
    echo "Usage:"
    echo "  sh publish.sh beta [phase]         # Beta publishing"
    echo "  sh publish.sh release [phase]      # Release publishing"
    echo ""
    echo "Phases: check | maven | npm | all (default: all)"
    echo "Bump (release only): --bump  # bump MINOR instead of PATCH (or env BUMP=1)"
    exit 1
fi

if [ "$MODE" != "beta" ] && [ "$MODE" != "release" ]; then
    echo "❌ Error: Invalid MODE '$MODE'. Must be 'beta' or 'release'"
    exit 1
fi

if [ "$MODE" == "beta" ] && [ "$BUMP_MINOR" = true ]; then
    echo "⚠️  Note: --bump is ignored in beta mode (beta version comes from package.json)."
fi

# ============================================================================
# PHASE 1: CHECK AND UPDATE VERSION
# ============================================================================
phase_check_version() {
    echo ""
    echo "==============================================="
    echo "📋 PHASE 1: CHECK AND UPDATE VERSION ($MODE)"
    echo "==============================================="

    PACKAGE_NAME=$(node -p "require('./package.json').name")

    # ==============================================================
    # BETA MODE: Check format for tag, fail if exists
    # ==============================================================
    if [ "$MODE" == "beta" ]; then
        echo "🔍 Reading version from package.json..."
        VERSION=$(node -p "require('./package.json').version")

        if [ -z "$VERSION" ]; then
            echo "❌ Error: Could not read version from package.json"
            exit 1
        fi

        echo "📦 Version from package.json: $VERSION"

        # Detect tag based on version format
        # Has "beta" in version → tag beta
        # No "beta" in version → tag alpha

        if [[ "$VERSION" == *"beta"* ]]; then
            NPM_TAG="beta"
            echo "🏷️  Detected: Version contains 'beta' → tag: beta"
        else
            NPM_TAG="alpha"
            echo "🏷️  Detected: Version does not contain 'beta' → tag: alpha"
        fi

        # Check if version exists on npm
        echo "🔎 Checking if version $VERSION exists on npm..."
        NPM_VERSION_INFO=$(npm view "$PACKAGE_NAME@$VERSION" version 2>/dev/null || echo "")

        if [ -n "$NPM_VERSION_INFO" ]; then
            echo ""
            echo "❌ ERROR: Version $VERSION already exists on npm!"
            echo ""
            echo "Please update the version in package.json before publishing."
            echo ""
            exit 1
        fi

        echo "✅ Version $VERSION does not exist on npm. Safe to publish."
    fi

    # ==============================================================
    # RELEASE MODE: Read from npm@latest and auto-increment
    # ==============================================================
    if [ "$MODE" == "release" ]; then
        echo "🔍 Reading latest version from npm@latest (NOT from package.json)..."

        # Read version from npm@latest
        LATEST_VERSION=$(npm view "$PACKAGE_NAME@latest" version 2>/dev/null || echo "")

        if [ -z "$LATEST_VERSION" ]; then
            echo "❌ Error: Could not read version from npm@latest"
            echo "Package may not exist on npm yet."
            exit 1
        fi

        echo "📦 Current @latest version on npm: $LATEST_VERSION"

        # Parse major.minor.patch (handle versions like 0.156.2 or 0.156.2-beta.1)
        MAJOR=$(echo "$LATEST_VERSION" | cut -d'.' -f1)
        MINOR=$(echo "$LATEST_VERSION" | cut -d'.' -f2)
        PATCH=$(echo "$LATEST_VERSION" | cut -d'.' -f3 | cut -d'-' -f1)

        # Compute next version:
        #   --bump  -> bump MINOR, reset patch to 0   (0.161.0 -> 0.162.0)
        #   default -> auto-increment PATCH           (0.161.0 -> 0.161.1)
        if [ "$BUMP_MINOR" = true ]; then
            MINOR=$((MINOR + 1))
            NEW_PATCH=0
            echo "🔼 Bump: MINOR (--bump)"
        else
            NEW_PATCH=$((PATCH + 1))
            echo "🔼 Bump: PATCH (default)"
        fi
        VERSION="$MAJOR.$MINOR.$NEW_PATCH"

        echo "🔼 Computed next version: $LATEST_VERSION → $VERSION"

        # Find the next publishable patch within this major.minor line.
        # A version is "taken" if EITHER the normal OR the "-debug" variant
        # already exists on npm (phase 3 publishes both, so both must be free).
        # Keeps incrementing the patch (e.g. 0.161.0 -> 0.161.1 -> 0.161.2 ...)
        # until a fully-free version is found, or until a safety cap is hit.
        echo "🔎 Finding a publishable version starting at $VERSION..."
        MAX_TRIES=100
        TRIES=0
        while true; do
            EXISTING=$(npm view "$PACKAGE_NAME@$VERSION" version 2>/dev/null || echo "")
            EXISTING_DEBUG=$(npm view "$PACKAGE_NAME@$VERSION-debug" version 2>/dev/null || echo "")

            if [ -z "$EXISTING" ] && [ -z "$EXISTING_DEBUG" ]; then
                echo "✅ $VERSION is free (normal + debug). Using this version."
                break
            fi

            echo "⚠️  $VERSION is taken (normal: ${EXISTING:-free}, debug: ${EXISTING_DEBUG:-free}). Incrementing patch..."
            TRIES=$((TRIES + 1))
            if [ "$TRIES" -ge "$MAX_TRIES" ]; then
                echo "❌ Error: Could not find a free version after $MAX_TRIES tries (stuck near $VERSION)."
                exit 1
            fi
            NEW_PATCH=$((NEW_PATCH + 1))
            VERSION="$MAJOR.$MINOR.$NEW_PATCH"
            echo "   → trying $VERSION"
        done

        # Update package.json with new version
        CURRENT_VERSION=$(node -p "require('./package.json').version")
        if [[ "$OSTYPE" == "darwin"* ]]; then
            sed -i '' "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$VERSION\"/" package.json
        else
            sed -i "s/\"version\": \"$CURRENT_VERSION\"/\"version\": \"$VERSION\"/" package.json
        fi
        echo "📝 Updated package.json: $CURRENT_VERSION → $VERSION"

        # Set NPM tag to latest
        NPM_TAG="latest"
    fi

    # Update gradle.properties with the same version
    echo "📝 Updating gradle.properties..."
    CURRENT_GRADLE_VERSION=$(grep "^version=" gradle.properties | cut -d'=' -f2 | tr -d '"')

    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' "s/^version=.*/version=$VERSION/" gradle.properties
    else
        sed -i "s/^version=.*/version=$VERSION/" gradle.properties
    fi

    echo "   Gradle version updated: $CURRENT_GRADLE_VERSION → $VERSION"

    export VERSION="$VERSION"
    export NPM_TAG="$NPM_TAG"

    echo "✅ Using version: $VERSION"
    echo "✅ NPM tag: $NPM_TAG"
    echo "✅ PHASE 1 COMPLETED"
    echo ""
}

# ============================================================================
# PHASE 2: PUBLISH TO MAVEN
# ============================================================================
phase_publish_maven() {
    echo ""
    echo "==============================================="
    echo "🔧 PHASE 2: PUBLISH TO MAVEN ($MODE)"
    echo "==============================================="

    # Get version from package.json
    VERSION=$(node -p "require('./package.json').version")
    export VERSION="$VERSION"

    echo "📦 Publishing KMP artifacts to Maven (version ${VERSION})..."

    ./gradlew :compose:publishAllPublicationsToGitLabPackagesRepository

    echo "✅ compose Maven publishing completed successfully!"

    echo "📦 Publishing sample/shared KMP artifacts to Maven (version ${VERSION})..."

    # Temporarily remove composeResources and compose { resources { ... } } block
    echo "📦 Backing up sample/shared composeResources and build.gradle.kts..."
    if [ -d "sample/shared/src/commonMain/composeResources" ]; then
        mv sample/shared/src/commonMain/composeResources sample/shared/src/commonMain/composeResources.backup
    fi
    cp sample/shared/build.gradle.kts sample/shared/build.gradle.kts.backup
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' '/^compose {$/,/^}$/d' sample/shared/build.gradle.kts
    else
        sed -i '/^compose {$/,/^}$/d' sample/shared/build.gradle.kts
    fi

    ./gradlew :sample:shared:publishAllPublicationsToGitLabPackagesRepository

    # Restore composeResources and build.gradle.kts
    echo "📦 Restoring sample/shared composeResources and build.gradle.kts..."
    mv sample/shared/build.gradle.kts.backup sample/shared/build.gradle.kts
    if [ -d "sample/shared/src/commonMain/composeResources.backup" ]; then
        mv sample/shared/src/commonMain/composeResources.backup sample/shared/src/commonMain/composeResources
    fi

    echo "✅ sample/shared Maven publishing completed successfully!"
    echo "✅ PHASE 2 COMPLETED"
    echo ""
}

# ============================================================================
# PHASE 3: PUBLISH TO NPM
# ============================================================================
phase_publish_npm() {
    echo ""
    echo "==============================================="
    echo "📦 PHASE 3: PUBLISH TO NPM ($MODE)"
    echo "==============================================="

    # Get version from package.json
    VERSION=$(node -p "require('./package.json').version")
    export VERSION="$VERSION"

    echo "📦 Version from package.json: $VERSION"

    # Determine NPM tag (should already be set from phase 1, but fallback just in case)
    if [ -z "$NPM_TAG" ]; then
        echo "⚠️  NPM_TAG not set, re-detecting..."
        if [ "$MODE" == "beta" ]; then
            # Re-detect based on version format
            if [[ "$VERSION" == *"beta"* ]]; then
                NPM_TAG="beta"
                echo "🏷️  Detected: Version contains 'beta' → tag: beta"
            else
                NPM_TAG="alpha"
                echo "🏷️  Detected: Version does not contain 'beta' → tag: alpha"
            fi
        else
            NPM_TAG="latest"
            echo "🏷️  Release mode → tag: latest"
        fi
    else
        echo "✅ NPM_TAG already set: $NPM_TAG"
    fi

    echo "📦 Publishing version: $VERSION"
    echo "🏷️  NPM tag: $NPM_TAG"

    ./gradlew clean

    # ============================================================
    # FIRST PUBLISH: DEBUG VERSION (with compose kits included)
    # ============================================================
    echo ""
    echo "🔧 Preparing debug version with compose kits..."

    # Create debug version
    DEBUG_VERSION="${VERSION}-debug"
    echo "📦 Debug version: $DEBUG_VERSION"

    # Get current version from package.json (in case it's different from $VERSION)
    CURRENT_PKG_VERSION=$(node -p "require('./package.json').version")

    # Update package.json version to debug version
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' "s/\"version\": \"$CURRENT_PKG_VERSION\"/\"version\": \"$DEBUG_VERSION\"/" package.json
    else
        sed -i "s/\"version\": \"$CURRENT_PKG_VERSION\"/\"version\": \"$DEBUG_VERSION\"/" package.json
    fi

    # Backup compose/build.gradle.kts
    echo "📦 Backing up compose/build.gradle.kts..."
    cp compose/build.gradle.kts compose/build.gradle.kts.backup

    # Comment out maven publish in compose/build.gradle.kts
    echo "💬 Commenting out maven publish in compose/build.gradle.kts..."
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' 's/^import com\.vanniktech\.maven\.publish\.JavadocJar$/\/\/ &/' compose/build.gradle.kts
        sed -i '' 's/^import com\.vanniktech\.maven\.publish\.KotlinMultiplatform$/\/\/ &/' compose/build.gradle.kts
        sed -i '' 's/^    alias(libs\.plugins\.vanniktech\.mavenPublish)$/\/\/     &/' compose/build.gradle.kts
        sed -i '' '/^publishing {$/,/^}$/s/^/\/\/ /' compose/build.gradle.kts
        sed -i '' '/^mavenPublishing {$/,/^}$/s/^/\/\/ /' compose/build.gradle.kts
    else
        sed -i 's/^import com\.vanniktech\.maven\.publish\.JavadocJar$/\/\/ &/' compose/build.gradle.kts
        sed -i 's/^import com\.vanniktech\.maven\.publish\.KotlinMultiplatform$/\/\/ &/' compose/build.gradle.kts
        sed -i 's/^    alias(libs\.plugins\.vanniktech\.mavenPublish)$/\/\/     &/' compose/build.gradle.kts
        sed -i '/^publishing {$/,/^}$/s/^/\/\/ /' compose/build.gradle.kts
        sed -i '/^mavenPublishing {$/,/^}$/s/^/\/\/ /' compose/build.gradle.kts
    fi

    # Modify android configuration for debug version
    echo "🔧 Modifying android configuration for debug version..."
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' 's/namespace = "\$gitlabGroup\.\$gitlabArtifactId"/namespace = "vn.momo.kits.kits"/' compose/build.gradle.kts
        sed -i '' 's/compileSdk = libs\.versions\.android\.compileSdk\.get()\.toInt()/compileSdk = 35/' compose/build.gradle.kts
        sed -i '' 's/minSdk = libs\.versions\.android\.minSdk\.get()\.toInt()/minSdk = 24/' compose/build.gradle.kts
        sed -i '' "s/version = gitlabVersion/version = \"$DEBUG_VERSION\"/" compose/build.gradle.kts
    else
        sed -i 's/namespace = "\$gitlabGroup\.\$gitlabArtifactId"/namespace = "vn.momo.kits.kits"/' compose/build.gradle.kts
        sed -i 's/compileSdk = libs\.versions\.android\.compileSdk\.get()\.toInt()/compileSdk = 35/' compose/build.gradle.kts
        sed -i 's/minSdk = libs\.versions\.android\.minSdk\.get()\.toInt()/minSdk = 24/' compose/build.gradle.kts
        sed -i "s/version = gitlabVersion/version = \"$DEBUG_VERSION\"/" compose/build.gradle.kts
    fi

    # Backup .npmignore
    cp .npmignore .npmignore.backup

    # Create minimal .npmignore for debug version
    cat > .npmignore << 'EOF'
sample/
build/

.fleet
.gradle
.idea
.kotlin
.run

.gitattributes
.gitlab-ci.yml
.npmignore.backup
EOF

    echo "📤 Publishing debug version (with compose)..."
    npm publish --tag $NPM_TAG --access=public

    echo "✅ Debug version published successfully!"

    # Restore .npmignore
    mv .npmignore.backup .npmignore
    echo "✅ .npmignore restored"

    # Restore compose/build.gradle.kts
    mv compose/build.gradle.kts.backup compose/build.gradle.kts
    echo "✅ compose/build.gradle.kts restored"

    # Restore package.json version to original
    # Verify current version is debug version before restoring
    CURRENT_VERSION_CHECK=$(node -p "require('./package.json').version")
    if [ "$CURRENT_VERSION_CHECK" == "$DEBUG_VERSION" ]; then
        if [[ "$OSTYPE" == "darwin"* ]]; then
            sed -i '' "s/\"version\": \"$DEBUG_VERSION\"/\"version\": \"$VERSION\"/" package.json
        else
            sed -i "s/\"version\": \"$DEBUG_VERSION\"/\"version\": \"$VERSION\"/" package.json
        fi
        echo "✅ package.json version restored: $DEBUG_VERSION → $VERSION"
    else
        echo "⚠️  Warning: package.json version is $CURRENT_VERSION_CHECK, expected $DEBUG_VERSION"
        echo "   Restoring to $VERSION anyway..."
        if [[ "$OSTYPE" == "darwin"* ]]; then
            sed -i '' "s/\"version\": \"$CURRENT_VERSION_CHECK\"/\"version\": \"$VERSION\"/" package.json
        else
            sed -i "s/\"version\": \"$CURRENT_VERSION_CHECK\"/\"version\": \"$VERSION\"/" package.json
        fi
    fi

    # ============================================================
    # SECOND PUBLISH: NORMAL VERSION (without compose)
    # ============================================================
    echo ""
    echo "📤 Publishing normal version (without compose)..."
    npm publish --tag $NPM_TAG --access=public

    echo "✅ Normal version published successfully!"

    echo ""
    echo "✅ PHASE 3 COMPLETED"
    echo "   🐛 Debug version: $DEBUG_VERSION (with compose) - Published first"
    echo "   📦 Normal version: $VERSION (without compose) - Published second"
    echo "   🏷️  NPM Tag: $NPM_TAG"
    echo ""
}

# ============================================================================
# MAIN EXECUTION
# ============================================================================

echo ""
echo "🚀 PUBLISH SCRIPT - MODE: $(echo $MODE | tr '[:lower:]' '[:upper:]')"
if [ "$MODE" == "release" ]; then
    if [ "$BUMP_MINOR" = true ]; then echo "   Bump: MINOR (--bump)"; else echo "   Bump: PATCH (default)"; fi
fi
echo "================================================="

case "$PHASE" in
    "check")
        echo "Running PHASE 1 only: Check and update version"
        phase_check_version
        ;;
    "maven")
        echo "Running PHASE 2 only: Publish to Maven"
        phase_publish_maven
        ;;
    "npm")
        echo "Running PHASE 3 only: Publish to NPM"
        phase_publish_npm
        ;;
    "all")
        echo "Running ALL PHASES"
        phase_check_version
        phase_publish_maven
        phase_publish_npm
        echo ""
        echo "🎉 ALL PHASES COMPLETED SUCCESSFULLY!"
        echo "================================================="
        ;;
    *)
        echo "❌ Error: Invalid phase '$PHASE'"
        echo ""
        echo "Usage:"
        echo "  sh publish.sh $MODE              # Run all phases"
        echo "  sh publish.sh $MODE check        # Phase 1: Check and update version"
        echo "  sh publish.sh $MODE maven        # Phase 2: Publish to Maven"
        echo "  sh publish.sh $MODE npm          # Phase 3: Publish to NPM"
        exit 1
        ;;
esac
