# VibeSniffer GitHub Action
# Add this file to your repo at .github/workflows/vibesniffer.yml
# Scans every PR for security issues and code quality problems
# Learn more: https://vibesniffer.com/ci-integration

name: VibeSniffer Scan

on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  pull-requests: write

jobs:
  vibesniffer:
    name: VibeSniffer Security Scan
    runs-on: ubuntu-latest
    steps:
      - name: Run VibeSniffer scan
        id: scan
        run: |
          REPO_URL="https://github.com/${{ github.repository }}"

          RESPONSE=$(curl -s -w "\n%{http_code}" \
            -X POST "https://vibesniffer.com/api/ci" \
            -H "Content-Type: application/json" \
            -d "{\"repoUrl\": \"${REPO_URL}\"}")

          HTTP_CODE=$(echo "$RESPONSE" | tail -1)
          BODY=$(echo "$RESPONSE" | sed '$d')

          if [ "$HTTP_CODE" != "200" ]; then
            echo "VibeSniffer scan failed (HTTP $HTTP_CODE)"
            echo "$BODY"
            exit 1
          fi

          # Parse results
          GRADE=$(echo "$BODY" | jq -r '.grade')
          SCORE=$(echo "$BODY" | jq -r '.score')
          CRITICAL=$(echo "$BODY" | jq -r '.summary.critical')
          WARNINGS=$(echo "$BODY" | jq -r '.summary.warnings')
          INFO=$(echo "$BODY" | jq -r '.summary.info')
          TOTAL=$(echo "$BODY" | jq -r '.summary.total')
          SCAN_ID=$(echo "$BODY" | jq -r '.id')

          echo "grade=$GRADE" >> $GITHUB_OUTPUT
          echo "score=$SCORE" >> $GITHUB_OUTPUT
          echo "critical=$CRITICAL" >> $GITHUB_OUTPUT
          echo "warnings=$WARNINGS" >> $GITHUB_OUTPUT
          echo "info=$INFO" >> $GITHUB_OUTPUT
          echo "total=$TOTAL" >> $GITHUB_OUTPUT
          echo "scan_id=$SCAN_ID" >> $GITHUB_OUTPUT

          # Build findings summary for PR comment
          FINDINGS_MD=""
          FINDING_COUNT=$(echo "$BODY" | jq '.findings | length')

          if [ "$FINDING_COUNT" -gt 0 ]; then
            FINDINGS_MD=$(echo "$BODY" | jq -r '
              .findings[:20] | to_entries[] |
              "| " + (
                if .value.severity == "critical" then "🔴"
                elif .value.severity == "warning" then "🟡"
                else "🔵" end
              ) + " | `" + .value.file + ":" + (.value.line | tostring) + "` | " + .value.title + " |"
            ')
          fi

          # Store findings for comment step (use delimiter for multiline)
          {
            echo "findings_md<<VIBESNIFFER_EOF"
            echo "$FINDINGS_MD"
            echo "VIBESNIFFER_EOF"
          } >> $GITHUB_OUTPUT

      - name: Post PR comment
        uses: actions/github-script@v7
        with:
          script: |
            const grade = '${{ steps.scan.outputs.grade }}';
            const score = '${{ steps.scan.outputs.score }}';
            const critical = '${{ steps.scan.outputs.critical }}';
            const warnings = '${{ steps.scan.outputs.warnings }}';
            const info = '${{ steps.scan.outputs.info }}';
            const total = '${{ steps.scan.outputs.total }}';
            const findingsMd = `${{ steps.scan.outputs.findings_md }}`;

            const gradeEmoji = {
              'A': '🟢', 'B': '🟢', 'C': '🟡', 'D': '🔴', 'F': '🔴'
            };

            let body = `## ${gradeEmoji[grade] || '⚪'} VibeSniffer Scan: Grade ${grade} (${score}/100)\n\n`;
            body += `| Critical | Warnings | Info | Total |\n`;
            body += `|----------|----------|------|-------|\n`;
            body += `| 🔴 ${critical} | 🟡 ${warnings} | 🔵 ${info} | ${total} |\n\n`;

            if (findingsMd && findingsMd.trim()) {
              body += `### Findings\n\n`;
              body += `| Severity | Location | Issue |\n`;
              body += `|----------|----------|-------|\n`;
              body += findingsMd + '\n\n';

              if (parseInt(total) > 20) {
                body += `> Showing top 20 of ${total} findings.\n\n`;
              }
            } else {
              body += `✨ No issues found — your code is looking clean!\n\n`;
            }

            if (grade === 'D' || grade === 'F') {
              body += `> ⚠️ **This PR has a grade of ${grade}.** Please review the findings above before merging.\n\n`;
            }

            body += `---\n🐺 Scanned by [VibeSniffer](https://vibesniffer.com) — free security scanner for vibe coders`;

            // Find existing VibeSniffer comment to update
            const { data: comments } = await github.rest.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
            });

            const existingComment = comments.find(c =>
              c.body && c.body.includes('VibeSniffer Scan:')
            );

            if (existingComment) {
              await github.rest.issues.updateComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                comment_id: existingComment.id,
                body,
              });
            } else {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.issue.number,
                body,
              });
            }

      - name: Fail on bad grade
        if: ${{ steps.scan.outputs.grade == 'D' || steps.scan.outputs.grade == 'F' }}
        run: |
          echo "❌ VibeSniffer grade: ${{ steps.scan.outputs.grade }} — failing check."
          echo "Fix critical issues before merging."
          exit 1
