# SonarQube Code Quality Tasks
# Provides SonarQube analysis integration and issue management
#
# Configuration:
# - Set SONAR_TOKEN in .env file
# - Supports 1Password references: op://vault/item/field
# - Project key read from sonar-project.properties in repository root

version: '3'

vars:
  REPORT_PATH: '{{.PWD}}/.logs/sonar'
  SONAR_HOST: '{{.SONAR_HOST | default "https://sonarcloud.io"}}'

tasks:
  default:
    desc: 'Show available SonarQube tasks'
    aliases: [help, h]
    silent: true
    cmds:
      - |
        # Color codes
        GREEN='\033[0;32m'
        YELLOW='\033[0;33m'
        BOLD='\033[1m'
        NC='\033[0m'

        echo -e "${BOLD}SonarQube Code Quality${NC}"
        echo ""
        echo "Command                            Alias     Description                              Examples"
        echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
        echo -e "${BOLD}Analysis:${NC}"
        echo -e "  ${GREEN}task sonar:scan${NC}                  ${YELLOW}s${NC}         Run SonarQube analysis locally"
        echo -e "  ${GREEN}task sonar:download${NC}              ${YELLOW}dl${NC}        Download issues from SonarQube"
        echo -e "  ${GREEN}task sonar:issues${NC}                ${YELLOW}i${NC}         Display downloaded findings"
        echo ""
        echo -e "${BOLD}Configuration:${NC}"
        echo -e "  ${GREEN}task sonar:setup${NC}                           Install sonar-scanner CLI"
        echo ""
        echo -e "${BOLD}Usage Examples:${NC}"
        echo -e "  task sonar:download                        Download issues"
        echo -e "  task sonar:issues                          View findings"
        echo -e "  task sonar:scan                            Run local scan"
        echo ""

  setup:
    desc: Install sonar-scanner CLI if not present
    silent: true
    cmds:
      - |
        # Check if already installed
        if command -v sonar-scanner &> /dev/null; then
          exit 0
        fi

        # Color codes
        GREEN='\033[0;32m'
        NC='\033[0m'

        echo "Installing sonar-scanner..."

        # Detect OS
        OS="$(uname -s)"
        case "$OS" in
          Darwin)
            if command -v brew &> /dev/null; then
              brew install sonar-scanner --quiet
            else
              echo "Error: Homebrew not found. Install from https://brew.sh"
              exit 1
            fi
            ;;
          Linux)
            # Download to local directory
            INSTALL_DIR="$HOME/.local/bin"
            mkdir -p "$INSTALL_DIR"

            curl -sSL https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip -o /tmp/sonar-scanner.zip
            unzip -q /tmp/sonar-scanner.zip -d /tmp/
            mv /tmp/sonar-scanner-*/* "$INSTALL_DIR/"
            rm -rf /tmp/sonar-scanner*

            echo -e "${GREEN}✓${NC} Installed to $INSTALL_DIR"
            ;;
          *)
            echo "Error: Unsupported OS. Install from https://docs.sonarcloud.io"
            exit 1
            ;;
        esac

        if command -v sonar-scanner &> /dev/null; then
          echo -e "${GREEN}✓${NC} sonar-scanner installed"
        fi

  scan:
    desc: Run SonarQube analysis locally
    silent: true
    dotenv: ['.env']
    deps: [setup]
    cmds:
      - |
        # Color codes
        GREEN='\033[0;32m'
        RED='\033[0;31m'
        NC='\033[0m'

        # Source secrets if .env has 1Password references
        if [ -f .env ] && grep -q "op://" .env 2>/dev/null; then
          source $(task op:export)

          # Check if token is still encrypted (force a refresh)
          if [[ "${SONAR_TOKEN:-}" == *"op://"* ]]; then
            source $(task op:export:force)
          fi
        fi

        # Validate token
        if [ -z "$SONAR_TOKEN" ]; then
          echo -e "${RED}❌ SONAR_TOKEN not set${NC}" >&2
          echo "Add to .env: SONAR_TOKEN=your-token" >&2
          exit 1
        fi

        # Create report directory
        mkdir -p {{.REPORT_PATH}}

        # Run scanner
        sonar-scanner \
          -Dsonar.host.url={{.SONAR_HOST}} \
          -Dsonar.token=$SONAR_TOKEN \
          -Dsonar.working.directory={{.REPORT_PATH}}/.scannerwork \
          2>&1 | tee {{.REPORT_PATH}}/scan.log > /dev/null

        if [ $? -eq 0 ]; then
          echo -e "${GREEN}✓${NC} Scan complete → {{.REPORT_PATH}}/scan.log"
        else
          echo -e "${RED}❌ Scan failed${NC}" >&2
          exit 1
        fi

  download:
    desc: Download SonarQube issues for project
    aliases: [dl]
    silent: true
    dotenv: ['.env']
    cmds:
      - |
        set -euo pipefail

        # Color codes
        GREEN='\033[0;32m'
        RED='\033[0;31m'
        CYAN='\033[0;36m'
        NC='\033[0m'

        # Source secrets if .env has 1Password references
        if [ -f .env ] && grep -q "op://" .env 2>/dev/null; then
          source $(task op:export)

          # Check if token is still encrypted (force a refresh)
          if [[ "${SONAR_TOKEN:-}" == *"op://"* ]]; then
            source $(task op:export:force)
          fi
        fi

        # Validate token
        if [ -z "$SONAR_TOKEN" ]; then
          echo -e "${RED}❌ SONAR_TOKEN not set${NC}" >&2
          echo "Add to .env: SONAR_TOKEN=your-token" >&2
          exit 1
        fi

        # Read project key from sonar-project.properties
        if [ ! -f "sonar-project.properties" ]; then
          echo -e "${RED}❌ sonar-project.properties not found${NC}" >&2
          echo "Create configuration file in repository root" >&2
          exit 1
        fi

        PROJECT_KEY=$(grep "^sonar.projectKey=" sonar-project.properties | cut -d'=' -f2)
        if [ -z "$PROJECT_KEY" ]; then
          echo -e "${RED}❌ sonar.projectKey not found in sonar-project.properties${NC}" >&2
          exit 1
        fi

        # Detect PR context
        CURRENT_BRANCH=$(task git:branch:current)
        DEFAULT_BRANCH=$(task git:branch:default)
        PR_NUMBER=$(gh pr list --head "$CURRENT_BRANCH" --base "$DEFAULT_BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")

        # Show what we're analyzing
        if [ -n "$PR_NUMBER" ]; then
          PR_TITLE=$(gh pr view "$PR_NUMBER" --json title --jq '.title' 2>/dev/null || echo "")
          echo -e "${CYAN}ℹ${NC} Analyzing PR #$PR_NUMBER: $PR_TITLE"
          echo -e "${CYAN}ℹ${NC} Project: $PROJECT_KEY"
          echo -e "${CYAN}ℹ${NC} Branch: $CURRENT_BRANCH → $DEFAULT_BRANCH"
          ANALYSIS_TYPE="PR #$PR_NUMBER"
        else
          echo -e "${CYAN}ℹ${NC} Analyzing default branch"
          echo -e "${CYAN}ℹ${NC} Project: $PROJECT_KEY"
          echo -e "${CYAN}ℹ${NC} Branch: $DEFAULT_BRANCH"
          ANALYSIS_TYPE="Branch: $DEFAULT_BRANCH"
        fi
        echo ""

        # Create report directory
        mkdir -p {{.REPORT_PATH}}
        TIMESTAMP=$(date +%Y%m%d-%H%M%S)
        RAW_FILE="{{.REPORT_PATH}}/issues-${TIMESTAMP}-raw.json"
        REPORT_FILE="{{.REPORT_PATH}}/issues-${TIMESTAMP}.txt"

        # Fetch issues from SonarQube API (PR-specific or default branch)
        if [ -n "$PR_NUMBER" ]; then
          # Try PR-specific analysis first
          ISSUES_API="{{.SONAR_HOST}}/api/issues/search?pullRequest=$PR_NUMBER&componentKeys=$PROJECT_KEY&ps=500"
          HOTSPOTS_API="{{.SONAR_HOST}}/api/hotspots/search?pullRequest=$PR_NUMBER&projectKey=$PROJECT_KEY&ps=500"
          QG_API="{{.SONAR_HOST}}/api/qualitygates/project_status?projectKey=$PROJECT_KEY&pullRequest=$PR_NUMBER"

          # Fetch PR data
          ISSUES_DATA=$(curl -s -X GET "$ISSUES_API" -H "Authorization: Bearer $SONAR_TOKEN")
          PR_TOTAL=$(echo "$ISSUES_DATA" | jq '.total // 0')

          # If PR analysis doesn't exist or is empty, fall back to default branch
          if [ "$PR_TOTAL" -eq 0 ]; then
            echo -e "${YELLOW}⚠${NC}  PR analysis not found, showing default branch analysis"
            ANALYSIS_TYPE="Branch: $DEFAULT_BRANCH (PR not analyzed)"
            ISSUES_API="{{.SONAR_HOST}}/api/issues/search?componentKeys=$PROJECT_KEY&ps=500"
            HOTSPOTS_API="{{.SONAR_HOST}}/api/hotspots/search?projectKey=$PROJECT_KEY&ps=500"
            QG_API="{{.SONAR_HOST}}/api/qualitygates/project_status?projectKey=$PROJECT_KEY"
          fi
        else
          # Default branch analysis
          ISSUES_API="{{.SONAR_HOST}}/api/issues/search?componentKeys=$PROJECT_KEY&ps=500"
          HOTSPOTS_API="{{.SONAR_HOST}}/api/hotspots/search?projectKey=$PROJECT_KEY&ps=500"
          QG_API="{{.SONAR_HOST}}/api/qualitygates/project_status?projectKey=$PROJECT_KEY"
        fi

        # Fetch issues
        ISSUES_DATA=$(curl -s -X GET "$ISSUES_API" -H "Authorization: Bearer $SONAR_TOKEN")
        if [ $? -ne 0 ]; then
          echo -e "${RED}❌ Failed to fetch issues${NC}" >&2
          exit 1
        fi

        # Fetch security hotspots
        HOTSPOTS_DATA=$(curl -s -X GET "$HOTSPOTS_API" -H "Authorization: Bearer $SONAR_TOKEN")

        # Fetch quality gate status
        QG_DATA=$(curl -s -X GET "$QG_API" -H "Authorization: Bearer $SONAR_TOKEN")

        # Fetch coverage metrics
        if [ -n "$PR_NUMBER" ]; then
          MEASURES_API="{{.SONAR_HOST}}/api/measures/component?component=$PROJECT_KEY&pullRequest=$PR_NUMBER&metricKeys=new_coverage,new_lines_to_cover,new_uncovered_lines,coverage,lines_to_cover,uncovered_lines"
        else
          MEASURES_API="{{.SONAR_HOST}}/api/measures/component?component=$PROJECT_KEY&metricKeys=coverage,lines_to_cover,uncovered_lines"
        fi
        COVERAGE_DATA=$(curl -s -X GET "$MEASURES_API" -H "Authorization: Bearer $SONAR_TOKEN")

        # Save raw responses
        echo "$ISSUES_DATA" > "$RAW_FILE"
        echo "$HOTSPOTS_DATA" > "{{.REPORT_PATH}}/hotspots-${TIMESTAMP}-raw.json"
        echo "$QG_DATA" > "{{.REPORT_PATH}}/quality-gate-${TIMESTAMP}-raw.json"
        echo "$COVERAGE_DATA" > "{{.REPORT_PATH}}/coverage-${TIMESTAMP}-raw.json"

        # Count issues by severity
        TOTAL=$(echo "$ISSUES_DATA" | jq '.total // 0')
        BLOCKER=$(echo "$ISSUES_DATA" | jq '[.issues[] | select(.severity == "BLOCKER")] | length')
        CRITICAL=$(echo "$ISSUES_DATA" | jq '[.issues[] | select(.severity == "CRITICAL")] | length')
        MAJOR=$(echo "$ISSUES_DATA" | jq '[.issues[] | select(.severity == "MAJOR")] | length')
        MINOR=$(echo "$ISSUES_DATA" | jq '[.issues[] | select(.severity == "MINOR")] | length')

        # Count security hotspots
        HOTSPOTS_TOTAL=$(echo "$HOTSPOTS_DATA" | jq '.paging.total // 0')
        HOTSPOTS_TO_REVIEW=$(echo "$HOTSPOTS_DATA" | jq '[.hotspots[] | select(.status == "TO_REVIEW")] | length')
        HOTSPOTS_REVIEWED=$(echo "$HOTSPOTS_DATA" | jq '[.hotspots[] | select(.status == "REVIEWED")] | length')

        # Get quality gate status
        QG_STATUS=$(echo "$QG_DATA" | jq -r '.projectStatus.status // "NONE"')
        QG_CONDITIONS=$(echo "$QG_DATA" | jq -r '.projectStatus.conditions[]? | select(.status != "OK") | "  - \(.metricKey): \(.actualValue) (threshold: \(.errorThreshold // .warningThreshold))"' 2>/dev/null || echo "")

        # Generate report
        {
          echo "SonarQube Analysis Report"
          echo "========================="
          echo "Project: $PROJECT_KEY"
          echo "Analysis: $ANALYSIS_TYPE"
          echo "Date: $(date)"
          echo ""

          # Quality Gate Status
          echo "Quality Gate: $QG_STATUS"
          if [ "$QG_STATUS" != "OK" ] && [ -n "$QG_CONDITIONS" ]; then
            echo "Failed Conditions:"
            echo "$QG_CONDITIONS"
          fi
          echo ""

          # Issues Summary
          echo "Issues: $TOTAL"
          if [ "$TOTAL" -gt 0 ]; then
            echo "By Severity:"
            [ "$BLOCKER" -gt 0 ] && echo "  Blocker: $BLOCKER"
            [ "$CRITICAL" -gt 0 ] && echo "  Critical: $CRITICAL"
            [ "$MAJOR" -gt 0 ] && echo "  Major: $MAJOR"
            [ "$MINOR" -gt 0 ] && echo "  Minor: $MINOR"
          fi
          echo ""

          # Security Hotspots Summary
          echo "Security Hotspots: $HOTSPOTS_TOTAL"
          if [ "$HOTSPOTS_TOTAL" -gt 0 ]; then
            echo "  To Review: $HOTSPOTS_TO_REVIEW"
            echo "  Reviewed: $HOTSPOTS_REVIEWED"
          fi
          echo ""

          # Coverage Summary
          COVERAGE=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "coverage") | .value' 2>/dev/null || echo "")
          NEW_COVERAGE=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "new_coverage") | .periods[0].value' 2>/dev/null || echo "")
          LINES_TO_COVER=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "lines_to_cover") | .value' 2>/dev/null || echo "")
          UNCOVERED_LINES=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "uncovered_lines") | .value' 2>/dev/null || echo "")
          NEW_LINES_TO_COVER=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "new_lines_to_cover") | .periods[0].value' 2>/dev/null || echo "")
          NEW_UNCOVERED_LINES=$(echo "$COVERAGE_DATA" | jq -r '.component.measures[]? | select(.metric == "new_uncovered_lines") | .periods[0].value' 2>/dev/null || echo "")

          if [ -n "$COVERAGE" ] || [ -n "$NEW_COVERAGE" ]; then
            echo "Coverage:"
            if [ -n "$COVERAGE" ]; then
              echo "  Overall: ${COVERAGE}%"
              if [ -n "$LINES_TO_COVER" ] && [ -n "$UNCOVERED_LINES" ]; then
                COVERED_LINES=$((LINES_TO_COVER - UNCOVERED_LINES))
                echo "    Covered: $COVERED_LINES / $LINES_TO_COVER lines"
              fi
            fi
            if [ -n "$NEW_COVERAGE" ]; then
              echo "  New Code: ${NEW_COVERAGE}%"
              if [ -n "$NEW_LINES_TO_COVER" ] && [ -n "$NEW_UNCOVERED_LINES" ]; then
                NEW_COVERED_LINES=$(echo "$NEW_LINES_TO_COVER - $NEW_UNCOVERED_LINES" | bc)
                echo "    Covered: $NEW_COVERED_LINES / $NEW_LINES_TO_COVER new lines"
              fi
              # Highlight if below 80% threshold
              if [ -n "$NEW_COVERAGE" ] && (( $(echo "$NEW_COVERAGE < 80" | bc -l) )); then
                echo "    ⚠ Below 80% threshold"
              fi
            fi
            echo ""
          fi

          # Detailed Issues
          if [ "$TOTAL" -gt 0 ]; then
            echo "═══════════════════════════════════════════════════════════════"
            echo "DETAILED ISSUES"
            echo "═══════════════════════════════════════════════════════════════"
            echo ""

            echo "$ISSUES_DATA" | jq -r '.issues[] |
              "[\(.severity)] \(.component | split(":")[1]):\(.line // "??")\n" +
              "Type: \(.type)\n" +
              "Rule: \(.rule)\n" +
              "Message: \(.message)\n" +
              "───────────────────────────────────────────────────────────────"'
          fi

          # Detailed Security Hotspots
          if [ "$HOTSPOTS_TOTAL" -gt 0 ]; then
            echo ""
            echo "═══════════════════════════════════════════════════════════════"
            echo "SECURITY HOTSPOTS"
            echo "═══════════════════════════════════════════════════════════════"
            echo ""

            echo "$HOTSPOTS_DATA" | jq -r '.hotspots[] |
              "[\(.vulnerabilityProbability)] \(.component | split(":")[1]):\(.line // "??")\n" +
              "Status: \(.status)\n" +
              "Category: \(.securityCategory)\n" +
              "Message: \(.message)\n" +
              "───────────────────────────────────────────────────────────────"'
          fi

          # Summary at bottom
          if [ "$TOTAL" -eq 0 ] && [ "$HOTSPOTS_TOTAL" -eq 0 ]; then
            echo "No issues or security hotspots found."
          fi
        } > "$REPORT_FILE"

        # Calculate total findings
        TOTAL_FINDINGS=$((TOTAL + HOTSPOTS_TOTAL))

        # Display summary
        if [ "$QG_STATUS" != "OK" ]; then
          echo -e "${RED}❌ Quality Gate: $QG_STATUS${NC}"
        else
          echo -e "${GREEN}✓${NC} Quality Gate: $QG_STATUS"
        fi

        if [ "$TOTAL_FINDINGS" -gt 0 ]; then
          echo -e "${CYAN}ℹ${NC} Downloaded $TOTAL issues + $HOTSPOTS_TOTAL hotspots → $REPORT_FILE"

          # Open in VSCode only if findings exist
          if command -v code &> /dev/null; then
            code "$REPORT_FILE" 2>/dev/null || true
          fi
        else
          echo -e "${GREEN}✓${NC} No issues or hotspots found"
        fi

  issues:
    desc: Display most recent SonarQube findings
    aliases: [i]
    silent: true
    cmds:
      - |
        # Color codes
        GREEN='\033[0;32m'
        RED='\033[0;31m'
        NC='\033[0m'

        # Find most recent report
        LATEST_REPORT=$(ls -t {{.REPORT_PATH}}/issues-*.txt 2>/dev/null | head -1)

        if [ -z "$LATEST_REPORT" ]; then
          echo -e "${RED}❌ No reports found${NC}" >&2
          echo "Run: task sonar:download" >&2
          exit 1
        fi

        # Extract summary
        TOTAL=$(grep "^Total issues:" "$LATEST_REPORT" | awk '{print $3}')
        echo -e "${GREEN}✓${NC} Found $TOTAL issues → $LATEST_REPORT"

        # Open in VSCode
        if command -v code &> /dev/null; then
          code "$LATEST_REPORT" 2>/dev/null || true
        fi
