name: CI and Release

on:
  push:
    branches: ["**"]
  pull_request:
    branches: ["**"]
  workflow_dispatch:

jobs:
  lint-backend:
    runs-on: self-hosted
    container:
      image: golang:1.24.9
      volumes:
        - /runner-cache/go-pkg:/go/pkg/mod
        - /runner-cache/go-build:/root/.cache/go-build
        - /runner-cache/golangci-lint:/root/.cache/golangci-lint
        - /runner-cache/apt-archives:/var/cache/apt/archives
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Configure Git for container
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"

      - name: Download Go modules
        run: |
          cd backend
          go mod download

      - name: Install golangci-lint
        run: |
          curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.7.2
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH

      - name: Install swag for swagger generation
        run: go install github.com/swaggo/swag/cmd/swag@v1.16.4

      - name: Generate swagger docs
        run: |
          cd backend
          swag init -d . -g cmd/main.go -o swagger

      - name: Run golangci-lint
        run: |
          cd backend
          golangci-lint run

      - name: Verify go mod tidy
        run: |
          cd backend
          go mod tidy
          git diff --exit-code go.mod go.sum || (echo "go mod tidy made changes, please run 'go mod tidy' and commit the changes" && exit 1)

  lint-frontend:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install dependencies
        run: |
          cd frontend
          npm ci

      - name: Check if prettier was run
        run: |
          cd frontend
          npm run format
          git diff --exit-code || (echo "Prettier made changes, please run 'npm run format' and commit the changes" && exit 1)

      - name: Check if linter was run
        run: |
          cd frontend
          npm run lint

      - name: Build frontend
        run: |
          cd frontend
          npm run build

  test-frontend:
    runs-on: ubuntu-latest
    needs: [lint-frontend]
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install dependencies
        run: |
          cd frontend
          npm ci

      - name: Run frontend tests
        run: |
          cd frontend
          npm run test

  test-backend:
    runs-on: self-hosted
    needs: [lint-backend]
    container:
      image: golang:1.24.9
      options: --privileged -v /var/run/docker.sock:/var/run/docker.sock --add-host=host.docker.internal:host-gateway
      volumes:
        - /runner-cache/go-pkg:/go/pkg/mod
        - /runner-cache/go-build:/root/.cache/go-build
        - /runner-cache/apt-archives:/var/cache/apt/archives
    steps:
      - name: Install Docker CLI
        run: |
          apt-get update -qq
          apt-get install -y -qq docker.io docker-compose netcat-openbsd wget

      - name: Check out code
        uses: actions/checkout@v4

      - name: Configure Git for container
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"

      - name: Download Go modules
        run: |
          cd backend
          go mod download

      - name: Create .env file for testing
        run: |
          cd backend
          cat > .env << EOF
          # docker-compose.yml
          DEV_DB_NAME=databasus
          DEV_DB_USERNAME=postgres
          DEV_DB_PASSWORD=Q1234567
          #app
          ENV_MODE=development
          # db - using 172.17.0.1 to access host from container
          DATABASE_DSN=host=172.17.0.1 user=postgres password=Q1234567 dbname=databasus port=5437 sslmode=disable
          DATABASE_URL=postgres://postgres:Q1234567@172.17.0.1:5437/databasus?sslmode=disable
          # migrations
          GOOSE_DRIVER=postgres
          GOOSE_DBSTRING=postgres://postgres:Q1234567@172.17.0.1:5437/databasus?sslmode=disable
          GOOSE_MIGRATION_DIR=./migrations
          # testing 
          TEST_LOCALHOST=172.17.0.1
          IS_SKIP_EXTERNAL_RESOURCES_TESTS=true
          # to get Google Drive env variables: add storage in UI and copy data from added storage here 
          TEST_GOOGLE_DRIVE_CLIENT_ID=${{ secrets.TEST_GOOGLE_DRIVE_CLIENT_ID }}
          TEST_GOOGLE_DRIVE_CLIENT_SECRET=${{ secrets.TEST_GOOGLE_DRIVE_CLIENT_SECRET }}
          TEST_GOOGLE_DRIVE_TOKEN_JSON=${{ secrets.TEST_GOOGLE_DRIVE_TOKEN_JSON }}
          # testing DBs
          TEST_POSTGRES_12_PORT=5000
          TEST_POSTGRES_13_PORT=5001
          TEST_POSTGRES_14_PORT=5002
          TEST_POSTGRES_15_PORT=5003
          TEST_POSTGRES_16_PORT=5004
          TEST_POSTGRES_17_PORT=5005
          TEST_POSTGRES_18_PORT=5006
          # testing S3
          TEST_MINIO_PORT=9000
          TEST_MINIO_CONSOLE_PORT=9001
          # testing Azure Blob
          TEST_AZURITE_BLOB_PORT=10000
          # testing NAS
          TEST_NAS_PORT=7006
          # testing FTP
          TEST_FTP_PORT=7007
          # testing SFTP
          TEST_SFTP_PORT=7008
          # testing MySQL
          TEST_MYSQL_57_PORT=33057
          TEST_MYSQL_80_PORT=33080
          TEST_MYSQL_84_PORT=33084
          TEST_MYSQL_90_PORT=33090
          # testing MariaDB
          TEST_MARIADB_55_PORT=33055
          TEST_MARIADB_101_PORT=33101
          TEST_MARIADB_102_PORT=33102
          TEST_MARIADB_103_PORT=33103
          TEST_MARIADB_104_PORT=33104
          TEST_MARIADB_105_PORT=33105
          TEST_MARIADB_106_PORT=33106
          TEST_MARIADB_1011_PORT=33111
          TEST_MARIADB_114_PORT=33114
          TEST_MARIADB_118_PORT=33118
          TEST_MARIADB_120_PORT=33120
          # testing Telegram
          TEST_TELEGRAM_BOT_TOKEN=${{ secrets.TEST_TELEGRAM_BOT_TOKEN }}
          TEST_TELEGRAM_CHAT_ID=${{ secrets.TEST_TELEGRAM_CHAT_ID }}
          # supabase
          TEST_SUPABASE_HOST=${{ secrets.TEST_SUPABASE_HOST }}
          TEST_SUPABASE_PORT=${{ secrets.TEST_SUPABASE_PORT }}
          TEST_SUPABASE_USERNAME=${{ secrets.TEST_SUPABASE_USERNAME }}
          TEST_SUPABASE_PASSWORD=${{ secrets.TEST_SUPABASE_PASSWORD }}
          TEST_SUPABASE_DATABASE=${{ secrets.TEST_SUPABASE_DATABASE }}
          # testing MongoDB
          TEST_MONGODB_40_PORT=27040
          TEST_MONGODB_42_PORT=27042
          TEST_MONGODB_44_PORT=27044
          TEST_MONGODB_50_PORT=27050
          TEST_MONGODB_60_PORT=27060
          TEST_MONGODB_70_PORT=27070
          TEST_MONGODB_82_PORT=27082
          # Valkey (cache) - using 172.17.0.1
          VALKEY_HOST=172.17.0.1
          VALKEY_PORT=6379
          VALKEY_USERNAME=
          VALKEY_PASSWORD=
          VALKEY_IS_SSL=false
          # Host for test databases (container -> host)
          TEST_DB_HOST=172.17.0.1
          EOF

      - name: Start test containers
        run: |
          cd backend
          docker compose -f docker-compose.yml.example up -d

      - name: Wait for containers to be ready
        run: |
          # Wait for main dev database
          timeout 60 bash -c 'until docker exec dev-db pg_isready -h localhost -p 5437 -U postgres; do sleep 2; done'

          # Wait for Valkey (cache)
          echo "Waiting for Valkey..."
          timeout 60 bash -c 'until docker exec dev-valkey valkey-cli ping 2>/dev/null | grep -q PONG; do sleep 2; done'
          echo "Valkey is ready!"

          # Wait for test databases (using 172.17.0.1 from container)
          timeout 60 bash -c 'until nc -z 172.17.0.1 5000; do sleep 2; done'
          timeout 60 bash -c 'until nc -z 172.17.0.1 5001; do sleep 2; done'
          timeout 60 bash -c 'until nc -z 172.17.0.1 5002; do sleep 2; done'
          timeout 60 bash -c 'until nc -z 172.17.0.1 5003; do sleep 2; done'
          timeout 60 bash -c 'until nc -z 172.17.0.1 5004; do sleep 2; done'
          timeout 60 bash -c 'until nc -z 172.17.0.1 5005; do sleep 2; done'

          # Wait for MinIO
          timeout 60 bash -c 'until nc -z 172.17.0.1 9000; do sleep 2; done'

          # Wait for Azurite
          timeout 60 bash -c 'until nc -z 172.17.0.1 10000; do sleep 2; done'

          # Wait for FTP
          timeout 60 bash -c 'until nc -z 172.17.0.1 7007; do sleep 2; done'

          # Wait for SFTP
          timeout 60 bash -c 'until nc -z 172.17.0.1 7008; do sleep 2; done'

          # Wait for MySQL containers
          echo "Waiting for MySQL 5.7..."
          timeout 120 bash -c 'until docker exec test-mysql-57 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MySQL 8.0..."
          timeout 120 bash -c 'until docker exec test-mysql-80 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MySQL 8.4..."
          timeout 120 bash -c 'until docker exec test-mysql-84 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MySQL 9.0..."
          timeout 120 bash -c 'until docker exec test-mysql-90 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'

          # Wait for MariaDB containers
          echo "Waiting for MariaDB 5.5..."
          timeout 120 bash -c 'until docker exec test-mariadb-55 mysqladmin ping -h localhost -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.1..."
          timeout 120 bash -c 'until docker exec test-mariadb-101 mysqladmin ping -h localhost -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.2..."
          timeout 120 bash -c 'until docker exec test-mariadb-102 mysqladmin ping -h localhost -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.3..."
          timeout 120 bash -c 'until docker exec test-mariadb-103 mysqladmin ping -h localhost -prootpassword --silent 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.4..."
          timeout 120 bash -c 'until docker exec test-mariadb-104 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.5..."
          timeout 120 bash -c 'until docker exec test-mariadb-105 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.6..."
          timeout 120 bash -c 'until docker exec test-mariadb-106 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 10.11..."
          timeout 120 bash -c 'until docker exec test-mariadb-1011 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 11.4..."
          timeout 120 bash -c 'until docker exec test-mariadb-114 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 11.8..."
          timeout 120 bash -c 'until docker exec test-mariadb-118 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'
          echo "Waiting for MariaDB 12.0..."
          timeout 120 bash -c 'until docker exec test-mariadb-120 healthcheck.sh --connect --innodb_initialized 2>/dev/null; do sleep 2; done'

          # Wait for MongoDB containers
          echo "Waiting for MongoDB 4.0..."
          timeout 120 bash -c 'until docker exec test-mongodb-40 mongo --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 4.2..."
          timeout 120 bash -c 'until docker exec test-mongodb-42 mongo --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 4.4..."
          timeout 120 bash -c 'until docker exec test-mongodb-44 mongo --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 5.0..."
          timeout 120 bash -c 'until docker exec test-mongodb-50 mongosh --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 6.0..."
          timeout 120 bash -c 'until docker exec test-mongodb-60 mongosh --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 7.0..."
          timeout 120 bash -c 'until docker exec test-mongodb-70 mongosh --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'
          echo "Waiting for MongoDB 8.2..."
          timeout 120 bash -c 'until docker exec test-mongodb-82 mongosh --eval "db.adminCommand(\"ping\")" -u root -p rootpassword --authenticationDatabase admin 2>/dev/null; do sleep 2; done'

      - name: Create data and temp directories
        run: |
          # Create directories that are used for backups and restore
          # These paths match what's configured in config.go
          mkdir -p databasus-data/backups
          mkdir -p databasus-data/temp

      - name: Install database client dependencies
        run: |
          apt-get update -qq
          apt-get install -y -qq libncurses6 libpq5
          ln -sf /usr/lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5 || true
          ln -sf /usr/lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5 || true

      - name: Setup PostgreSQL, MySQL and MariaDB client tools from pre-built assets
        run: |
          cd backend/tools

          # Create directory structure
          mkdir -p postgresql mysql mariadb mongodb/bin

          # Copy PostgreSQL client tools (12-18) from pre-built assets
          for version in 12 13 14 15 16 17 18; do
            mkdir -p postgresql/postgresql-$version
            cp -r ../../assets/tools/x64/postgresql/postgresql-$version/bin postgresql/postgresql-$version/
          done

          # Copy MySQL client tools (5.7, 8.0, 8.4, 9) from pre-built assets
          for version in 5.7 8.0 8.4 9; do
            mkdir -p mysql/mysql-$version
            cp -r ../../assets/tools/x64/mysql/mysql-$version/bin mysql/mysql-$version/
          done

          # Copy MariaDB client tools (10.6, 12.1) from pre-built assets
          for version in 10.6 12.1; do
            mkdir -p mariadb/mariadb-$version
            cp -r ../../assets/tools/x64/mariadb/mariadb-$version/bin mariadb/mariadb-$version/
          done

          # Make all binaries executable
          chmod +x postgresql/*/bin/*
          chmod +x mysql/*/bin/*
          chmod +x mariadb/*/bin/*

          echo "Pre-built client tools setup complete"

      - name: Install MongoDB Database Tools
        run: |
          cd backend/tools

          # MongoDB Database Tools must be downloaded (not in pre-built assets)
          # They are backward compatible - single version supports all servers (4.0-8.0)
          MONGODB_TOOLS_URL="https://fastdl.mongodb.org/tools/db/mongodb-database-tools-debian12-x86_64-100.10.0.deb"

          echo "Downloading MongoDB Database Tools..."
          wget -q "$MONGODB_TOOLS_URL" -O /tmp/mongodb-database-tools.deb

          echo "Installing MongoDB Database Tools..."
          dpkg -i /tmp/mongodb-database-tools.deb || apt-get install -f -y --no-install-recommends

          # Create symlinks to tools directory
          ln -sf /usr/bin/mongodump mongodb/bin/mongodump
          ln -sf /usr/bin/mongorestore mongodb/bin/mongorestore

          rm -f /tmp/mongodb-database-tools.deb
          echo "MongoDB Database Tools installed successfully"

      - name: Verify MariaDB client tools exist
        run: |
          cd backend/tools
          echo "Checking MariaDB client tools..."
          if [ -f "mariadb/mariadb-10.6/bin/mariadb-dump" ]; then
            echo "MariaDB 10.6 client tools found"
            ls -la mariadb/mariadb-10.6/bin/
          else
            echo "MariaDB 10.6 client tools NOT found"
          fi
          if [ -f "mariadb/mariadb-12.1/bin/mariadb-dump" ]; then
            echo "MariaDB 12.1 client tools found"
            ls -la mariadb/mariadb-12.1/bin/
          else
            echo "MariaDB 12.1 client tools NOT found"
          fi

      - name: Verify MongoDB Database Tools exist
        run: |
          cd backend/tools
          echo "Checking MongoDB Database Tools..."
          if [ -f "mongodb/bin/mongodump" ]; then
            echo "MongoDB Database Tools found"
            ls -la mongodb/bin/
            mongodb/bin/mongodump --version || true
          else
            echo "MongoDB Database Tools NOT found"
          fi

      - name: Run database migrations
        run: |
          cd backend
          go install github.com/pressly/goose/v3/cmd/goose@latest
          goose up

      - name: Run Go tests
        run: |
          cd backend
          go test -p=1 -count=1 -failfast -timeout 10m ./internal/...

      - name: Stop test containers
        if: always()
        run: |
          cd backend
          # Stop and remove containers (keeping images for next run)
          docker compose -f docker-compose.yml.example down -v

          # Clean up all data directories created by docker-compose
          echo "Cleaning up data directories..."
          rm -rf pgdata || true
          rm -rf valkey-data || true
          rm -rf mysqldata || true
          rm -rf mariadbdata || true
          rm -rf temp/nas || true
          rm -rf databasus-data || true

          # Also clean root-level databasus-data if exists
          cd ..
          rm -rf databasus-data || true

          echo "Cleanup complete"

  determine-version:
    runs-on: self-hosted
    container:
      image: node:20
    needs: [test-backend, test-frontend]
    if: ${{ github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip-release]') }}
    outputs:
      should_release: ${{ steps.version_bump.outputs.should_release }}
      new_version: ${{ steps.version_bump.outputs.new_version }}
      bump_type: ${{ steps.version_bump.outputs.bump_type }}
    steps:
      - name: Check out code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Configure Git for container
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"

      - name: Install semver
        run: npm install -g semver

      - name: Get current version
        id: current_version
        run: |
          LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
          echo "current_version=${LATEST_TAG#v}" >> $GITHUB_OUTPUT
          echo "Current version: ${LATEST_TAG#v}"

      - name: Analyze commits and determine version bump
        id: version_bump
        shell: bash
        run: |
          CURRENT_VERSION="${{ steps.current_version.outputs.current_version }}"
          LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")

          # Get commits since last tag
          if [ "$LATEST_TAG" = "v0.0.0" ]; then
            COMMITS=$(git log --pretty=format:"%s" --no-merges)
          else
            COMMITS=$(git log ${LATEST_TAG}..HEAD --pretty=format:"%s" --no-merges)
          fi

          echo "Analyzing commits:"
          echo "$COMMITS"

          # Initialize flags
          HAS_FEATURE=false
          HAS_FIX=false
          HAS_BREAKING=false

          # Analyze each commit - USE PROCESS SUBSTITUTION to avoid subshell variable scope issues
          while IFS= read -r commit; do
            if [[ "$commit" =~ ^FEATURE ]]; then
              HAS_FEATURE=true
              echo "Found FEATURE commit: $commit"
            elif [[ "$commit" =~ ^FIX ]]; then
              HAS_FIX=true
              echo "Found FIX commit: $commit"
            elif [[ "$commit" =~ ^REFACTOR ]]; then
              HAS_FIX=true  # Treat refactor as patch
              echo "Found REFACTOR commit: $commit"
            fi
            
            # Check for breaking changes
            if [[ "$commit" =~ BREAKING[[:space:]]CHANGE ]] || [[ "$commit" =~ "!" ]]; then
              HAS_BREAKING=true
              echo "Found BREAKING CHANGE: $commit"
            fi
          done < <(printf '%s\n' "$COMMITS")

          # Determine version bump
          if [ "$HAS_BREAKING" = true ]; then
            BUMP_TYPE="major"
          elif [ "$HAS_FEATURE" = true ]; then
            BUMP_TYPE="minor"
          elif [ "$HAS_FIX" = true ]; then
            BUMP_TYPE="patch"
          else
            BUMP_TYPE="none"
          fi

          echo "bump_type=$BUMP_TYPE" >> $GITHUB_OUTPUT

          if [ "$BUMP_TYPE" != "none" ]; then
            NEW_VERSION=$(npx semver -i $BUMP_TYPE $CURRENT_VERSION)
            echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
            echo "should_release=true" >> $GITHUB_OUTPUT
            echo "New version will be: $NEW_VERSION"
          else
            echo "should_release=false" >> $GITHUB_OUTPUT
            echo "No version bump needed"
          fi

  build-only:
    runs-on: self-hosted
    needs: [test-backend, test-frontend]
    if: ${{ github.ref == 'refs/heads/main' && contains(github.event.head_commit.message, '[skip-release]') }}
    steps:
      - name: Clean workspace
        run: |
          sudo rm -rf "$GITHUB_WORKSPACE"/* || true
          sudo rm -rf "$GITHUB_WORKSPACE"/.* || true

      - name: Check out code
        uses: actions/checkout@v4

      - name: Set up QEMU (enables multi-arch emulation)
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push SHA-only tags
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          build-args: |
            APP_VERSION=dev-${{ github.sha }}
          tags: |
            databasus/databasus:latest
            databasus/databasus:${{ github.sha }}

  build-and-push:
    runs-on: self-hosted
    needs: [determine-version]
    if: ${{ needs.determine-version.outputs.should_release == 'true' }}
    permissions:
      contents: write
    steps:
      - name: Clean workspace
        run: |
          sudo rm -rf "$GITHUB_WORKSPACE"/* || true
          sudo rm -rf "$GITHUB_WORKSPACE"/.* || true

      - name: Check out code
        uses: actions/checkout@v4

      - name: Set up QEMU (enables multi-arch emulation)
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push with version tags
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          build-args: |
            APP_VERSION=${{ needs.determine-version.outputs.new_version }}
          tags: |
            databasus/databasus:latest
            databasus/databasus:v${{ needs.determine-version.outputs.new_version }}
            databasus/databasus:${{ github.sha }}

  release:
    runs-on: self-hosted
    container:
      image: node:20
    needs: [determine-version, build-and-push]
    if: ${{ needs.determine-version.outputs.should_release == 'true' }}
    permissions:
      contents: write
      pull-requests: write
    steps:
      - name: Clean workspace
        run: |
          rm -rf "$GITHUB_WORKSPACE"/* || true
          rm -rf "$GITHUB_WORKSPACE"/.* || true

      - name: Check out code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Configure Git for container
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"

      - name: Generate changelog
        id: changelog
        shell: bash
        run: |
          NEW_VERSION="${{ needs.determine-version.outputs.new_version }}"
          LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")

          # Get commits since last tag
          if [ "$LATEST_TAG" = "v0.0.0" ]; then
            COMMITS=$(git log --pretty=format:"%s|%H|%an|%ad" --date=short --no-merges)
          else
            COMMITS=$(git log ${LATEST_TAG}..HEAD --pretty=format:"%s|%H|%an|%ad" --date=short --no-merges)
          fi

          # Create changelog
          CHANGELOG="# Changelog\n\n## [${NEW_VERSION}] - $(date +%Y-%m-%d)\n\n"

          # Group commits by type and area
          FEATURES=""
          FIXES=""
          REFACTORS=""

          # USE PROCESS SUBSTITUTION to avoid subshell variable scope issues
          while IFS= read -r line; do
            if [ -n "$line" ]; then
              COMMIT_MSG=$(echo "$line" | cut -d'|' -f1)
              COMMIT_HASH=$(echo "$line" | cut -d'|' -f2)
              SHORT_HASH=${COMMIT_HASH:0:7}
              
              # Parse commit message format: TYPE (area): description
              if [[ "$COMMIT_MSG" == FEATURE* ]]; then
                TEMP="${COMMIT_MSG#FEATURE}"
                TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
                if [[ "$TEMP" == \(* ]]; then
                  AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
                  DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
                  FEATURES="${FEATURES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
                fi
              elif [[ "$COMMIT_MSG" == FIX* ]]; then
                TEMP="${COMMIT_MSG#FIX}"
                TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
                if [[ "$TEMP" == \(* ]]; then
                  AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
                  DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
                  FIXES="${FIXES}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
                fi
              elif [[ "$COMMIT_MSG" == REFACTOR* ]]; then
                TEMP="${COMMIT_MSG#REFACTOR}"
                TEMP="${TEMP#"${TEMP%%[![:space:]]*}"}"
                if [[ "$TEMP" == \(* ]]; then
                  AREA=$(echo "$TEMP" | sed 's/^(\([^)]*\)).*/\1/')
                  DESC=$(echo "$TEMP" | sed 's/^([^)]*):[[:space:]]*//')
                  REFACTORS="${REFACTORS}- **${AREA}**: ${DESC} ([${SHORT_HASH}](https://github.com/${{ github.repository }}/commit/${COMMIT_HASH}))\n"
                fi
              fi
            fi
          done < <(printf '%s\n' "$COMMITS")

          # Build changelog sections
          if [ -n "$FEATURES" ]; then
            CHANGELOG="${CHANGELOG}### ✨ Features\n${FEATURES}\n"
          fi

          if [ -n "$FIXES" ]; then
            CHANGELOG="${CHANGELOG}### 🐛 Bug Fixes\n${FIXES}\n"
          fi

          if [ -n "$REFACTORS" ]; then
            CHANGELOG="${CHANGELOG}### 🔨 Refactoring\n${REFACTORS}\n"
          fi

          # Add Docker image info
          CHANGELOG="${CHANGELOG}### 🐳 Docker\n"
          CHANGELOG="${CHANGELOG}- **Image**: \`databasus/databasus:v${NEW_VERSION}\`\n"
          CHANGELOG="${CHANGELOG}- **Platforms**: linux/amd64, linux/arm64\n\n"

          # Set output for GitHub release
          {
            echo 'changelog<<EOF'
            echo -e "$CHANGELOG"
            echo EOF
          } >> $GITHUB_OUTPUT

      - name: Create GitHub Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: v${{ needs.determine-version.outputs.new_version }}
          release_name: Release v${{ needs.determine-version.outputs.new_version }}
          body: ${{ steps.changelog.outputs.changelog }}
          draft: false
          prerelease: false

  publish-helm-chart:
    runs-on: self-hosted
    container:
      image: alpine:3.19
      volumes:
        - /runner-cache/apk-cache:/etc/apk/cache
    needs: [determine-version, build-and-push]
    if: ${{ needs.determine-version.outputs.should_release == 'true' }}
    permissions:
      contents: read
      packages: write
    steps:
      - name: Clean workspace
        run: |
          rm -rf "$GITHUB_WORKSPACE"/* || true
          rm -rf "$GITHUB_WORKSPACE"/.* || true

      - name: Install dependencies
        run: |
          apk add --no-cache git bash curl

      - name: Check out code
        uses: actions/checkout@v4

      - name: Configure Git for container
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"

      - name: Set up Helm
        uses: azure/setup-helm@v4
        with:
          version: v3.14.0

      - name: Log in to GHCR
        run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin

      - name: Update Chart.yaml with release version
        run: |
          VERSION="${{ needs.determine-version.outputs.new_version }}"
          sed -i "s/^version: .*/version: ${VERSION}/" deploy/helm/Chart.yaml
          sed -i "s/^appVersion: .*/appVersion: \"v${VERSION}\"/" deploy/helm/Chart.yaml
          cat deploy/helm/Chart.yaml

      - name: Package Helm chart
        run: helm package deploy/helm --destination .

      - name: Push Helm chart to GHCR
        run: |
          VERSION="${{ needs.determine-version.outputs.new_version }}"
          helm push databasus-${VERSION}.tgz oci://ghcr.io/databasus/charts
