#!/bin/bash
set -euo pipefail

# ============================================================================
# PR Review Orchestrator with Priority Organization
# ============================================================================
# Comprehensive PR review that fetches all feedback from 4 GitHub endpoints,
# organizes by priority, and enforces strict resolution requirements.
#
# Priority Levels:
#   CRITICAL - Must be addressed before merge (blocking)
#   MAJOR    - Should be addressed before merge (important)
#   MINOR    - Should be addressed but not blocking
#   NIT      - Optional improvements (nice to have)
#
# Merge Requirements:
#   ✅ ALL Critical issues resolved
#   ✅ ALL Major issues resolved
#   ✅ ALL Minor issues resolved
#   ⚠️  Nits are optional (nice to have)
# ============================================================================

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

usage() {
    cat << EOF
Usage: $(basename "$0") <PR_NUMBER> [OPTIONS]

Comprehensive PR review with priority-based issue organization.

Arguments:
  PR_NUMBER    PR number or GitHub URL

Options:
  --output-file FILE   Save organized review to file (default: {REPO}/tmp/pr-review-{PR}.md)
  --strict             Exit with error if any critical/major/minor issues found
  --json               Output in JSON format instead of markdown

Priority Levels (in order of severity):
  🔴 CRITICAL - Must be addressed before merge (blocking issues)
     Examples: Security vulnerabilities, data loss, system crashes

  🟠 MAJOR - Should be addressed before merge (important issues)
     Examples: Performance problems, incorrect behavior, missing tests

  🟡 MINOR - Should be addressed but not blocking
     Examples: Code quality issues, missing documentation, edge cases

  ⚪ NIT - Optional improvements (nice to have)
     Examples: Formatting preferences, minor refactoring suggestions

Merge Readiness:
  ✅ Can merge when: All Critical, Major, and Minor issues resolved
  ⚠️  Nits are optional: Can merge even if nits remain unresolved

Examples:
  # Review PR with priority organization
  $(basename "$0") 22

  # Strict mode (fail if issues found)
  $(basename "$0") 22 --strict

  # Save to file
  $(basename "$0") 22 --output-file ./tmp/pr22-review.md

  # JSON output for programmatic processing
  $(basename "$0") 22 --json

Exit codes:
  0 - Success (or only nits found)
  1 - Invalid arguments or missing dependencies
  2 - Critical, Major, or Minor issues found (when --strict)
  3 - GitHub API error
EOF
    exit 1
}

# Check dependencies
check_dependencies() {
    local missing_deps=()

    if ! command -v jq &> /dev/null; then
        missing_deps+=("jq")
    fi

    # Check if fetch-pr-data exists
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    if [[ ! -x "$script_dir/fetch-pr-data" ]]; then
        missing_deps+=("fetch-pr-data (not found at $script_dir/fetch-pr-data)")
    fi

    if [ ${#missing_deps[@]} -ne 0 ]; then
        echo -e "${RED}✗${NC} Missing required dependencies:"
        for dep in "${missing_deps[@]}"; do
            echo "  - $dep"
        done
        echo ""
        echo "Install with:"
        echo "  brew install jq"
        exit 1
    fi
}

# Extract PR number from argument (handles URLs)
extract_pr_number() {
    local input="$1"

    if [[ "$input" =~ pull/([0-9]+) ]]; then
        echo "${BASH_REMATCH[1]}"
    elif [[ "$input" =~ ^[0-9]+$ ]]; then
        echo "$input"
    else
        echo -e "${RED}✗${NC} Invalid PR number or URL: $input"
        exit 1
    fi
}

# Classify issue priority based on keywords in comment body
classify_priority() {
    local body="$1"
    local body_lower=$(echo "$body" | tr '[:upper:]' '[:lower:]')

    # Critical indicators
    if echo "$body_lower" | grep -qE "(critical|security|vulnerability|data loss|crash|breaking change)"; then
        echo "CRITICAL"
        return
    fi

    # Major indicators
    if echo "$body_lower" | grep -qE "(major|bug|error|incorrect|performance|test|missing|should|important)"; then
        echo "MAJOR"
        return
    fi

    # Nit indicators
    if echo "$body_lower" | grep -qE "(nit|nitpick|minor|consider|suggestion|optional|nice to have|style|formatting)"; then
        echo "NIT"
        return
    fi

    # Default to MINOR
    echo "MINOR"
}

# Categorize all comments by priority
categorize_comments() {
    local pr_data="$1"

    # Initialize categories
    local critical=()
    local major=()
    local minor=()
    local nit=()

    # Process all comment types
    for comment_type in "reviews" "inline_comments" "pr_comments" "issue_comments"; do
        local comments=$(echo "$pr_data" | jq -c ".${comment_type}[]" 2>/dev/null || echo "")

        while IFS= read -r comment; do
            [[ -z "$comment" ]] && continue

            local body=$(echo "$comment" | jq -r '.body')
            local priority=$(classify_priority "$body")

            case "$priority" in
                CRITICAL)
                    critical+=("$comment")
                    ;;
                MAJOR)
                    major+=("$comment")
                    ;;
                MINOR)
                    minor+=("$comment")
                    ;;
                NIT)
                    nit+=("$comment")
                    ;;
            esac
        done <<< "$comments"
    done

    # Output categorized comments as JSON
    jq -n \
        --argjson critical "$(printf '%s\n' "${critical[@]+"${critical[@]}"}" | jq -s '.' 2>/dev/null || echo '[]')" \
        --argjson major "$(printf '%s\n' "${major[@]+"${major[@]}"}" | jq -s '.' 2>/dev/null || echo '[]')" \
        --argjson minor "$(printf '%s\n' "${minor[@]+"${minor[@]}"}" | jq -s '.' 2>/dev/null || echo '[]')" \
        --argjson nit "$(printf '%s\n' "${nit[@]+"${nit[@]}"}" | jq -s '.' 2>/dev/null || echo '[]')" \
        '{
            critical: $critical,
            major: $major,
            minor: $minor,
            nit: $nit,
            summary: {
                critical_count: ($critical | length),
                major_count: ($major | length),
                minor_count: ($minor | length),
                nit_count: ($nit | length),
                total: (($critical | length) + ($major | length) + ($minor | length) + ($nit | length))
            }
        }'
}

# Format output as markdown
format_markdown() {
    local categorized="$1"
    local pr_number="$2"

    cat << EOF
# PR #${pr_number} - Review Summary

**Generated**: $(date '+%Y-%m-%d %H:%M:%S')

## Priority Breakdown

| Priority | Count | Status |
|----------|-------|--------|
| 🔴 CRITICAL | $(echo "$categorized" | jq '.summary.critical_count') | Must resolve before merge |
| 🟠 MAJOR | $(echo "$categorized" | jq '.summary.major_count') | Should resolve before merge |
| 🟡 MINOR | $(echo "$categorized" | jq '.summary.minor_count') | Should resolve |
| ⚪ NIT | $(echo "$categorized" | jq '.summary.nit_count') | Optional (nice to have) |

**Total Issues**: $(echo "$categorized" | jq '.summary.total')

## Merge Readiness

EOF

    local critical_count=$(echo "$categorized" | jq '.summary.critical_count')
    local major_count=$(echo "$categorized" | jq '.summary.major_count')
    local minor_count=$(echo "$categorized" | jq '.summary.minor_count')
    local nit_count=$(echo "$categorized" | jq '.summary.nit_count')

    if [[ $critical_count -gt 0 ]] || [[ $major_count -gt 0 ]] || [[ $minor_count -gt 0 ]]; then
        echo "❌ **NOT READY TO MERGE**"
        echo ""
        if [[ $critical_count -gt 0 ]]; then
            echo "- ❌ $critical_count Critical issue(s) must be resolved"
        fi
        if [[ $major_count -gt 0 ]]; then
            echo "- ❌ $major_count Major issue(s) should be resolved"
        fi
        if [[ $minor_count -gt 0 ]]; then
            echo "- ⚠️  $minor_count Minor issue(s) should be resolved"
        fi
    else
        echo "✅ **READY TO MERGE**"
        echo ""
        echo "All critical, major, and minor issues have been resolved."
        if [[ $nit_count -gt 0 ]]; then
            echo ""
            echo "⚪ $nit_count nit(s) remain but are optional."
        fi
    fi

    echo ""
    echo "---"
    echo ""

    # Output each priority category
    for priority in "critical" "major" "minor" "nit"; do
        local priority_upper=$(echo "$priority" | tr '[:lower:]' '[:upper:]')
        local count=$(echo "$categorized" | jq ".summary.${priority}_count")

        if [[ $count -eq 0 ]]; then
            continue
        fi

        case "$priority" in
            critical) echo "## 🔴 CRITICAL Issues ($count)" ;;
            major) echo "## 🟠 MAJOR Issues ($count)" ;;
            minor) echo "## 🟡 MINOR Issues ($count)" ;;
            nit) echo "## ⚪ NIT / Nice to Have ($count)" ;;
        esac

        echo ""

        local issues=$(echo "$categorized" | jq -c ".${priority}[]")
        local issue_num=1

        while IFS= read -r issue; do
            [[ -z "$issue" ]] && continue

            local author=$(echo "$issue" | jq -r '.author')
            local body=$(echo "$issue" | jq -r '.body' | head -c 200)
            local path=$(echo "$issue" | jq -r '.path // "N/A"')

            echo "### ${priority_upper}-${issue_num}: $author"
            if [[ "$path" != "N/A" ]]; then
                echo "**File**: \`$path\`"
            fi
            echo ""
            echo "$body..."
            echo ""
            echo "---"
            echo ""

            ((issue_num++))
        done <<< "$issues"
    done
}

# Main function
main() {
    local pr_number=""
    local output_file=""
    local strict_mode=false
    local json_output=false
    # TODO: Add --show-resolved flag support
    # Requires filtering resolved comments from GitHub API data
    # in categorize_comments function

    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            --output-file)
                output_file="$2"
                shift 2
                ;;
            --strict)
                strict_mode=true
                shift
                ;;
            --json)
                json_output=true
                shift
                ;;
            -h|--help)
                usage
                ;;
            *)
                if [[ -z "$pr_number" ]]; then
                    pr_number="$1"
                else
                    echo "Error: Unknown argument: $1"
                    usage
                fi
                shift
                ;;
        esac
    done

    if [[ -z "$pr_number" ]]; then
        usage
    fi

    check_dependencies

    pr_number=$(extract_pr_number "$pr_number")

    echo -e "${BLUE}[PR-REVIEW]${NC} Fetching PR #${pr_number} data..."

    # Fetch all PR data using fetch-pr-data skill
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local pr_data
    pr_data=$("$script_dir/fetch-pr-data" "$pr_number" 2>/dev/null) || {
        echo -e "${RED}✗${NC} Failed to fetch PR data"
        exit 3
    }

    echo -e "${GREEN}✓${NC} PR data fetched successfully"
    echo -e "${BLUE}[PR-REVIEW]${NC} Categorizing issues by priority..."

    # Categorize comments by priority
    local categorized
    categorized=$(categorize_comments "$pr_data")

    echo -e "${GREEN}✓${NC} Issues categorized"

    # Determine output file (use repo tmp directory)
    if [[ -z "$output_file" ]]; then
        # Get repo root (traverse up from script location)
        local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
        local repo_root="$(cd "$script_dir/../.." && pwd)"
        mkdir -p "$repo_root/tmp"
        output_file="$repo_root/tmp/pr-review-${pr_number}.md"
    fi

    # Generate output
    if [[ "$json_output" == true ]]; then
        echo "$categorized" | tee "$output_file"
    else
        format_markdown "$categorized" "$pr_number" | tee "$output_file"
    fi

    echo ""
    echo -e "${GREEN}✓${NC} Review saved to: $output_file"

    # Check strict mode
    if [[ "$strict_mode" == true ]]; then
        local critical_count=$(echo "$categorized" | jq '.summary.critical_count')
        local major_count=$(echo "$categorized" | jq '.summary.major_count')
        local minor_count=$(echo "$categorized" | jq '.summary.minor_count')

        if [[ $critical_count -gt 0 ]] || [[ $major_count -gt 0 ]] || [[ $minor_count -gt 0 ]]; then
            echo ""
            echo -e "${RED}✗${NC} PR has unresolved Critical/Major/Minor issues (strict mode)"
            exit 2
        fi
    fi
}

main "$@"
