name: Tag and Release
on:
  push:
    tags:
      - 'v*.*.*'
# Prevent concurrent builds: only one at a time (main pushes + releases)
concurrency:
  group: main-build
  cancel-in-progress: false
jobs:
  lint:
    name: Lint and test
    uses: ./.github/workflows/lint.yml

  draft-release:
    name: Create draft release
    runs-on: ubuntu-latest
    needs: lint
    permissions:
      contents: write
    outputs:
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Get tag version
        id: version
        run: echo "version=${GITHUB_REF#refs/tags/v}" | tee -a "$GITHUB_OUTPUT"

      - name: Compare tag and Cargo versions
        env:
          TAG_VERSION: ${{ steps.version.outputs.version }}
        run: |
          CARGO_VERSION="$(yq -roy '.package.version' Cargo.toml)"
          if [[ "$TAG_VERSION" != "$CARGO_VERSION" ]]; then
            echo "❌ Error: Tag version ${TAG_VERSION} does not match Cargo.toml version ${CARGO_VERSION}" >&2
            exit 1
          fi

      - name: Check if release already exists
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          if gh release view ${{ github.ref_name }} --repo ${{ github.repository }} >/dev/null 2>&1; then
            echo "❌ Error: Release ${{ github.ref_name }} already exists" >&2
            exit 1
          fi

      - name: Create Draft Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref_name }}
          release_name: Release ${{ github.ref_name }}
          draft: true
          prerelease: false
          body: |
            Release ${{ github.ref_name }}

            ## Installation

            Download the appropriate binary for your platform from the assets below.

            ### From crates.io

            ```bash
            cargo install markdownlint-rs
            ```

            ### Binary Downloads

            See assets below for pre-built binaries for your platform.

            ### Verify checksums

            Each binary includes a `.sha256` file for verification:

            ```bash
            # Linux/macOS
            sha256sum -c mdlint-*.sha256

            # Windows (PowerShell)
            $expected = (Get-Content mdlint-*.sha256).Split()[0]
            $actual = (Get-FileHash mdlint.exe).Hash.ToLower()
            if ($expected -eq $actual) { "OK" } else { "FAILED" }
            ```

            ### Docker

            ```bash
            docker pull ghcr.io/${{ github.repository }}:${{ steps.get_version.outputs.version }}
            ```

  build:
    name: Build
    needs: draft-release
    permissions:
      contents: write
    uses: ./.github/workflows/build.yml
    with:
      release: ${{ github.ref_name }}

  build-docker:
    name: Build Docker Image (${{ matrix.platform }})
    needs: draft-release
    runs-on: ${{ matrix.runs-on }}
    permissions:
      contents: read
      packages: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: linux/amd64
            runs-on: ubuntu-latest
          - platform: linux/arm64
            runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

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

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

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

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ghcr.io/${{ github.repository }}
            docker.io/${{ secrets.DOCKERHUB_USERNAME }}/mdlint
          tags: |
            type=semver,pattern={{version}}-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
            type=raw,value=${{ matrix.platform == 'linux/amd64' && 'latest-amd64' || 'latest-arm64' }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: ${{ matrix.platform }}
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  publish-docker:
    name: Publish Multi-Platform Docker Manifest
    needs: build-docker
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

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

      - name: Extract version
        id: version
        run: echo "version=${GITHUB_REF#refs/tags/v}" | tee -a "$GITHUB_OUTPUT"

      - name: Create and push multi-platform manifest
        env:
          DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
        run: |
          GHCR_REPO="ghcr.io/${{ github.repository }}"
          DH_REPO="docker.io/${DOCKERHUB_USERNAME}/mdlint"
          VERSION="${{ steps.version.outputs.version }}"
          MAJOR_MINOR=$(echo "${VERSION}" | cut -d. -f1-2)
          MAJOR=$(echo "${VERSION}" | cut -d. -f1)

          for REPO in "${GHCR_REPO}" "${DH_REPO}"; do
            docker buildx imagetools create \
              --tag "${REPO}:${VERSION}" \
              --tag "${REPO}:latest" \
              "${GHCR_REPO}:${VERSION}-amd64" \
              "${GHCR_REPO}:${VERSION}-arm64"

            docker buildx imagetools create \
              --tag "${REPO}:${MAJOR_MINOR}" \
              "${GHCR_REPO}:${VERSION}-amd64" \
              "${GHCR_REPO}:${VERSION}-arm64"

            docker buildx imagetools create \
              --tag "${REPO}:${MAJOR}" \
              "${GHCR_REPO}:${VERSION}-amd64" \
              "${GHCR_REPO}:${VERSION}-arm64"
          done

  publish-crates-io:
    name: Publish to crates.io
    needs: draft-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          cache-key: "publish"

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --token ${CARGO_REGISTRY_TOKEN}

  publish-release:
    name: Publish Release
    needs:
      - publish-crates-io
      - publish-docker
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Publish Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: gh release edit '${{ github.ref_name }}' --repo '${{ github.repository }}' --draft=false
