#!/bin/bash
#
# CURATOR BOT - Automated Knowledge Management System
# For RateRight Growth Engine
#
# Purpose: Keeps the codebase clean, organized, and well-documented
# Features:
#   - Archive old files (30-day rule)
#   - Organize knowledge/documentation
#   - Delete clutter and temp files
#   - Backup critical data
#
# Usage: ./curator-bot-main.sh [command] [options]
#   Commands:
#     run        - Run full curation cycle
#     archive    - Archive old files only
#     organize   - Organize knowledge files only
#     clean      - Clean clutter only
#     backup     - Run backup only
#     status     - Show current curation status
#     help       - Show this help message
#

set -e

# =============================================================================
# CONFIGURATION
# =============================================================================

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CONFIG_FILE="$SCRIPT_DIR/curator-bot.conf"
LOG_DIR="$SCRIPT_DIR/curator-bot-logs"
ARCHIVE_DIR="$PROJECT_ROOT/.archive"
BACKUP_DIR="$PROJECT_ROOT/.backups"

# Default settings (can be overridden by curator-bot.conf)
ARCHIVE_DAYS=30
DRY_RUN=false
VERBOSE=false
MAX_LOG_FILES=30
BACKUP_RETENTION_DAYS=7

# Load configuration if exists
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
fi

# =============================================================================
# LOGGING
# =============================================================================

mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/curator-$(date +%Y%m%d-%H%M%S).log"

log() {
    local level="$1"
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}

log_info() { log "INFO" "$@"; }
log_warn() { log "WARN" "$@"; }
log_error() { log "ERROR" "$@"; }
log_debug() { [ "$VERBOSE" = true ] && log "DEBUG" "$@" || true; }

# =============================================================================
# ARCHIVE SYSTEM (30-day rule)
# =============================================================================

archive_old_files() {
    log_info "Starting archive process (files older than $ARCHIVE_DAYS days)"

    mkdir -p "$ARCHIVE_DIR"

    local archived_count=0
    local archive_date=$(date +%Y%m%d)

    # Files to consider for archiving
    local patterns=(
        "*.log"
        "*.tmp"
        "*.bak"
        "*-old.*"
        "*-backup.*"
    )

    # Directories to scan
    local scan_dirs=(
        "$PROJECT_ROOT/docs"
        "$PROJECT_ROOT/scripts"
        "$PROJECT_ROOT/.claude"
    )

    for dir in "${scan_dirs[@]}"; do
        if [ -d "$dir" ]; then
            log_debug "Scanning $dir for old files"

            for pattern in "${patterns[@]}"; do
                while IFS= read -r -d '' file; do
                    local filename=$(basename "$file")
                    local archive_path="$ARCHIVE_DIR/$archive_date"

                    if [ "$DRY_RUN" = true ]; then
                        log_info "[DRY RUN] Would archive: $file"
                    else
                        mkdir -p "$archive_path"
                        mv "$file" "$archive_path/"
                        log_info "Archived: $file -> $archive_path/$filename"
                        ((archived_count++))
                    fi
                done < <(find "$dir" -maxdepth 3 -name "$pattern" -type f -mtime +$ARCHIVE_DAYS -print0 2>/dev/null)
            done
        fi
    done

    # Archive old OUTBOX entries (keep only last 50 results)
    archive_outbox_history

    log_info "Archive complete. $archived_count files archived."
    return 0
}

archive_outbox_history() {
    local outbox="$PROJECT_ROOT/.claude/OUTBOX.md"

    if [ ! -f "$outbox" ]; then
        log_debug "No OUTBOX.md found"
        return 0
    fi

    local result_count=$(grep -c "^## RESULT" "$outbox" 2>/dev/null || echo "0")

    if [ "$result_count" -gt 50 ]; then
        log_info "OUTBOX.md has $result_count results, trimming to keep last 50"

        if [ "$DRY_RUN" = true ]; then
            log_info "[DRY RUN] Would trim OUTBOX.md"
        else
            # Create backup
            cp "$outbox" "$ARCHIVE_DIR/OUTBOX-$(date +%Y%m%d).md.bak"

            # Keep header and last 50 results
            local header_end=$(grep -n "^## RESULT\|^## REVIEW REQUEST" "$outbox" | head -1 | cut -d: -f1)
            if [ -n "$header_end" ]; then
                head -n $((header_end - 1)) "$outbox" > "$outbox.tmp"
                grep -A 1000 "^## RESULT\|^## REVIEW REQUEST" "$outbox" | tail -n 1000 >> "$outbox.tmp"
                mv "$outbox.tmp" "$outbox"
                log_info "OUTBOX.md trimmed successfully"
            fi
        fi
    fi
}

# =============================================================================
# KNOWLEDGE ORGANIZATION
# =============================================================================

organize_knowledge() {
    log_info "Starting knowledge organization"

    local docs_dir="$PROJECT_ROOT/docs"
    mkdir -p "$docs_dir"

    # Ensure proper structure
    local subdirs=(
        "plans"
        "api"
        "guides"
        "archive"
    )

    for subdir in "${subdirs[@]}"; do
        if [ ! -d "$docs_dir/$subdir" ]; then
            if [ "$DRY_RUN" = true ]; then
                log_info "[DRY RUN] Would create: $docs_dir/$subdir"
            else
                mkdir -p "$docs_dir/$subdir"
                log_info "Created: $docs_dir/$subdir"
            fi
        fi
    done

    # Move plan files to plans/
    while IFS= read -r -d '' file; do
        local filename=$(basename "$file")
        if [[ "$filename" == *"-plan.md" ]] && [[ "$file" != *"/plans/"* ]]; then
            if [ "$DRY_RUN" = true ]; then
                log_info "[DRY RUN] Would move: $file -> $docs_dir/plans/"
            else
                mv "$file" "$docs_dir/plans/"
                log_info "Organized: $file -> $docs_dir/plans/"
            fi
        fi
    done < <(find "$docs_dir" -maxdepth 1 -name "*-plan.md" -type f -print0 2>/dev/null)

    # Move archived/old docs
    while IFS= read -r -d '' file; do
        local filename=$(basename "$file")
        if [[ "$filename" == *"-old.md" ]] || [[ "$filename" == *"-archived.md" ]]; then
            if [[ "$file" != *"/archive/"* ]]; then
                if [ "$DRY_RUN" = true ]; then
                    log_info "[DRY RUN] Would move: $file -> $docs_dir/archive/"
                else
                    mv "$file" "$docs_dir/archive/"
                    log_info "Organized: $file -> $docs_dir/archive/"
                fi
            fi
        fi
    done < <(find "$docs_dir" -maxdepth 1 -name "*.md" -type f -print0 2>/dev/null)

    log_info "Knowledge organization complete"
}

# =============================================================================
# CLUTTER DELETION
# =============================================================================

clean_clutter() {
    log_info "Starting clutter cleanup"

    local deleted_count=0

    # Patterns to delete
    local delete_patterns=(
        "*.pyc"
        "__pycache__"
        "*.swp"
        "*.swo"
        "*~"
        ".DS_Store"
        "Thumbs.db"
        "*.orig"
        "npm-debug.log*"
        "yarn-error.log"
    )

    # Safe directories to clean (never touch node_modules, .git, etc.)
    local safe_dirs=(
        "$PROJECT_ROOT/src"
        "$PROJECT_ROOT/admin/src"
        "$PROJECT_ROOT/docs"
        "$PROJECT_ROOT/scripts"
        "$PROJECT_ROOT/supabase"
    )

    for dir in "${safe_dirs[@]}"; do
        if [ -d "$dir" ]; then
            for pattern in "${delete_patterns[@]}"; do
                while IFS= read -r -d '' file; do
                    if [ "$DRY_RUN" = true ]; then
                        log_info "[DRY RUN] Would delete: $file"
                    else
                        rm -rf "$file"
                        log_info "Deleted: $file"
                        ((deleted_count++))
                    fi
                done < <(find "$dir" -name "$pattern" -print0 2>/dev/null)
            done
        fi
    done

    # Clean old log files (keep last 30)
    clean_old_logs

    log_info "Clutter cleanup complete. $deleted_count items deleted."
}

clean_old_logs() {
    if [ -d "$LOG_DIR" ]; then
        local log_count=$(ls -1 "$LOG_DIR"/*.log 2>/dev/null | wc -l || echo "0")

        if [ "$log_count" -gt "$MAX_LOG_FILES" ]; then
            local to_delete=$((log_count - MAX_LOG_FILES))
            log_info "Found $log_count log files, removing oldest $to_delete"

            if [ "$DRY_RUN" = true ]; then
                log_info "[DRY RUN] Would delete $to_delete old log files"
            else
                ls -1t "$LOG_DIR"/*.log | tail -n "$to_delete" | xargs rm -f
                log_info "Deleted $to_delete old log files"
            fi
        fi
    fi
}

# =============================================================================
# BACKUP SYSTEM
# =============================================================================

run_backup() {
    log_info "Starting backup"

    mkdir -p "$BACKUP_DIR"

    local backup_date=$(date +%Y%m%d-%H%M%S)
    local backup_name="rateright-backup-$backup_date.tar.gz"

    # Files/directories to backup
    local backup_items=(
        ".claude"
        "docs"
        "CLAUDE.md"
        "DEV.md"
        "COO.md"
        "package.json"
        "admin/package.json"
        "supabase/PENDING_MIGRATIONS.md"
    )

    local backup_args=""
    for item in "${backup_items[@]}"; do
        if [ -e "$PROJECT_ROOT/$item" ]; then
            backup_args="$backup_args $item"
        fi
    done

    if [ -z "$backup_args" ]; then
        log_warn "No files to backup"
        return 0
    fi

    if [ "$DRY_RUN" = true ]; then
        log_info "[DRY RUN] Would create backup: $BACKUP_DIR/$backup_name"
        log_info "[DRY RUN] Items: $backup_args"
    else
        cd "$PROJECT_ROOT"
        tar -czf "$BACKUP_DIR/$backup_name" $backup_args 2>/dev/null
        log_info "Backup created: $BACKUP_DIR/$backup_name"

        # Show backup size
        local size=$(du -h "$BACKUP_DIR/$backup_name" | cut -f1)
        log_info "Backup size: $size"
    fi

    # Clean old backups
    clean_old_backups

    log_info "Backup complete"
}

clean_old_backups() {
    if [ -d "$BACKUP_DIR" ]; then
        log_debug "Cleaning backups older than $BACKUP_RETENTION_DAYS days"

        while IFS= read -r -d '' file; do
            if [ "$DRY_RUN" = true ]; then
                log_info "[DRY RUN] Would delete old backup: $file"
            else
                rm -f "$file"
                log_info "Deleted old backup: $file"
            fi
        done < <(find "$BACKUP_DIR" -name "*.tar.gz" -type f -mtime +$BACKUP_RETENTION_DAYS -print0 2>/dev/null)
    fi
}

# =============================================================================
# STATUS REPORT
# =============================================================================

show_status() {
    echo ""
    echo "========================================"
    echo "  CURATOR BOT STATUS REPORT"
    echo "========================================"
    echo ""

    # Project info
    echo "Project: $PROJECT_ROOT"
    echo "Date: $(date)"
    echo ""

    # Archive status
    echo "-- ARCHIVE --"
    if [ -d "$ARCHIVE_DIR" ]; then
        local archive_size=$(du -sh "$ARCHIVE_DIR" 2>/dev/null | cut -f1)
        local archive_count=$(find "$ARCHIVE_DIR" -type f 2>/dev/null | wc -l)
        echo "  Location: $ARCHIVE_DIR"
        echo "  Size: $archive_size"
        echo "  Files: $archive_count"
    else
        echo "  No archive directory exists yet"
    fi
    echo ""

    # Backup status
    echo "-- BACKUPS --"
    if [ -d "$BACKUP_DIR" ]; then
        local backup_count=$(ls -1 "$BACKUP_DIR"/*.tar.gz 2>/dev/null | wc -l || echo "0")
        local latest_backup=$(ls -1t "$BACKUP_DIR"/*.tar.gz 2>/dev/null | head -1)
        echo "  Location: $BACKUP_DIR"
        echo "  Count: $backup_count"
        if [ -n "$latest_backup" ]; then
            echo "  Latest: $(basename "$latest_backup")"
        fi
    else
        echo "  No backups exist yet"
    fi
    echo ""

    # Clutter check
    echo "-- CLUTTER CHECK --"
    local clutter_count=0
    for pattern in "*.pyc" "*.swp" "*.swo" "*~" ".DS_Store"; do
        local found=$(find "$PROJECT_ROOT" -name "$pattern" -type f 2>/dev/null | wc -l)
        clutter_count=$((clutter_count + found))
    done
    echo "  Clutter files found: $clutter_count"
    echo ""

    # OUTBOX status
    echo "-- OUTBOX STATUS --"
    local outbox="$PROJECT_ROOT/.claude/OUTBOX.md"
    if [ -f "$outbox" ]; then
        local result_count=$(grep -c "^## RESULT" "$outbox" 2>/dev/null || echo "0")
        echo "  Results in OUTBOX: $result_count"
        if [ "$result_count" -gt 50 ]; then
            echo "  WARNING: OUTBOX has many results, consider running 'curator.sh archive'"
        fi
    fi
    echo ""

    # Logs
    echo "-- LOGS --"
    if [ -d "$LOG_DIR" ]; then
        local log_count=$(ls -1 "$LOG_DIR"/*.log 2>/dev/null | wc -l || echo "0")
        echo "  Log files: $log_count"
    fi
    echo ""

    echo "========================================"
}

# =============================================================================
# FULL CURATION CYCLE
# =============================================================================

run_full_cycle() {
    log_info "=========================================="
    log_info "  CURATOR BOT - Full Curation Cycle"
    log_info "=========================================="

    local start_time=$(date +%s)

    archive_old_files
    organize_knowledge
    clean_clutter
    run_backup

    local end_time=$(date +%s)
    local duration=$((end_time - start_time))

    log_info "=========================================="
    log_info "  Curation cycle complete in ${duration}s"
    log_info "=========================================="
}

# =============================================================================
# HELP
# =============================================================================

show_help() {
    cat << 'EOF'
CURATOR BOT - Automated Knowledge Management System

Usage: ./curator-bot-main.sh [command] [options]

Commands:
    run        Run full curation cycle (archive + organize + clean + backup)
    archive    Archive old files only (30-day rule)
    organize   Organize knowledge/documentation files
    clean      Clean clutter and temp files
    backup     Create backup of critical files
    status     Show current curation status
    help       Show this help message

Options:
    --dry-run   Show what would be done without making changes
    --verbose   Show detailed output
    --days N    Override archive age threshold (default: 30)

Examples:
    ./curator-bot-main.sh run                    # Full curation cycle
    ./curator-bot-main.sh archive --dry-run      # Preview archiving
    ./curator-bot-main.sh clean --verbose        # Clean with detailed output
    ./curator-bot-main.sh status                 # Check current status

Configuration:
    Edit curator-bot.conf to customize behavior:
    - ARCHIVE_DAYS: Days before archiving (default: 30)
    - BACKUP_RETENTION_DAYS: Days to keep backups (default: 7)
    - MAX_LOG_FILES: Maximum log files to keep (default: 30)

EOF
}

# =============================================================================
# MAIN
# =============================================================================

main() {
    local command="${1:-help}"
    shift || true

    # Parse options
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --dry-run)
                DRY_RUN=true
                shift
                ;;
            --verbose)
                VERBOSE=true
                shift
                ;;
            --days)
                ARCHIVE_DAYS="$2"
                shift 2
                ;;
            *)
                shift
                ;;
        esac
    done

    case "$command" in
        run)
            run_full_cycle
            ;;
        archive)
            archive_old_files
            ;;
        organize)
            organize_knowledge
            ;;
        clean)
            clean_clutter
            ;;
        backup)
            run_backup
            ;;
        status)
            show_status
            ;;
        help|--help|-h)
            show_help
            ;;
        *)
            log_error "Unknown command: $command"
            show_help
            exit 1
            ;;
    esac
}

main "$@"
