name: CI

permissions:
  contents: read

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest

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

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: "go.mod"

      - 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') }}
          restore-keys: |
            ${{ runner.os }}-go-

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

      - name: Download dependencies
        run: go mod download

      - name: Verify dependencies
        run: go mod verify

      - name: Run tests
        run: go test -v -race -coverprofile=coverage.out ./...

      - name: Build service
        run: make build-service

      - name: Run HTTP client integration tests
        run: make test-http-client

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v6
        with:
          file: ./coverage.out
          flags: unittests
          name: codecov-umbrella
          fail_ci_if_error: false

  lint:
    name: Lint
    runs-on: ubuntu-latest

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

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: "go.mod"

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

      - name: Run golangci-lint
        uses: golangci/golangci-lint-action@v9
        with:
          version: latest
          args: --timeout=5m

  build:
    name: Build
    runs-on: ubuntu-latest
    strategy:
      matrix:
        goos: [linux, darwin, windows]
        goarch: [amd64, arm64]
        exclude:
          # Windows ARM64 builds are experimental
          - goos: windows
            goarch: arm64

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

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: "go.mod"

      - name: Build CLI
        env:
          GOOS: ${{ matrix.goos }}
          GOARCH: ${{ matrix.goarch }}
        run: |
          output_name="soundtouch-cli-${{ matrix.goos }}-${{ matrix.goarch }}"
          if [ "${{ matrix.goos }}" = "windows" ]; then
            output_name="${output_name}.exe"
          fi
          go build -o "$output_name" ./cmd/soundtouch-cli

      - name: Upload build artifacts
        uses: actions/upload-artifact@v7
        with:
          name: soundtouch-cli-${{ matrix.goos }}-${{ matrix.goarch }}
          path: soundtouch-cli-*

  security:
    name: Basic Security Check
    runs-on: ubuntu-latest

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

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: "go.mod"

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

      - name: Run basic vulnerability check
        run: |
          go install golang.org/x/vuln/cmd/govulncheck@latest
          govulncheck ./...

      - name: Security scan reminder
        run: |
          echo "ℹ️ This is a basic security check for CI speed."
          echo "For comprehensive security scanning, see the Security workflow:"
          echo "https://github.com/${{ github.repository }}/actions/workflows/security.yml"

  docs:
    name: Documentation Check
    runs-on: ubuntu-latest

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

      - name: Check documentation links
        run: |
          npm install -g markdown-link-check
          find . -name "*.md" -not -path "./tests/*" -not -path "./node_modules/*" -print0 | xargs -0 -n1 markdown-link-check -q -v -c .github/markdown-link-check.json

      - name: Warn on pending images
        run: |
          IMAGES=(
            "dashboard-home.png"
            "account-creation.png"
            "account-dashboard.png"
            "usb-remote-services.png"
            "device-discovery.png"
            "device-registration.png"
            "account-migration.png"
            "migration-setup.png"
            "migration-progress.png"
            "migration-health.png"
            "migration-complete.png"
            "backup-setup.png"
          )

          for img in "${IMAGES[@]}"; do
            if [ ! -f "docs/images/$img" ]; then
              echo "::warning file=docs/guides/MIGRATION-GUIDE.md::Pending image '$img' is missing from docs/images/"
            fi
          done

      - name: Validate API documentation
        run: |
          # Check that all documented endpoints exist in code
          echo "Validating API documentation consistency..."

          # Check API cookbook
          if [ -f "docs/reference/API-COOKBOOK.md" ]; then
            echo "✓ API Cookbook exists"
          else
            echo "✗ API Cookbook missing"
            exit 1
          fi

          # Check getting started guide
          if [ -f "docs/guides/GETTING-STARTED.md" ]; then
            echo "✓ Getting Started guide exists"
          else
            echo "✗ Getting Started guide missing"
            exit 1
          fi

  integration:
    name: Integration Test
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'

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

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: "go.mod"

      - name: Test CLI build and help
        run: |
          go build -o soundtouch-cli ./cmd/soundtouch-cli
          ./soundtouch-cli -help

      - name: Test library imports
        run: |
          cat > test_import.go << 'EOF'
          package main

          import (
              "fmt"
              "github.com/gesellix/bose-soundtouch/pkg/client"
              "github.com/gesellix/bose-soundtouch/pkg/models"
              "github.com/gesellix/bose-soundtouch/pkg/discovery"
              "github.com/gesellix/bose-soundtouch/pkg/config"
          )

          func main() {
              // Test basic client creation
              c := client.NewClientFromHost("192.168.1.100")
              fmt.Printf("Client created for %s\n", c.BaseURL())

              // Test models can be imported
              var info models.DeviceInfo
              fmt.Printf("DeviceInfo model available: %T\n", info)

              // Test discovery can be imported
              cfg := config.DefaultConfig()
              service := discovery.NewUnifiedDiscoveryService(cfg)
              fmt.Printf("Discovery service available: %T\n", service)

              fmt.Println("All imports successful!")
          }
          EOF

          go run test_import.go
          rm test_import.go

  docker:
    name: Docker Build
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    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
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        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=raw,value=edge,enable=${{ github.ref == 'refs/heads/main' }}
            type=ref,event=pr

      - 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: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
          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=raw,value=edge,enable=${{ github.ref == 'refs/heads/main' }}
            type=ref,event=pr

      - 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: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
          tags: ${{ steps.meta-web.outputs.tags }}
          labels: ${{ steps.meta-web.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  notify:
    name: Notify Status
    runs-on: ubuntu-latest
    needs: [test, lint, build, security, docs, docker]
    if: always()
    permissions:
      statuses: write
      contents: read

    steps:
      - name: Check overall status
        run: |
          if [[ "${{ needs.test.result }}" == "success" && \
                "${{ needs.lint.result }}" == "success" && \
                "${{ needs.build.result }}" == "success" && \
                "${{ needs.security.result }}" == "success" && \
                "${{ needs.docs.result }}" == "success" && \
                "${{ needs.docker.result }}" == "success" ]]; then
            echo "✅ All CI checks passed!"
            echo "status=success" >> $GITHUB_OUTPUT
          else
            echo "❌ Some CI checks failed"
            echo "Test: ${{ needs.test.result }}"
            echo "Lint: ${{ needs.lint.result }}"
            echo "Build: ${{ needs.build.result }}"
            echo "Security: ${{ needs.security.result }}"
            echo "Docs: ${{ needs.docs.result }}"
            echo "Docker: ${{ needs.docker.result }}"
            echo "status=failure" >> $GITHUB_OUTPUT
          fi
        id: status

      - name: Update commit status
        if: always()
        uses: actions/github-script@v9
        with:
          script: |
            try {
              const state = '${{ steps.status.outputs.status }}' === 'success' ? 'success' : 'failure';
              const description = state === 'success' ? 'All checks passed' : 'Some checks failed';

              await github.rest.repos.createCommitStatus({
                owner: context.repo.owner,
                repo: context.repo.repo,
                sha: context.sha,
                state: state,
                description: description,
                context: 'CI Pipeline'
              });

              console.log(`✅ Successfully updated commit status to: ${state}`);
            } catch (error) {
              console.log(`⚠️  Failed to update commit status: ${error.message}`);
              // Don't fail the workflow if status update fails
            }
