name: Release

on:
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag to release (e.g., v1.0.0)"
        required: true
        default: "v1.0.0"

permissions:
  contents: write
  actions: read
  packages: write

env:
  GO_VERSION_FILE: "go.mod"

jobs:
  validate:
    name: Validate Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      is_prerelease: ${{ steps.version.outputs.is_prerelease }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Validate tag format
        id: version
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            TAG_NAME="${{ github.event.inputs.tag }}"
          else
            TAG_NAME="${GITHUB_REF#refs/tags/}"
          fi

          echo "Tag name: $TAG_NAME"

          # Validate semantic versioning format
          if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
            echo "❌ Invalid tag format: $TAG_NAME"
            echo "Expected format: v1.2.3 or v1.2.3-beta.1"
            exit 1
          fi

          # Extract version without 'v' prefix
          VERSION=${TAG_NAME#v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT

          # Check if prerelease (contains hyphen)
          if [[ "$TAG_NAME" =~ - ]]; then
            echo "is_prerelease=true" >> $GITHUB_OUTPUT
            echo "📦 Prerelease detected: $TAG_NAME"
          else
            echo "is_prerelease=false" >> $GITHUB_OUTPUT
            echo "🚀 Stable release detected: $TAG_NAME"
          fi

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: ${{ env.GO_VERSION_FILE }}

      - name: Install libpcap
        run: sudo apt-get install -y libpcap-dev

      - name: Run tests before release
        run: |
          echo "Running final tests before release..."
          go test -v ./...
          echo "✅ All tests passed"

  build:
    name: Build Release Binaries
    runs-on: ubuntu-latest
    needs: validate
    strategy:
      matrix:
        include:
          - goos: linux
            goarch: amd64
          - goos: linux
            goarch: arm64
          - goos: linux
            goarch: arm
            goarm: 7
          - goos: darwin
            goarch: amd64
          - goos: darwin
            goarch: arm64
          - goos: windows
            goarch: amd64
          - goos: freebsd
            goarch: amd64

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: ${{ env.GO_VERSION_FILE }}

      - name: Cache Go modules
        uses: actions/cache@v5
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }}

      - name: Build binaries
        env:
          GOOS: ${{ matrix.goos }}
          GOARCH: ${{ matrix.goarch }}
          GOARM: ${{ matrix.goarm }}
          CGO_ENABLED: 0
        run: |
          # Common variables
          ARCH_SUFFIX="${{ matrix.goos }}-${{ matrix.goarch }}"
          if [[ "${{ matrix.goarm }}" != "" ]]; then
            ARCH_SUFFIX="${ARCH_SUFFIX}v${{ matrix.goarm }}"
          fi

          # Function to build a binary
          build_binary() {
            local BINARY_NAME=$1
            local CMD_PATH=$2
            local OUTPUT_NAME

            # Ensure build directory exists
            mkdir -p build

            if [[ "${{ matrix.goos }}" == "windows" ]]; then
              OUTPUT_NAME="build/${BINARY_NAME}-v${{ needs.validate.outputs.version }}-${ARCH_SUFFIX}.exe"
            else
              OUTPUT_NAME="build/${BINARY_NAME}-v${{ needs.validate.outputs.version }}-${ARCH_SUFFIX}"
            fi

            echo "Building $BINARY_NAME: $OUTPUT_NAME"

            # Ensure clean build environment for this binary
            rm -f "$OUTPUT_NAME" "$OUTPUT_NAME.sha256" "$OUTPUT_NAME.sha512"

            if ! go build \
              -ldflags="-s -w" \
              -o "$OUTPUT_NAME" \
              "$CMD_PATH"; then
              echo "❌ Build failed for $BINARY_NAME"
              exit 1
            fi

            # Verify binary was created
            ls -la "$OUTPUT_NAME"
            echo "$BINARY_NAME=$OUTPUT_NAME" >> $GITHUB_OUTPUT
          }

          # Build CLI
          build_binary "soundtouch-cli" "./cmd/soundtouch-cli"

          # Build Service
          build_binary "soundtouch-service" "./cmd/soundtouch-service"

          # Build Web
          build_binary "soundtouch-web" "./cmd/soundtouch-web"

          # Build Backup
          build_binary "soundtouch-backup" "./cmd/soundtouch-backup"
        id: build

      - name: Generate individual checksums
        run: |
          CLI_NAME="${{ steps.build.outputs.soundtouch-cli }}"
          SVC_NAME="${{ steps.build.outputs.soundtouch-service }}"
          WEB_NAME="${{ steps.build.outputs.soundtouch-web }}"
          BCK_NAME="${{ steps.build.outputs.soundtouch-backup }}"

          # Use atomic operations to avoid conflicts
          TEMP_DIR=$(mktemp -d)

          generate_checksums() {
            local FILE=$1
            echo "Building checksums for: $FILE"
            sha256sum "$FILE" > "${TEMP_DIR}/$(basename "$FILE").sha256"
            sha512sum "$FILE" > "${TEMP_DIR}/$(basename "$FILE").sha512"
            mv "${TEMP_DIR}/$(basename "$FILE").sha256" "$FILE.sha256"
            mv "${TEMP_DIR}/$(basename "$FILE").sha512" "$FILE.sha512"
          }

          generate_checksums "$CLI_NAME"
          generate_checksums "$SVC_NAME"
          generate_checksums "$WEB_NAME"
          generate_checksums "$BCK_NAME"

          # Cleanup
          rm -rf "$TEMP_DIR"
          echo "✅ Checksums generated successfully"

      - name: Upload build artifact
        uses: actions/upload-artifact@v7
        with:
          name: binaries-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm }}
          path: |
            build/soundtouch-cli-v*
            build/soundtouch-service-v*
            build/soundtouch-web-v*
            build/soundtouch-backup-v*
          retention-days: 1

  checksums:
    name: Generate Checksums
    runs-on: ubuntu-latest
    needs: [validate, build]

    steps:
      - name: Download binary artifacts
        uses: actions/download-artifact@v8
        with:
          pattern: binaries-*
          path: ./binaries

      - name: Generate checksums
        run: |
          cd binaries

          # Debug: Show the downloaded structure
          echo "📁 Downloaded artifact structure:"
          ls -R

          # Create a collection directory to avoid naming conflicts
          mkdir -p release-files

          # Move all files from subdirectories to the collection directory
          find . -mindepth 2 -type f \( -name "soundtouch-cli-*" -o -name "soundtouch-service-*" -o -name "soundtouch-web-*" -o -name "soundtouch-backup-*" \) -exec mv {} release-files/ \;

          # Remove empty directories
          find . -type d -empty -delete

          # Move to the collection directory for the rest of the processing
          cd release-files

          # Debug: Show flattened structure
          echo "📁 Flattened structure:"
          ls -la soundtouch-* || echo "No files found matching pattern"

          # Generate combined checksums (exclude individual .sha256/.sha512 files)
          if ls soundtouch-* 1> /dev/null 2>&1; then
            # Only checksum the actual binaries, not the .sha256/.sha512 files
            ls soundtouch-cli-* soundtouch-service-* soundtouch-web-* soundtouch-backup-* | grep -v '\.sha256$' | grep -v '\.sha512$' | xargs sha256sum > checksums.sha256
            ls soundtouch-cli-* soundtouch-service-* soundtouch-web-* soundtouch-backup-* | grep -v '\.sha256$' | grep -v '\.sha512$' | xargs sha512sum > checksums.sha512

            echo "📋 Generated combined checksums:"
            cat checksums.sha256

            # Verify all expected files are present (binaries only, not checksum files)
            EXPECTED_COUNT=28  # 7 platforms * 4 binaries
            ACTUAL_COUNT=$(ls soundtouch-* | grep -v '\.sha256$' | grep -v '\.sha512$' | wc -l)

            if [[ $ACTUAL_COUNT -ne $EXPECTED_COUNT ]]; then
              echo "❌ Expected $EXPECTED_COUNT binaries, found $ACTUAL_COUNT"
              ls -la
              exit 1
            fi

            echo "✅ All $ACTUAL_COUNT binaries present"
          else
            echo "❌ No binary files found"
            echo "Directory contents:"
            ls -la
            exit 1
          fi

      - name: Upload checksums
        uses: actions/upload-artifact@v7
        with:
          name: checksums
          path: |
            binaries/release-files/checksums.sha256
            binaries/release-files/checksums.sha512
            binaries/release-files/*.sha256
            binaries/release-files/*.sha512
          retention-days: 1

      - name: Upload all release assets
        uses: actions/upload-artifact@v7
        with:
          name: release-assets
          path: binaries/release-files/
          retention-days: 1

  create_release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [validate, checksums]
    if: github.event_name == 'workflow_dispatch'

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Download release assets
        uses: actions/download-artifact@v8
        with:
          name: release-assets
          path: ./release-assets

      - name: Generate release notes
        id: release_notes
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            TAG_NAME="${{ github.event.inputs.tag }}"
          else
            TAG_NAME="${{ github.event.release.tag_name }}"
          fi
          VERSION="${TAG_NAME#v}"

          # Generate comprehensive release notes
          cat > release_notes.md << EOF
          # Bose SoundTouch Go Library $TAG_NAME

          A comprehensive Go library for controlling Bose SoundTouch speakers with 100% API coverage, real-time WebSocket events, and production-ready features.

          ## 🎯 Key Features

          - **100% API Coverage**: All 19 official endpoints + 6 useful extensions (25 total)
          - **Real-time Events**: WebSocket support with auto-reconnect and comprehensive event handling
          - **Multiroom Control**: Complete zone management and coordination
          - **Production Ready**: Connection pooling, error handling, circuit breakers, monitoring
          - **Excellent Documentation**: 4000+ lines including Getting Started, Cookbook, Troubleshooting, and Deployment guides
          - **CLI Tool**: Full-featured command-line interface with all endpoints

          ## 🚀 Quick Start

          \`\`\`bash
          go get github.com/gesellix/bose-soundtouch@$TAG_NAME
          \`\`\`

          \`\`\`go
          package main

          import (
              "fmt"
              "log"

              "github.com/gesellix/bose-soundtouch/pkg/client"
          )

          func main() {
              // Create client
              c := client.New("192.168.1.100", 8090)

              // Get device info
              info, err := c.GetInfo()
              if err != nil {
                  log.Fatal(err)
              }

              fmt.Printf("Device: %s\\n", info.Name)
          }
          \`\`\`

          ## 📚 Documentation

          - [Getting Started Guide](docs/GETTING-STARTED.md) - 10-minute tutorial from discovery to WebSocket monitoring
          - [API Cookbook](docs/API-COOKBOOK.md) - 1000+ lines of real-world patterns and examples
          - [Troubleshooting Guide](docs/TROUBLESHOOTING.md) - Systematic issue resolution
          - [Deployment Guide](docs/DEPLOYMENT.md) - Production deployment examples (Docker, K8s, systemd)

          ## 🔧 CLI & Service Tools

          Download the tools for your platform from the assets below:

          ### CLI Tool
          \`\`\`bash
          # Quick device discovery
          ./soundtouch-cli -discover
          \`\`\`

          ### SoundTouch Service
          \`\`\`bash
          # Start the service
          ./soundtouch-service
          \`\`\`

          ### SoundTouch Web
          \`\`\`bash
          # Start the web app
          ./soundtouch-web
          \`\`\`

          ### SoundTouch Backup
          \`\`\`bash
          # Back up cloud account and all paired speakers in one go
          ./soundtouch-backup all
          \`\`\`

          ## 🧪 Tested Hardware

          - Bose SoundTouch 10
          - Bose SoundTouch 20
          - All core functionality validated on real devices

          ## 📈 What's New in $TAG_NAME

          $(git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 HEAD^)..HEAD 2>/dev/null || echo "- Initial release with complete feature set")

          ## 🏗️ Supported Platforms

          This release includes pre-built binaries for:
          - Linux (amd64, arm64, armv7)
          - macOS (Intel & Apple Silicon)
          - Windows (amd64)
          - FreeBSD (amd64)

          `soundtouch-cli`, `soundtouch-service`, `soundtouch-web`, and `soundtouch-backup` are included.

          ## 🔐 Checksums

          Multiple checksum options are provided for download verification:

          ### Combined Checksums (Recommended)
          - \`checksums.sha256\` - SHA256 checksums for all binaries
          - \`checksums.sha512\` - SHA512 checksums for all binaries

          \`\`\`bash
          # Download any binary + combined checksums
          curl -L -O https://github.com/.../soundtouch-cli-v$TAG_NAME-linux-amd64
          curl -L -O https://github.com/.../checksums.sha256

          # Verify your specific download
          sha256sum -c checksums.sha256 --ignore-missing
          \`\`\`

          ### Individual Checksums (Per Binary)
          Each binary also has its own dedicated checksum files:
          - \`soundtouch-cli-v$TAG_NAME-platform.sha256\`
          - \`soundtouch-cli-v$TAG_NAME-platform.sha512\`

          \`\`\`bash
          # Download binary + its individual checksum
          curl -L -O https://github.com/.../soundtouch-cli-v$TAG_NAME-linux-amd64
          curl -L -O https://github.com/.../soundtouch-cli-v$TAG_NAME-linux-amd64.sha256

          # Verify with individual checksum
          sha256sum -c soundtouch-cli-v$TAG_NAME-linux-amd64.sha256
          \`\`\`

          ## 🤝 Contributing

          Contributions welcome! See our documentation for examples and patterns.

          ## 📄 License

          MIT License - see [LICENSE](LICENSE) file.
          EOF

          echo "release_notes_file=release_notes.md" >> $GITHUB_OUTPUT

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v3
        with:
          tag_name: ${{ github.event.inputs.tag }}
          name: "Bose SoundTouch Go Library ${{ github.event.inputs.tag }}"
          body_path: ${{ steps.release_notes.outputs.release_notes_file }}
          draft: false
          prerelease: ${{ needs.validate.outputs.is_prerelease == 'true' }}
          files: |
            release-assets/soundtouch-cli-v*
            release-assets/soundtouch-service-v*
            release-assets/soundtouch-web-v*
            release-assets/soundtouch-backup-v*
            release-assets/checksums.sha256
            release-assets/checksums.sha512
          fail_on_unmatched_files: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  update_release:
    name: Update Existing Release
    runs-on: ubuntu-latest
    needs: [validate, checksums]
    if: github.event_name == 'release' && github.event.action == 'published'

    steps:
      - name: Download release assets
        uses: actions/download-artifact@v8
        with:
          name: release-assets
          path: ./release-assets

      - name: Upload additional assets to existing release
        uses: softprops/action-gh-release@v3
        with:
          tag_name: ${{ github.event.release.tag_name }}
          files: |
            release-assets/soundtouch-cli-v*
            release-assets/soundtouch-service-v*
            release-assets/soundtouch-web-v*
            release-assets/soundtouch-backup-v*
            release-assets/checksums.sha256
            release-assets/checksums.sha512
          fail_on_unmatched_files: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  docker:
    name: Build and Push Docker Image
    runs-on: ubuntu-latest
    needs: validate

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

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

      - name: Extract metadata (tags, labels) for soundtouch-service
        id: meta-service
        uses: docker/metadata-action@v6
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=semver,pattern={{version}},value=v${{ needs.validate.outputs.version }}
            type=semver,pattern={{major}}.{{minor}},value=v${{ needs.validate.outputs.version }}
            type=raw,value=latest,enable=${{ needs.validate.outputs.is_prerelease == 'false' }}

      - name: Build and push soundtouch-service Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          target: soundtouch-service
          platforms: linux/amd64,linux/arm64,linux/arm64/v8,linux/arm/v7
          push: true
          tags: ${{ steps.meta-service.outputs.tags }}
          labels: ${{ steps.meta-service.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Extract metadata (tags, labels) for soundtouch-web
        id: meta-web
        uses: docker/metadata-action@v6
        with:
          images: ghcr.io/${{ github.repository }}-web
          tags: |
            type=semver,pattern={{version}},value=v${{ needs.validate.outputs.version }}
            type=semver,pattern={{major}}.{{minor}},value=v${{ needs.validate.outputs.version }}
            type=raw,value=latest,enable=${{ needs.validate.outputs.is_prerelease == 'false' }}

      - name: Build and push soundtouch-web Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          target: soundtouch-web
          platforms: linux/amd64,linux/arm64,linux/arm64/v8,linux/arm/v7
          push: true
          tags: ${{ steps.meta-web.outputs.tags }}
          labels: ${{ steps.meta-web.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  notify:
    name: Post-Release Notifications
    runs-on: ubuntu-latest
    needs: [validate, create_release, update_release, docker]
    if: always() && (needs.create_release.result == 'success' || needs.update_release.result == 'success' || needs.docker.result == 'success')

    steps:
      - name: Notify success
        run: |
          echo "🎉 Release ${{ needs.validate.outputs.version }} completed successfully!"
          echo "📦 Binaries built for 7 platforms (CLI, Service, Web, and Backup)"
          echo "🐳 Docker image published to ghcr.io"
          echo "🔐 Checksums generated and verified"
          echo "📋 Release notes automatically generated"
          echo ""
          TAG_NAME="${{ github.event.inputs.tag || github.event.release.tag_name }}"
          echo "🔗 Release URL: https://github.com/${{ github.repository }}/releases/tag/${TAG_NAME}"
          echo ""
          echo "Next steps:"
          echo "- Monitor download metrics"
          echo "- Update documentation if needed"
          echo "- Announce to community (see scripts/post-release.md)"
