name: Lint & Build

on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    name: Build Firmware
    needs: [cppcheck, flawfinder, gitleaks]
    runs-on: anvil
    container:
      image: docker.io/espressif/idf:v5.5
      volumes:
        - /var/cache/ccache:/ccache
    env:
      CCACHE_DIR: /ccache
      IDF_CCACHE_ENABLE: 1
    steps:
      - name: Checkout
        run: |
          git clone --depth=1 --branch=${{ github.ref_name }} \
            https://oauth2:${{ github.token }}@git.mymx.me/${{ github.repository }}.git .

      - name: Setup ccache
        run: |
          apt-get update && apt-get install -y --no-install-recommends ccache
          ccache --zero-stats
          ccache --show-config | grep -E "(cache_dir|max_size)"

      - name: Build firmware
        run: |
          . /opt/esp/idf/export.sh
          cd get-started/csi_recv_router
          idf.py build

      - name: Show ccache stats
        run: ccache --show-stats

      - name: Show binary size
        run: |
          ls -lh get-started/csi_recv_router/build/*.bin

      - name: Check firmware size
        run: |
          BIN="get-started/csi_recv_router/build/csi_recv_router.bin"
          MAX_SIZE=1966080  # 0x1E0000 = 1920 KB partition
          WARN_PERCENT=85

          SIZE=$(stat -c%s "$BIN")
          PERCENT=$((SIZE * 100 / MAX_SIZE))

          echo "Firmware: $((SIZE/1024)) KB / $((MAX_SIZE/1024)) KB ($PERCENT%)"

          if [ $SIZE -gt $MAX_SIZE ]; then
            echo "::error::Firmware exceeds partition size!"
            exit 1
          fi

          if [ $PERCENT -gt $WARN_PERCENT ]; then
            echo "::warning::Firmware using $PERCENT% of partition"
          fi

      - name: Security checks
        run: |
          BIN="get-started/csi_recv_router/build/csi_recv_router.bin"
          CFG="get-started/csi_recv_router/sdkconfig"

          echo "=== Checking for hardcoded secrets ==="
          if strings "$BIN" | grep -iqE '(password|secret|api_key|apikey)=[^$]'; then
            echo "::error::Potential hardcoded secret found in binary"
            exit 1
          fi
          echo "No hardcoded secrets detected"

          echo "=== Checking release configuration ==="
          LOG_LEVEL=$(grep 'CONFIG_LOG_DEFAULT_LEVEL=' "$CFG" | cut -d= -f2)
          if [ "$LOG_LEVEL" -gt 3 ]; then
            echo "::warning::Debug/verbose logging enabled (level $LOG_LEVEL)"
          else
            echo "Log level OK ($LOG_LEVEL)"
          fi

          echo "=== Component size breakdown ==="
          . /opt/esp/idf/export.sh
          cd get-started/csi_recv_router
          idf.py size-components 2>/dev/null | head -30

      - name: Create release
        if: startsWith(github.ref, 'refs/tags/v')
        run: |
          BIN="get-started/csi_recv_router/build/csi_recv_router.bin"
          TAG="${{ github.ref_name }}"
          API="https://git.mymx.me/api/v1/repos/${{ github.repository }}"
          TOKEN="${{ github.token }}"
          SIZE=$(stat -c%s "$BIN")

          RELEASE_ID=$(curl -sS -f -X POST "$API/releases" \
            -H "Authorization: token $TOKEN" \
            -H "Content-Type: application/json" \
            -d "{
              \"tag_name\": \"$TAG\",
              \"name\": \"$TAG\",
              \"body\": \"Firmware $TAG — $((SIZE / 1024)) KB\"
            }" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")

          echo "Release $RELEASE_ID created for $TAG"

          curl -sS -f -X POST \
            "$API/releases/$RELEASE_ID/assets?name=csi_recv_router.bin" \
            -H "Authorization: token $TOKEN" \
            -H "Content-Type: application/octet-stream" \
            --data-binary @"$BIN"

          echo "Uploaded csi_recv_router.bin ($((SIZE / 1024)) KB)"

  cppcheck:
    name: C/C++ Static Analysis
    runs-on: anvil
    container:
      image: docker.io/library/debian:bookworm-slim
    steps:
      - name: Install tools
        run: |
          apt-get update && apt-get install -y --no-install-recommends git cppcheck ca-certificates

      - name: Checkout
        run: |
          git clone --depth=1 --branch=${{ github.ref_name }} \
            https://oauth2:${{ github.token }}@git.mymx.me/${{ github.repository }}.git .

      - name: Run cppcheck
        run: |
          cppcheck --enable=warning,style,performance,portability \
            --suppress=missingIncludeSystem \
            --error-exitcode=1 \
            --inline-suppr \
            -I get-started/csi_recv_router/main \
            get-started/csi_recv_router/main/*.c

  flawfinder:
    name: Security Flaw Analysis
    runs-on: anvil
    container:
      image: docker.io/library/python:3.12-slim
    steps:
      - name: Install tools
        run: |
          apt-get update && apt-get install -y --no-install-recommends git ca-certificates
          pip install --no-cache-dir flawfinder

      - name: Checkout
        run: |
          git clone --depth=1 --branch=${{ github.ref_name }} \
            https://oauth2:${{ github.token }}@git.mymx.me/${{ github.repository }}.git .

      - name: Run flawfinder
        run: |
          flawfinder --minlevel=2 --error-level=4 \
            get-started/csi_recv_router/main/

  gitleaks:
    name: Secret Scanning
    runs-on: anvil
    container:
      image: docker.io/zricethezav/gitleaks:latest
    steps:
      - name: Checkout
        run: |
          git clone --branch=${{ github.ref_name }} \
            https://oauth2:${{ github.token }}@git.mymx.me/${{ github.repository }}.git .

      - name: Run gitleaks
        run: gitleaks detect --source . --verbose --redact
