name: Docker Browser Build

on:
  push:
    branches:
      - master
      - release
      - beta
    paths:
      - 'Dockerfile.browser'
      - 'src/server.ts'
      - 'src/AuthManager.ts'
      - 'app/**'
      - 'backend/**'
      - 'package.json'
      - 'yarn.lock'
      - '.github/workflows/docker-browser.yml'
      - 'tsconfig.json'
      - 'events/**'
  schedule:
    # Run every two weeks (1st and 15th of each month) at 2:00 AM UTC
    - cron: '0 2 1,15 * *'
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write

    env:
      TESTS_MQTT_BROKER_HOST: localhost
      TESTS_MQTT_BROKER_PORT: 1883

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install and Start Mosquitto
        run: |
          sudo apt-get update
          sudo apt-get install -y mosquitto mosquitto-clients
          
          # Create a minimal configuration file for testing
          sudo tee /etc/mosquitto/conf.d/test.conf > /dev/null <<EOF
          listener 1883
          allow_anonymous true
          persistence false
          EOF
          
          # Start mosquitto in detached mode
          sudo mosquitto -c /etc/mosquitto/mosquitto.conf -d

      - 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: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=ref,event=branch
            type=sha,prefix={{branch}}-
            type=raw,value=latest,enable={{is_default_branch}}

      - name: Build Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile.browser
          platforms: linux/amd64
          push: false
          load: true
          tags: mqtt-explorer:test
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Test Docker image - Basic startup
        run: |
          # Start container with test credentials
          docker run -d \
            --name mqtt-explorer-test \
            -p 3000:3000 \
            -e MQTT_EXPLORER_USERNAME=test \
            -e MQTT_EXPLORER_PASSWORD=test123 \
            -e PORT=3000 \
            mqtt-explorer:test

          # Wait for server to be ready (max 60 seconds)
          echo "Waiting for server to start..."
          for i in {1..60}; do
            if curl -f http://localhost:3000 > /dev/null 2>&1; then
              echo "Server started successfully after $i seconds"
              break
            fi
            if [ $i -eq 60 ]; then
              echo "Server failed to start within 60 seconds"
              docker logs mqtt-explorer-test
              exit 1
            fi
            sleep 1
          done

      - name: Test Docker image - Health check
        run: |
          # Wait for health check to pass
          echo "Waiting for health check to pass..."
          for i in {1..30}; do
            health=$(docker inspect --format='{{.State.Health.Status}}' mqtt-explorer-test)
            if [ "$health" = "healthy" ]; then
              echo "Container is healthy"
              break
            fi
            if [ $i -eq 30 ]; then
              echo "Health check failed"
              docker logs mqtt-explorer-test
              exit 1
            fi
            sleep 2
          done

      - name: Test Docker image - Verify response
        run: |
          # Test that the server responds with HTML
          response=$(curl -s http://localhost:3000)
          if echo "$response" | grep -q "MQTT Explorer"; then
            echo "Server is serving the application correctly"
          else
            echo "Server response does not contain expected content"
            echo "Response: $response"
            exit 1
          fi

      - name: Test Docker image - Verify data persistence
        run: |
          # Check that data directory was created
          docker exec mqtt-explorer-test sh -c '[ -d /app/data ] && echo "Data directory exists"'

      - name: Clean up test container
        if: always()
        run: |
          docker stop mqtt-explorer-test || true
          docker rm mqtt-explorer-test || true

      - name: Check Docker image size
        run: |
          echo "### Docker Image Size" >> $GITHUB_STEP_SUMMARY
          docker images mqtt-explorer:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" >> $GITHUB_STEP_SUMMARY
          
          # Get size in bytes for detailed reporting
          SIZE_BYTES=$(docker inspect mqtt-explorer:test --format='{{.Size}}')
          SIZE_MB=$((SIZE_BYTES / 1024 / 1024))
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Image size**: ${SIZE_MB} MB (${SIZE_BYTES} bytes)" >> $GITHUB_STEP_SUMMARY
          echo "Image size: ${SIZE_MB} MB"

      - name: Setup Node.js for browser tests
        uses: actions/setup-node@v4
        with:
          node-version: '24'
          cache: 'yarn'

      - name: Install dependencies for browser tests
        run: yarn install --frozen-lockfile

      - name: Install Playwright Browsers
        run: npx playwright install --with-deps chromium

      - name: Start Docker container for browser tests
        run: |
          docker run -d \
            --name mqtt-explorer-browser-test \
            --network host \
            -e MQTT_EXPLORER_USERNAME=test \
            -e MQTT_EXPLORER_PASSWORD=test123 \
            -e PORT=3000 \
            mqtt-explorer:test
          
          # Wait for server to be ready
          echo "Waiting for Docker container to be ready..."
          timeout 60 bash -c 'until curl -f http://localhost:3000; do sleep 1; done'
          echo "Docker container is ready"

      - name: Run browser test suite
        run: |
          yarn test:browser
        env:
          MQTT_EXPLORER_USERNAME: test
          MQTT_EXPLORER_PASSWORD: test123
          BROWSER_MODE_URL: http://localhost:3000

      - name: Clean up browser test container
        if: always()
        run: |
          docker logs mqtt-explorer-browser-test || true
          docker stop mqtt-explorer-browser-test || true
          docker rm mqtt-explorer-browser-test || true

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

      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v1
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}
          push-to-registry: true
