#!/bin/bash

# Comprehensive Error Handling Library for AI Workflows
# Provides structured error handling, classification, and reporting
#
# Features:
# - Structured error classification and reporting
# - Integration with retry mechanisms
# - Circuit breaker awareness
# - Comprehensive logging with sanitization
# - Recovery suggestions and documentation

set -eo pipefail

# Basic logging functions
log_error() {
    echo "ERROR: $*" >&2
}

log_warn() {
    echo "WARNING: $*" >&2
}

log_info() {
    echo "INFO: $*" >&2
}

# Source retry utilities
source "$(dirname "${BASH_SOURCE[0]}")/retry-utils.sh"

# Error severity levels
ERROR_SEVERITY_CRITICAL=1
ERROR_SEVERITY_HIGH=2
ERROR_SEVERITY_MEDIUM=3
ERROR_SEVERITY_LOW=4

# Recovery action types
RECOVERY_ACTION_RETRY=1
RECOVERY_ACTION_MANUAL=2
RECOVERY_ACTION_ESCALATE=3
RECOVERY_ACTION_IGNORE=4

# Generate structured error report
generate_error_report() {
    local operation="$1"
    local exit_code="$2"
    local error_output="$3"
    local report_file="$4"
    local context="${5:-}"

    local timestamp=$(date '+%Y-%m-%d %H:%M:%S UTC')
    local error_type=$(classify_error "$exit_code" "$error_output")
    local severity=$(get_error_severity "$error_type" "$exit_code")
    local recovery_action=$(get_recovery_action "$error_type" "$severity")

    cat > "$report_file" << EOF
# Error Report

**Timestamp:** $timestamp
**Operation:** $operation
**Exit Code:** $exit_code
**Error Type:** $(get_error_type_name "$error_type")
**Severity:** $(get_severity_name "$severity")
**Recovery Action:** $(get_recovery_action_name "$recovery_action")

## Error Details

\`\`\`
$(echo "$error_output" | head -20)
\`\`\`

## Context

$(if [[ -n "$context" ]]; then echo "$context"; else echo "No additional context provided"; fi)

## Error Classification

- **Type Code:** $error_type
- **Retryable:** $(if is_retryable_error "$error_type"; then echo "Yes"; else echo "No"; fi)
- **Typical Causes:** $(get_error_causes "$error_type")

## Recommended Actions

$(get_recovery_recommendations "$error_type" "$severity" "$exit_code")

## Technical Details

- **Process ID:** $$
- **Working Directory:** $(pwd)
- **User:** $(whoami)
- **Environment:** $(if [[ -n "${CI:-}" ]]; then echo "CI/CD"; else echo "Local"; fi)

## Related Documentation

$(get_related_documentation "$error_type")

---
*Generated by AI Workflow Error Handler*
EOF

    echo "📄 Error report generated: $report_file"
}

# Get error type name for display
get_error_type_name() {
    local error_type="$1"

    case $error_type in
        $ERROR_TYPE_NETWORK)    echo "Network Connectivity" ;;
        $ERROR_TYPE_RATE_LIMIT) echo "API Rate Limiting" ;;
        $ERROR_TYPE_AUTH)       echo "Authentication" ;;
        $ERROR_TYPE_API)        echo "API Error" ;;
        $ERROR_TYPE_TIMEOUT)    echo "Timeout" ;;
        *)                      echo "Unknown" ;;
    esac
}

# Determine error severity based on type and exit code
get_error_severity() {
    local error_type="$1"
    local exit_code="$2"

    case $error_type in
        $ERROR_TYPE_AUTH)
            echo $ERROR_SEVERITY_CRITICAL  # Auth failures are critical
            ;;
        $ERROR_TYPE_RATE_LIMIT)
            echo $ERROR_SEVERITY_MEDIUM     # Rate limits are usually temporary
            ;;
        $ERROR_TYPE_NETWORK)
            if [[ $exit_code -eq 28 ]]; then  # Timeout
                echo $ERROR_SEVERITY_MEDIUM
            else
                echo $ERROR_SEVERITY_HIGH   # Other network issues
            fi
            ;;
        $ERROR_TYPE_TIMEOUT)
            echo $ERROR_SEVERITY_MEDIUM     # Timeouts are often recoverable
            ;;
        $ERROR_TYPE_API)
            if [[ $exit_code -eq 22 ]]; then  # HTTP error
                echo $ERROR_SEVERITY_HIGH
            else
                echo $ERROR_SEVERITY_MEDIUM
            fi
            ;;
        *)
            echo $ERROR_SEVERITY_MEDIUM     # Unknown errors - medium severity
            ;;
    esac
}

# Get severity name for display
get_severity_name() {
    local severity="$1"

    case $severity in
        $ERROR_SEVERITY_CRITICAL) echo "Critical" ;;
        $ERROR_SEVERITY_HIGH)     echo "High" ;;
        $ERROR_SEVERITY_MEDIUM)   echo "Medium" ;;
        $ERROR_SEVERITY_LOW)      echo "Low" ;;
        *)                        echo "Unknown" ;;
    esac
}

# Determine recovery action based on error type and severity
get_recovery_action() {
    local error_type="$1"
    local severity="$2"

    case $error_type in
        $ERROR_TYPE_AUTH)
            echo $RECOVERY_ACTION_MANUAL    # Auth requires manual intervention
            ;;
        $ERROR_TYPE_RATE_LIMIT)
            echo $RECOVERY_ACTION_RETRY     # Rate limits should be retried with backoff
            ;;
        $ERROR_TYPE_NETWORK)
            echo $RECOVERY_ACTION_RETRY     # Network issues are usually retryable
            ;;
        $ERROR_TYPE_TIMEOUT)
            echo $RECOVERY_ACTION_RETRY     # Timeouts are retryable
            ;;
        $ERROR_TYPE_API)
            if [[ $severity -eq $ERROR_SEVERITY_CRITICAL ]]; then
                echo $RECOVERY_ACTION_ESCALATE
            else
                echo $RECOVERY_ACTION_RETRY
            fi
            ;;
        *)
            echo $RECOVERY_ACTION_RETRY     # Default to retry for unknown errors
            ;;
    esac
}

# Get recovery action name for display
get_recovery_action_name() {
    local action="$1"

    case $action in
        $RECOVERY_ACTION_RETRY)    echo "Automatic Retry" ;;
        $RECOVERY_ACTION_MANUAL)   echo "Manual Intervention Required" ;;
        $RECOVERY_ACTION_ESCALATE) echo "Escalate to Support" ;;
        $RECOVERY_ACTION_IGNORE)   echo "Safe to Ignore" ;;
        *)                         echo "Unknown" ;;
    esac
}

# Get typical causes for error type
get_error_causes() {
    local error_type="$1"

    case $error_type in
        $ERROR_TYPE_NETWORK)
            echo "DNS resolution failure, network connectivity issues, firewall blocking, proxy configuration"
            ;;
        $ERROR_TYPE_RATE_LIMIT)
            echo "API quota exceeded, too many concurrent requests, insufficient rate limit headroom"
            ;;
        $ERROR_TYPE_AUTH)
            echo "Invalid API key, expired token, insufficient permissions, authentication service unavailable"
            ;;
        $ERROR_TYPE_API)
            echo "Service maintenance, API endpoint changes, malformed requests, server overload"
            ;;
        $ERROR_TYPE_TIMEOUT)
            echo "Slow network connection, overloaded servers, large request payloads, insufficient timeout limits"
            ;;
        *)
            echo "Various factors depending on specific operation and environment"
            ;;
    esac
}

# Get recovery recommendations
get_recovery_recommendations() {
    local error_type="$1"
    local severity="$2"
    local exit_code="$3"

    case $error_type in
        $ERROR_TYPE_NETWORK)
            cat << 'EOF'
1. **Check Network Connectivity:** Verify internet connection and DNS resolution
2. **Validate Proxy Settings:** Ensure proxy configuration is correct if applicable
3. **Check Firewall Rules:** Verify that outbound connections are allowed
4. **Test Alternative Endpoints:** Try connecting to different API endpoints
5. **Monitor Network Status:** Check for known network infrastructure issues
EOF
            ;;
        $ERROR_TYPE_RATE_LIMIT)
            cat << 'EOF'
1. **Wait for Reset:** Allow rate limit window to reset before retrying
2. **Implement Exponential Backoff:** Use increasing delays between retries
3. **Reduce Request Volume:** Lower the frequency of API calls
4. **Check Rate Limit Headers:** Review X-RateLimit-* headers for guidance
5. **Consider Request Batching:** Combine multiple operations into single requests where possible
EOF
            ;;
        $ERROR_TYPE_AUTH)
            cat << 'EOF'
1. **Verify API Key:** Check that ANTHROPIC_API_KEY is set and valid
2. **Check Token Expiration:** Ensure authentication tokens haven't expired
3. **Validate Permissions:** Confirm account has necessary API access permissions
4. **Review Account Status:** Check for account suspension or billing issues
5. **Regenerate Credentials:** Create new API keys if current ones are compromised
EOF
            ;;
        $ERROR_TYPE_API)
            cat << 'EOF'
1. **Check API Status:** Review service status pages for known issues
2. **Validate Request Format:** Ensure API requests conform to current specification
3. **Review API Documentation:** Check for recent changes or deprecations
4. **Test with Minimal Request:** Try a simple API call to isolate the issue
5. **Contact API Support:** Reach out to provider support if issues persist
EOF
            ;;
        $ERROR_TYPE_TIMEOUT)
            cat << 'EOF'
1. **Increase Timeout Values:** Allow more time for operations to complete
2. **Optimize Request Size:** Reduce payload size to improve response times
3. **Check Server Load:** Verify API servers aren't experiencing high load
4. **Split Large Operations:** Break down complex operations into smaller chunks
5. **Implement Progressive Timeouts:** Use different timeout values for different operation types
EOF
            ;;
        *)
            cat << 'EOF'
1. **Review Error Details:** Examine the specific error message for clues
2. **Check Recent Changes:** Identify any recent configuration or code changes
3. **Enable Debug Logging:** Increase logging verbosity to gather more information
4. **Test in Isolation:** Try to reproduce the error in a controlled environment
5. **Consult Documentation:** Review relevant documentation for troubleshooting guidance
EOF
            ;;
    esac
}

# Get related documentation links
get_related_documentation() {
    local error_type="$1"

    cat << 'EOF'
- [AI Workflow Troubleshooting Guide](dev-docs/troubleshooting.md)
- [Circuit Breaker Configuration](dev-docs/circuit-breaker.md)
- [Cost Monitoring and Controls](dev-docs/cost-monitoring.md)
- [Security and Authentication](dev-docs/security.md)
- [GitHub Actions Debugging](dev-docs/github-actions-debugging.md)
EOF
}

# Handle specific Claude CLI errors
handle_claude_error() {
    local exit_code="$1"
    local error_output="$2"
    local operation_context="$3"

    local error_type=$(classify_error "$exit_code" "$error_output")
    local severity=$(get_error_severity "$error_type" "$exit_code")

    echo "🔍 Analyzing Claude CLI error (exit code: $exit_code)"
    echo "   Error type: $(get_error_type_name "$error_type")"
    echo "   Severity: $(get_severity_name "$severity")"

    # Provide immediate guidance based on error type
    case $error_type in
        $ERROR_TYPE_AUTH)
            echo ""
            echo "🔐 AUTHENTICATION ERROR DETECTED"
            echo "   This typically indicates an issue with your ANTHROPIC_API_KEY"
            echo "   ❌ CRITICAL: This error is not retryable and requires manual intervention"
            echo ""
            echo "   Immediate actions:"
            echo "   1. Verify ANTHROPIC_API_KEY is set correctly"
            echo "   2. Check for API key expiration or account issues"
            echo "   3. Test API key with a simple curl command"
            echo ""
            ;;
        $ERROR_TYPE_RATE_LIMIT)
            echo ""
            echo "🚦 RATE LIMIT ERROR DETECTED"
            echo "   Claude API is temporarily limiting requests"
            echo "   ✅ RETRYABLE: Automatic retry with exponential backoff will be attempted"
            echo ""
            # Try to extract rate limit reset time
            local reset_time=$(get_rate_limit_reset_time "$error_output")
            if [[ -n "$reset_time" ]]; then
                echo "   Rate limit resets at: $(date -d "@$reset_time" 2>/dev/null || date -r "$reset_time" 2>/dev/null || echo "unknown")"
            fi
            echo ""
            ;;
        $ERROR_TYPE_NETWORK)
            echo ""
            echo "🌐 NETWORK ERROR DETECTED"
            echo "   Connection to Claude API failed"
            echo "   ✅ RETRYABLE: Automatic retry will be attempted"
            echo ""
            echo "   Common causes:"
            echo "   - Temporary network connectivity issues"
            echo "   - DNS resolution problems"
            echo "   - Firewall or proxy blocking requests"
            echo ""
            ;;
        $ERROR_TYPE_TIMEOUT)
            echo ""
            echo "⏰ TIMEOUT ERROR DETECTED"
            echo "   Operation exceeded time limit"
            echo "   ✅ RETRYABLE: Will retry with potentially longer timeout"
            echo ""
            echo "   Consider:"
            echo "   - Reducing prompt complexity"
            echo "   - Breaking large tasks into smaller chunks"
            echo "   - Increasing timeout values if appropriate"
            echo ""
            ;;
        *)
            echo ""
            echo "❓ UNKNOWN ERROR DETECTED"
            echo "   Error type could not be classified automatically"
            echo "   ⚠️  RETRYABLE: Will attempt retry with caution"
            echo ""
            echo "   Please review error details manually:"
            echo "   $(echo "$error_output" | head -3 | sed 's/^/   /')"
            echo ""
            ;;
    esac
}

# Validate prerequisites for AI operations
validate_prerequisites() {
    local validation_errors=()

    echo "🔍 Validating prerequisites for AI operations..."

    # Check required environment variables
    if [[ -z "${OPENROUTER_API_KEY:-}" ]]; then
        validation_errors+=("OPENROUTER_API_KEY environment variable is not set")
        echo "   ❌ OPENROUTER_API_KEY: Not set"
    else
        # Basic format validation (should start with sk-)
        if [[ ! "$OPENROUTER_API_KEY" =~ ^sk- ]]; then
            validation_errors+=("OPENROUTER_API_KEY appears to be in incorrect format")
            echo "   ⚠️  OPENROUTER_API_KEY: Set but format appears incorrect"
        else
            echo "   ✅ OPENROUTER_API_KEY: Set (${#OPENROUTER_API_KEY} characters)"
        fi
    fi

    # Check network connectivity
    echo "   🌐 Testing network connectivity..."
    if command -v curl >/dev/null 2>&1; then
        if curl -s --max-time 10 https://api.anthropic.com/health >/dev/null 2>&1; then
            echo "   ✅ Network connectivity: OK"
        else
            validation_errors+=("Cannot reach api.anthropic.com - network connectivity issue")
            echo "   ❌ Network connectivity: Failed to reach api.anthropic.com"
        fi
    else
        echo "   ⚠️  Network connectivity: Cannot test (curl not available)"
    fi

    # Check Claude CLI availability
    echo "   🔧 Checking Claude CLI availability..."
    if command -v claude-code >/dev/null 2>&1 ||
       command -v claude >/dev/null 2>&1 ||
       command -v npx >/dev/null 2>&1; then
        echo "   ✅ Claude CLI: Available"
    else
        validation_errors+=("No Claude CLI found (claude-code, claude, or npx)")
        echo "   ❌ Claude CLI: Not found"
    fi

    # Check GitHub CLI if needed
    if [[ -n "${GITHUB_TOKEN:-}" ]] && command -v gh >/dev/null 2>&1; then
        if gh auth status >/dev/null 2>&1; then
            echo "   ✅ GitHub CLI: Authenticated"
        else
            validation_errors+=("GitHub CLI is available but not authenticated")
            echo "   ❌ GitHub CLI: Not authenticated"
        fi
    fi

    # Check disk space
    local available_space_mb=$(df . | awk 'NR==2 {print int($4/1024)}')
    if [[ $available_space_mb -lt 100 ]]; then
        validation_errors+=("Low disk space: ${available_space_mb}MB available (minimum 100MB recommended)")
        echo "   ⚠️  Disk space: Low (${available_space_mb}MB available)"
    else
        echo "   ✅ Disk space: Sufficient (${available_space_mb}MB available)"
    fi

    # Report results
    if [[ ${#validation_errors[@]} -eq 0 ]]; then
        echo "   ✅ All prerequisites validated successfully"
        return 0
    else
        echo ""
        echo "   ❌ Prerequisite validation failed:"
        for error in "${validation_errors[@]}"; do
            echo "      - $error"
        done
        echo ""
        echo "   Please resolve these issues before proceeding."
        return 1
    fi
}

# Execute command with timeout and comprehensive error handling
execute_with_timeout_and_retry() {
    local command="$1"
    local timeout_seconds="${2:-600}"  # Default 10 minutes
    local max_retries="${3:-3}"

    echo "⏱️  Executing with timeout (${timeout_seconds}s) and retry (max: $max_retries):"
    echo "   Command: $command"

    # Use retry mechanism with timeout
    retry_with_backoff \
        "timeout $timeout_seconds bash -c \"$command\"" \
        "$max_retries" \
        2 \
        60 \
        2 \
        true
}

# Secure cleanup function
secure_cleanup() {
    local files=("$@")

    for file in "${files[@]}"; do
        if [[ -f "$file" ]]; then
            # Securely overwrite file before deletion
            if command -v shred >/dev/null 2>&1; then
                shred -vfz -n 3 "$file" 2>/dev/null || rm -f "$file"
            else
                # Fallback for systems without shred
                dd if=/dev/zero of="$file" bs=1024 count=$(du -k "$file" | cut -f1) 2>/dev/null || true
                rm -f "$file"
            fi
            echo "🗑️  Securely removed: $file"
        fi
    done
}

# Export functions for use in other scripts
export -f generate_error_report
export -f handle_claude_error
export -f validate_prerequisites
export -f execute_with_timeout_and_retry
export -f secure_cleanup
