name: Homebrew Tap Update

on:
    workflow_dispatch:
        inputs:
            tag:
                description: 'Tag to release'
                required: true
    workflow_run:
        workflows: ['CI and Release']
        types: [completed]

jobs:
    gate:
        if: github.event_name == 'workflow_run'
        runs-on: ubuntu-latest
        outputs:
            tag: ${{ steps.tag.outputs.tag }}
        steps:
            - id: tag
              run: |
                  # Require overall success
                  if [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then
                    echo "No success run; exiting."
                    exit 0
                  fi

                  # Only react to push events with a tag-like head_branch (e.g., v0.1.0)
                  TAG="${{ github.event.workflow_run.head_branch }}"
                  if [ "${{ github.event.workflow_run.event }}" != "push" ] || [ -z "$TAG" ]; then
                    echo "No tag push; exiting."
                    exit 0
                  fi
                  case "$TAG" in
                    v*) echo "tag=$TAG" >> "$GITHUB_OUTPUT";;
                    *) echo "Not a release tag ($TAG); exiting."; exit 0;;
                  esac
                  echo "Will run Homebrew for $TAG"

    update-formula:
        needs: gate
        if: |
            always() && (
                github.event_name == 'release' ||
                github.event_name == 'workflow_dispatch' ||
                (github.event_name == 'workflow_run' && needs.gate.outputs.tag != '')
            )
        env:
            TAP_REPO: edneedham/homebrew-cred
            FORMULA_NAME: cred
            VERSION: ${{ github.event_name == 'workflow_run' && needs.gate.outputs.tag || github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
        runs-on: ubuntu-latest
        outputs:
            version: ${{ steps.version.outputs.version }}
            sha256: ${{ steps.sha.outputs.sha256 }}
        steps:
            - name: Set version
              id: version
              run: |
                  echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

            - name: Compute tarball SHA256
              id: sha
              run: |
                  URL="https://github.com/${{ github.repository }}/archive/refs/tags/${VERSION}.tar.gz"
                  echo "Fetching: ${URL}"
                  SHA=$(curl -sL "${URL}" | shasum -a 256 | cut -d' ' -f1)
                  echo "sha256=${SHA}" >> "$GITHUB_OUTPUT"
                  echo "SHA256: ${SHA}"

            - name: Checkout tap
              uses: actions/checkout@v4
              with:
                  repository: ${{ env.TAP_REPO }}
                  token: ${{ secrets.TAP_PUSH_TOKEN }}
                  path: tap

            - name: Update formula URL and SHA
              run: |
                  VERSION="${VERSION}"
                  SHA="${{ steps.sha.outputs.sha256 }}"
                  FORMULA="tap/Formula/${FORMULA_NAME}.rb"

                  # Update url line
                  sed -i "s|url \"https://github.com/.*/archive/refs/tags/.*\.tar\.gz\"|url \"https://github.com/${{ github.repository }}/archive/refs/tags/${VERSION}.tar.gz\"|" "$FORMULA"

                  # Update sha256 line (the one right after url, not in bottle block)
                  # Match sha256 followed by a 64-char hex string on its own line
                  sed -i "s/^\([[:space:]]*\)sha256 \"[a-f0-9]\{64\}\"/\1sha256 \"${SHA}\"/" "$FORMULA"

                  # Remove existing bottle block (will be re-added after bottles are built)
                  sed -i '/^[[:space:]]*bottle do/,/^[[:space:]]*end/d' "$FORMULA"

                  echo "Updated formula:"
                  cat "$FORMULA"

            - name: Commit formula update
              working-directory: tap
              run: |
                  git config user.name "github-actions[bot]"
                  git config user.email "github-actions[bot]@users.noreply.github.com"
                  git add Formula/${FORMULA_NAME}.rb
                  git commit -m "Update ${FORMULA_NAME} to ${VERSION}" || echo "No changes to commit"
                  git push

    build-bottles:
        needs: update-formula
        if: ${{ always() && needs.update-formula.result == 'success' }}
        env:
            TAP_REPO: edneedham/homebrew-cred
            FORMULA_NAME: cred
        strategy:
            fail-fast: false
            matrix:
                include:
                    - os: macos-14
                      arch: arm64_sonoma
                    - os: macos-15
                      arch: arm64_sequioa
        runs-on: ${{ matrix.os }}
        steps:
            - name: Checkout tap
              uses: actions/checkout@v4
              with:
                  repository: ${{ env.TAP_REPO }}
                  token: ${{ secrets.TAP_PUSH_TOKEN }}
                  path: tap

            - name: Set up Homebrew
              run: brew update

            - name: Install tap locally
              run: |
                  # Link the checked-out tap into Homebrew's tap directory
                  TAP_DIR="$(brew --prefix)/Library/Taps/edneedham"
                  mkdir -p "$TAP_DIR"
                  ln -s "$GITHUB_WORKSPACE/tap" "$TAP_DIR/homebrew-cred"
                  brew tap --force edneedham/cred

            - name: Build bottle
              id: bottle
              run: |
                  VERSION="${{ needs.update-formula.outputs.version }}"
                  ROOT_URL="https://github.com/${TAP_REPO}/releases/download/${VERSION}"

                  brew install --build-bottle edneedham/cred/${FORMULA_NAME}
                  brew bottle --json --root-url="${ROOT_URL}" edneedham/cred/${FORMULA_NAME}

                  # Debug: list created files
                  echo "Created files:"
                  ls -la *.tar.gz *.json 2>/dev/null || echo "No bottle files in current directory"

                  # Find the bottle file
                  BOTTLE_FILE=$(ls ${FORMULA_NAME}--*.bottle*.tar.gz 2>/dev/null | head -1)
                  echo "bottle_file=${BOTTLE_FILE}" >> "$GITHUB_OUTPUT"

                  # Extract SHA from JSON (new Homebrew JSON format)
                  JSON_FILE=$(ls ${FORMULA_NAME}--*.bottle*.json 2>/dev/null | head -1)
                  echo "JSON file: ${JSON_FILE}"
                  echo "JSON contents:"
                  cat "$JSON_FILE"
                  BOTTLE_SHA=$(cat "$JSON_FILE" | ruby -rjson -e '
                    j = JSON.parse(STDIN.read)
                    # New format: {formula_name: {bottle: {tags: {arch: {sha256: ...}}}}}
                    j.each do |name, data|
                      if data["bottle"] && data["bottle"]["tags"]
                        data["bottle"]["tags"].each { |arch, info| puts info["sha256"] }
                      end
                    end
                  ')
                  echo "bottle_sha=${BOTTLE_SHA}" >> "$GITHUB_OUTPUT"
                  echo "Bottle SHA: ${BOTTLE_SHA}"

            - name: Upload bottle artifact
              uses: actions/upload-artifact@v4
              with:
                  name: bottle-${{ matrix.arch }}
                  path: |
                      ${{ env.FORMULA_NAME }}--*.bottle*.tar.gz
                      ${{ env.FORMULA_NAME }}--*.bottle*.json

    publish-bottles:
        needs: [update-formula, build-bottles]
        if: ${{ always() && needs.build-bottles.result == 'success' }}
        env:
            TAP_REPO: edneedham/homebrew-cred
            FORMULA_NAME: cred
        runs-on: ubuntu-latest
        steps:
            - name: Checkout tap
              uses: actions/checkout@v4
              with:
                  repository: ${{ env.TAP_REPO }}
                  token: ${{ secrets.TAP_PUSH_TOKEN }}
                  path: tap

            - name: Download all bottle artifacts
              uses: actions/download-artifact@v4
              with:
                  pattern: bottle-*
                  merge-multiple: true
                  path: tap/bottles

            - name: Rename bottles to expected format
              working-directory: tap/bottles
              run: |
                  # Homebrew expects: cred-0.4.0.arm64_sequoia.bottle.tar.gz
                  # brew bottle creates: cred--0.4.0.arm64_sequoia.bottle.1.tar.gz
                  for f in *.bottle.*.tar.gz; do
                    newname=$(echo "$f" | sed 's/--/-/' | sed 's/\.bottle\.[0-9]*\.tar\.gz/.bottle.tar.gz/')
                    mv "$f" "$newname"
                    echo "Renamed: $f -> $newname"
                  done
                  ls -la

            - name: Create tap release and upload bottles
              env:
                  GH_TOKEN: ${{ secrets.TAP_PUSH_TOKEN }}
              working-directory: tap
              run: |
                  VERSION="${{ needs.update-formula.outputs.version }}"
                  cd bottles

                  # Create release in tap repo (or update if exists)
                  gh release create "${VERSION}" \
                    --repo "${TAP_REPO}" \
                    --title "${FORMULA_NAME} ${VERSION}" \
                    --notes "Bottles for ${FORMULA_NAME} ${VERSION}" \
                    ${FORMULA_NAME}-*.bottle.tar.gz \
                    2>/dev/null || \
                  gh release upload "${VERSION}" \
                    --repo "${TAP_REPO}" \
                    --clobber \
                    ${FORMULA_NAME}-*.bottle.tar.gz

            - name: Generate and insert bottle block
              working-directory: tap
              run: |
                  VERSION="${{ needs.update-formula.outputs.version }}"
                  FORMULA="Formula/${FORMULA_NAME}.rb"
                  ROOT_URL="https://github.com/${TAP_REPO}/releases/download/${VERSION}"

                  # Parse all bottle JSONs and build the bottle block
                  BOTTLE_BLOCK="  bottle do\n    root_url \"${ROOT_URL}\"\n"

                  for json in bottles/${FORMULA_NAME}--*.bottle.json; do
                    if [ -f "$json" ]; then
                      ARCH_BLOCK=$(cat "$json" | ruby -rjson -e '
                        j = JSON.parse(STDIN.read)
                        # New format: {formula_name: {bottle: {tags: {arch: {sha256: ...}}}}}
                        j.each do |name, data|
                          if data["bottle"] && data["bottle"]["tags"]
                            data["bottle"]["tags"].each do |arch, info|
                              puts "    sha256 cellar: :any_skip_relocation, #{arch}: \"#{info["sha256"]}\""
                            end
                          end
                        end
                      ')
                      BOTTLE_BLOCK="${BOTTLE_BLOCK}${ARCH_BLOCK}\n"
                    fi
                  done

                  BOTTLE_BLOCK="${BOTTLE_BLOCK}  end"

                  echo "Generated bottle block:"
                  echo -e "$BOTTLE_BLOCK"

                  # Insert bottle block after the sha256 line (source sha, not in a block)
                  # Find line number of sha256 (not in bottle block)
                  LINE=$(grep -n '^[[:space:]]*sha256 "[a-f0-9]\{64\}"' "$FORMULA" | head -1 | cut -d: -f1)

                  if [ -n "$LINE" ]; then
                    # Insert after that line
                    head -n "$LINE" "$FORMULA" > formula.tmp
                    echo -e "\n$BOTTLE_BLOCK" >> formula.tmp
                    tail -n +$((LINE + 1)) "$FORMULA" >> formula.tmp
                    mv formula.tmp "$FORMULA"
                  fi

                  echo "Updated formula:"
                  cat "$FORMULA"

            - name: Commit bottle block
              working-directory: tap
              run: |
                  VERSION="${{ needs.update-formula.outputs.version }}"
                  git config user.name "github-actions[bot]"
                  git config user.email "github-actions[bot]@users.noreply.github.com"
                  git add Formula/${FORMULA_NAME}.rb
                  git commit -m "Add bottles for ${FORMULA_NAME} ${VERSION}" || echo "No changes to commit"
                  git push
