#!/bin/bash

# AI Commit Message Generator using OpenAI API
# Usage: ./scripts/ai-commit.sh [--dry-run|--generate-only|--help]

set -e

# Print help and exit if --help is passed
if [[ "$1" == "--help" ]]; then
    echo "AI Commit Message Generator using OpenAI API"
    echo "Usage: ai-commit [--dry-run|--generate-only|--help]"
    echo "  --dry-run         Show the generated commit message but do not commit"
    echo "  --generate-only   Output only the commit message (for hooks)"
    echo "  --help            Show this help message and exit"
    exit 0
fi

# Check if inside a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
    echo "❌ Error: Not inside a git repository. Please run 'git init' first."
    exit 1
fi

# Support for --generate-only flag (for use in hooks)
GENERATE_ONLY=false
if [ "$1" = "--generate-only" ]; then
    GENERATE_ONLY=true
    shift
fi

# Load AI prompts configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$(dirname "$SCRIPT_DIR")/config"
if [ -f "$CONFIG_DIR/ai-prompts.conf" ]; then
    source "$CONFIG_DIR/ai-prompts.conf"
else
    echo "❌ Error: AI prompts configuration not found at $CONFIG_DIR/ai-prompts.conf"
    exit 1
fi

# Load exclusion patterns from config
EXCLUDE_PATTERNS=( $AI_COMMIT_EXCLUDE )

# Configuration (using values from ai-prompts.conf)
OPENAI_API_URL="$OPENAI_API_URL"
MODEL="$OPENAI_MODEL"
MAX_TOKENS="$OPENAI_MAX_TOKENS"

# Check if API key is provided
if [ -z "$OPENAI_API_KEY" ]; then
    echo "❌ Error: OPENAI_API_KEY environment variable not set"
    echo "💡 Set it with: export OPENAI_API_KEY='your-api-key-here'"
    exit 1
fi

# Check for staged changes
if git diff --cached --quiet; then
    if [ "$GENERATE_ONLY" = false ]; then
        echo "❌ No staged changes found. Use 'git add' first."
    fi
    exit 1
fi

if [ "$GENERATE_ONLY" = false ]; then
    echo "🔍 Analyzing staged changes..."
fi

# Helper to build grep -v pattern for exclusions
build_exclude_grep() {
  local args=""
  for pat in "${EXCLUDE_PATTERNS[@]}"; do
    args+="| grep -v '^${pat//\//\/}' "
  done
  echo "$args"
}

# Get filtered file list
ALL_FILES=$(git diff --cached --name-only)
FILTERED_FILES="$ALL_FILES"

# Apply exclusion patterns if any exist
if [ ${#EXCLUDE_PATTERNS[@]} -gt 0 ]; then
    for pat in "${EXCLUDE_PATTERNS[@]}"; do
        if [ -n "$pat" ]; then
            FILTERED_FILES=$(echo "$FILTERED_FILES" | grep -v "^$pat" || true)
        fi
    done
fi

FILES=$(echo "$FILTERED_FILES" | tr '\n' ', ' | sed 's/,$//')

# Create a comprehensive change summary
FILE_COUNT=$(echo "$FILTERED_FILES" | wc -l)
NEW_FILES=$(git diff --cached --name-status | grep "^A" | wc -l)
MODIFIED_FILES=$(git diff --cached --name-status | grep "^M" | wc -l)
DELETED_FILES=$(git diff --cached --name-status | grep "^D" | wc -l)

# Enhanced Change Analysis System
# Provides intelligent context instead of raw diff truncation

# 1. Basic statistics
DIFF_STATS=$(git diff --cached --stat -- $FILTERED_FILES)

# 2. Categorize files by type and importance
categorize_files() {
    echo "🚀 MAJOR NEW FEATURES/FILES:"
    git diff --cached --numstat -- $FILTERED_FILES | while read additions deletions file; do
        [ "$additions" = "-" ] && additions=0
        if [ "$additions" -gt 100 ]; then
            echo "  - $file (+$additions lines)"
        fi
    done | head -5
    
    echo ""
    echo "📚 DOCUMENTATION & CONFIG:"
    echo "$FILTERED_FILES" | grep -E '\.(md|conf|json)$|README|docs/' | head -3 | while read file; do
        local additions=$(git diff --cached --numstat -- "$file" | cut -f1)
        echo "  - $file (+$additions lines)"
    done
    
    echo ""
    echo "� OTHER SIGNIFICANT CHANGES:"
    git diff --cached --numstat -- $FILTERED_FILES | while read additions deletions file; do
        [ "$additions" = "-" ] && additions=0
        if [ "$additions" -gt 20 ] && [ "$additions" -le 100 ]; then
            echo "  - $file (+$additions lines)"
        fi
    done | head -5
}

FILE_ANALYSIS=$(categorize_files)

# 3. Get key diff samples from major files only
get_representative_diff() {
    echo "--- Sampling from major feature files ---"
    git diff --cached --numstat -- $FILTERED_FILES | while read additions deletions file; do
        [ "$additions" = "-" ] && additions=0
        if [ "$additions" -gt 50 ]; then
            echo ""
            echo "=== Key changes in $file ==="
            git diff --cached --no-color -- "$file" | head -20
            break  # Just show one major file to avoid overwhelming
        fi
    done
}

DIFF_SAMPLE=$(get_representative_diff)

# Enhanced scope detection based on file paths
get_file_scope() {
    local file="$1"
    case "$file" in
        # Mail features - hierarchical detection
        *mail*allow*block* | *allowblock* | *blocklist* | */mail/allow-block* | */allow-block-list*)
            echo "mail.allow-block-lists" ;;
        *mail*quarantine* | */mail/quarantine*)
            echo "mail.quarantine" ;;
        *mail*scan* | *mail*filter* | */mail/scanning* | */mail/filter*)
            echo "mail.scanning" ;;
        */mail/* | *mail*) echo "mail" ;;
        
        # DNS features - hierarchical detection  
        *dns*polic* | */dns/policies* | */dns-policies*)
            echo "dns.policies" ;;
        *dns*rule* | *dns*custom* | */dns/custom-rules* | */dns/rules*)
            echo "dns.custom-rules" ;;
        */dns/* | *dns*) echo "dns" ;;
        
        # Reports features - hierarchical detection
        *report*traffic* | *email*traffic* | */reports/email-traffic* | */reports/traffic*)
            echo "reports.email-traffic" ;;
        *report*threat* | *threat*detect* | */reports/threat* | */threat-detection*)
            echo "reports.threat-detection" ;;
        */reports/* | *report*) echo "reports" ;;
        
        # Settings features - hierarchical detection
        *setting*notification* | */settings/notifications* | */notification-settings*)
            echo "settings.notifications" ;;
        *setting*integration* | */settings/integrations* | */integration-settings*)
            echo "settings.integrations" ;;
        */settings/* | *setting*) echo "settings" ;;
        
        # Auth features - hierarchical detection
        *auth*mfa* | *auth*multi* | */auth/mfa* | */multi-factor*)
            echo "auth.mfa" ;;
        *auth*sso* | *auth*single* | */auth/sso* | */single-sign*)
            echo "auth.sso" ;;
        */auth/* | *auth* | *login* | *user-management*) echo "auth" ;;
        
        # Other feature areas
        */billing/* | *billing* | *payment* | *subscription*) echo "billing" ;;
        */onboarding/* | *onboarding* | *welcome* | *setup-wizard*) echo "onboarding" ;;
        */dashboard/* | *dashboard* | *overview* | *main-page*) echo "dashboard" ;;
        */admin/* | *admin* | *administration*) echo "admin" ;;
        
        # Technical areas
        */api/* | *api* | *endpoint* | *service* | */services/* | */controllers/*) echo "api" ;;
        */components/* | */ui/* | *component* | *interface* | */styles/* | *.css | *.scss | *.vue) echo "ui" ;;
        */database/* | */db/* | *migration* | *schema* | *.sql) echo "db" ;;
        */test/* | */tests/* | *test* | *spec* | *.test.* | *.spec.*) echo "tests" ;;
        */doc/* | */docs/* | *readme* | *documentation* | *.md) echo "docs" ;;
        */infrastructure/* | */infra/* | */deploy/* | *docker* | *kubernetes* | *.yml | *.yaml) echo "infra" ;;
        
        # Cross-cutting concerns
        *a11y* | *accessibility* | */accessibility/* | *aria* | *wcag*) echo "a11y" ;;
        *i18n* | *internationalization* | */locales/* | */translations/* | *locale*) echo "i18n" ;;
        *mobile* | */mobile/* | *responsive* | *touch*) echo "mobile" ;;
        *seo* | */seo/* | *meta* | *sitemap*) echo "seo" ;;
        *analytics* | */analytics/* | *tracking* | *metrics*) echo "analytics" ;;
        *monitoring* | */monitoring/* | *health* | *status*) echo "monitoring" ;;
        *security* | */security/* | *encryption* | *permission*) echo "security" ;;
        *performance* | *perf* | */performance/* | *optimization*) echo "perf" ;;
        *) echo "" ;;
    esac
}

# Detect suggested scope from changed files
DETECTED_SCOPES=()
PRIMARY_SCOPE=""
SCOPE_CONFIDENCE="low"

while IFS= read -r file; do
    [ -z "$file" ] && continue
    scope=$(get_file_scope "$file")
    if [ -n "$scope" ]; then
        DETECTED_SCOPES+=("$scope")
        # Prefer hierarchical scopes (with dots) as primary
        if [ -z "$PRIMARY_SCOPE" ] || [[ "$scope" == *.* ]]; then
            PRIMARY_SCOPE="$scope"
            if [[ "$scope" == *.* ]]; then
                SCOPE_CONFIDENCE="high"
            else
                SCOPE_CONFIDENCE="medium"
            fi
        fi
    fi
done <<< "$FILTERED_FILES"

# Add scope guidance to the prompt if detected
SCOPE_GUIDANCE=""
if [ -n "$PRIMARY_SCOPE" ]; then
    SCOPE_GUIDANCE="

IMPORTANT: Based on the file paths, the suggested scope is '$PRIMARY_SCOPE' (confidence: $SCOPE_CONFIDENCE).
Please use this scope unless the changes clearly belong to a different area."
fi

# Enhanced context for AI with intelligent analysis
DIFF=$(cat << EOF
COMMIT ANALYSIS SUMMARY
======================

📊 Overview: $FILE_COUNT files changed ($NEW_FILES new, $MODIFIED_FILES modified, $DELETED_FILES deleted)

🚀 MAJOR NEW FILES (100+ lines):
$(git diff --cached --numstat -- $FILTERED_FILES | awk '$1 >= 100 {print "  - " $3 " (+" $1 " lines added)"}' | head -5)

📚 DOCUMENTATION & CONFIG:
$(echo "$FILTERED_FILES" | grep -E '\.md$|\.conf$|README|docs/' | head -3 | while read file; do
    additions=$(git diff --cached --numstat -- "$file" | cut -f1 2>/dev/null || echo "0")
    echo "  - $file (+$additions lines)"
done)

📈 Change Statistics:
$DIFF_STATS

🔍 Sample from largest new file:
$(git diff --cached --numstat -- $FILTERED_FILES | sort -nr | head -1 | while read additions deletions file; do
    echo "=== $file (showing first 20 lines) ==="
    git diff --cached --no-color -- "$file" | head -20
done)

$([ -n "$PRIMARY_SCOPE" ] && echo "💡 Suggested Scope: $PRIMARY_SCOPE (confidence: $SCOPE_CONFIDENCE)")
EOF
)

# Use the centralized prompt from config
PROMPT=$(eval echo "\"$AI_COMMIT_PROMPT\"")

# Prepare JSON payload (safer escaping)
JSON_PAYLOAD=$(cat << EOF
{
    "model": "$MODEL",
    "messages": [
        {
            "role": "user", 
            "content": $(echo "$PROMPT" | jq -R -s .)
        }
    ],
    "max_tokens": $MAX_TOKENS,
    "temperature": $OPENAI_TEMPERATURE
}
EOF
)

if [ "$GENERATE_ONLY" = false ]; then
    echo "🤖 Generating commit message..."
fi

# Call OpenAI API
RESPONSE=$(curl -s -X POST "$OPENAI_API_URL" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -d "$JSON_PAYLOAD")

# Check for API errors
if echo "$RESPONSE" | jq -e '.error' >/dev/null 2>&1; then
    echo "❌ OpenAI API Error:"
    echo "$RESPONSE" | jq -r '.error.message'
    exit 1
fi

# Extract commit message
COMMIT_MSG=$(echo "$RESPONSE" | jq -r '.choices[0].message.content' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

if [ -z "$COMMIT_MSG" ] || [ "$COMMIT_MSG" = "null" ]; then
    echo "❌ Failed to generate commit message"
    exit 1
fi

# Validate length - check subject line only (first line)
SUBJECT_LINE=$(echo "$COMMIT_MSG" | head -n1)
SUBJECT_LENGTH=${#SUBJECT_LINE}
MSG_LENGTH=${#COMMIT_MSG}

# Generate-only mode (for hooks) - output just the message
if [ "$GENERATE_ONLY" = true ]; then
    echo "$COMMIT_MSG"
    exit 0
fi

# For interactive mode, show the message details
echo "📝 Generated message (${MSG_LENGTH} chars total, ${SUBJECT_LENGTH} chars subject): $COMMIT_MSG"

if [ $SUBJECT_LENGTH -gt $MAX_COMMIT_LENGTH ]; then
    echo "⚠️  Warning: Subject line exceeds $MAX_COMMIT_LENGTH characters"
elif [ $SUBJECT_LENGTH -gt $WARN_COMMIT_LENGTH ]; then
    echo "⚠️  Note: Subject line is approaching the $MAX_COMMIT_LENGTH character limit"
fi

# Dry run option
if [ "$1" = "--dry-run" ]; then
    echo "🏃 Dry run mode - not committing"
    exit 0
fi

# Confirm and commit
echo ""
read -p "🚀 Proceed with commit? (Y/n): " confirm

if [[ $confirm =~ ^[Nn]$ ]]; then
    echo "❌ Commit cancelled"
    echo "💡 You can copy the message: $COMMIT_MSG"
else
    git commit -m "$COMMIT_MSG"
    echo "✅ Committed successfully!"
fi
