#!/bin/bash
# Cairnquire - Progress Monitor
# Watches the project directory and updates docs/STATUS.md with progress
# Exits if no filesystem changes detected between iterations

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="/Users/tim/developer/cairnquire"
DOCS_DIR="$PROJECT_DIR/docs"
STATUS_FILE="$DOCS_DIR/STATUS.md"
HASH_FILE="$DOCS_DIR/.last_state_hash"
ITERATION=0
MAX_ITERATIONS=1000  # Safety limit
START_TIME=$(date +%s)

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

log() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" >&2
}

warn() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" >&2
}

error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" >&2
}

success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" >&2
}

# Compute hash of all tracked files (excluding node_modules, .git, etc.)
compute_state_hash() {
    find "$PROJECT_DIR" \
        -type f \
        -not -path '*/node_modules/*' \
        -not -path '*/.git/*' \
        -not -path '*/data/*' \
        -not -path '*/vendor/*' \
        -not -name '.last_state_hash' \
        -not -name 'STATUS.md' \
        -not -name '*.lock' \
        | sort \
        | xargs stat -f '%m %N' 2>/dev/null \
        | md5 -q
}

# Check if filesystem changed
has_changes() {
    local current_hash
    current_hash=$(compute_state_hash)
    
    if [[ -f "$HASH_FILE" ]]; then
        local last_hash
        last_hash=$(cat "$HASH_FILE")
        if [[ "$current_hash" == "$last_hash" ]]; then
            return 1  # No changes
        fi
    fi
    
    echo "$current_hash" > "$HASH_FILE"
    return 0  # Changes detected (or first run)
}

# Count lines of code by language
analyze_codebase() {
    log "Analyzing codebase..."
    
    local go_files=0
    local go_lines=0
    local ts_files=0
    local ts_lines=0
    local md_files=0
    local md_lines=0
    local total_files=0
    local docker_files=0
    
    # Count Go files
    if command -v find &> /dev/null; then
        go_files=$(find "$PROJECT_DIR" -name '*.go' -not -path '*/vendor/*' -not -path '*/node_modules/*' | wc -l)
        go_lines=$(find "$PROJECT_DIR" -name '*.go' -not -path '*/vendor/*' -not -path '*/node_modules/*' -exec cat {} + 2>/dev/null | wc -l)
        
        ts_files=$(find "$PROJECT_DIR" -name '*.ts' -o -name '*.tsx' | grep -v node_modules | wc -l)
        ts_lines=$(find "$PROJECT_DIR" -name '*.ts' -o -name '*.tsx' | grep -v node_modules | xargs cat 2>/dev/null | wc -l)
        
        md_files=$(find "$PROJECT_DIR" -name '*.md' | wc -l)
        md_lines=$(find "$PROJECT_DIR" -name '*.md' -exec cat {} + 2>/dev/null | wc -l)
        
        docker_files=$(find "$PROJECT_DIR" -name 'Dockerfile*' -o -name 'docker-compose*' | wc -l)
        
        total_files=$(find "$PROJECT_DIR" -type f -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/data/*' | wc -l)
    fi
    
    echo "$go_files|$go_lines|$ts_files|$ts_lines|$md_files|$md_lines|$total_files|$docker_files"
}

# Check git status if available
check_git_status() {
    if [[ -d "$PROJECT_DIR/.git" ]]; then
        cd "$PROJECT_DIR"
        local branch=$(git branch --show-current 2>/dev/null || echo "unknown")
        local uncommitted=$(git status --short 2>/dev/null | wc -l | tr -d ' ')
        local last_commit=$(git log -1 --format="%h - %s (%cr)" 2>/dev/null || echo "No commits yet")
        echo "$branch|$uncommitted|$last_commit"
    else
        echo "no-git|0|N/A"
    fi
}

# Check if Docker is configured
check_docker() {
    if [[ -f "$PROJECT_DIR/docker-compose.yml" ]]; then
        echo "yes"
    else
        echo "no"
    fi
}

# Check milestone progress
check_milestones() {
    local completed=0
    local in_progress=0
    local total=6
    
    if [[ -f "$DOCS_DIR/milestones/milestone-01-foundation.md" ]]; then
        # Check for markers in milestone files
        for i in $(seq 1 6); do
            local file="$DOCS_DIR/milestones/milestone-0${i}-*.md"
            if ls $file 1> /dev/null 2>&1; then
                if grep -q "COMPLETED" $file 2>/dev/null; then
                    completed=$((completed + 1))
                elif grep -q "IN_PROGRESS" $file 2>/dev/null; then
                    in_progress=$((in_progress + 1))
                fi
            fi
        done
    fi
    
    echo "$completed|$in_progress|$total"
}

# Generate code review comments
generate_code_review() {
    log "Scanning for code review items..."
    
    local review=""
    
    # Check for TODO/FIXME/XXX in code
    if find "$PROJECT_DIR" -name '*.go' -o -name '*.ts' -o -name '*.tsx' | grep -v node_modules | xargs grep -n 'TODO\|FIXME\|XXX\|HACK' 2>/dev/null | head -20 > /tmp/todos.txt; then
        local todo_count=$(wc -l < /tmp/todos.txt | tr -d ' ')
        if [[ $todo_count -gt 0 ]]; then
            review+="### Action Items Found ($todo_count)\n\n"
            review+="| File | Line | Comment |\n"
            review+="|------|------|---------|\n"
            while IFS=: read -r file line comment; do
                # Extract just the filename
                local fname=$(basename "$file")
                review+="| $fname | $line | $comment |\n"
            done < /tmp/todos.txt
            review+="\n"
        fi
    fi
    
    # Check for security issues
    if find "$PROJECT_DIR" -name '*.go' | xargs grep -l 'http.Get\|http.Post\|ioutil.ReadFile' 2>/dev/null | head -5 > /tmp/security.txt; then
        local sec_count=$(wc -l < /tmp/security.txt | tr -d ' ')
        if [[ $sec_count -gt 0 ]]; then
            review+="### Security Review Notes\n\n"
            review+="- Found $sec_count files using potentially unsafe operations\n"
            review+="- Ensure all HTTP requests have timeouts\n"
            review+="- Validate all file paths before reading\n\n"
        fi
    fi
    
    # Check for error handling
    if find "$PROJECT_DIR" -name '*.go' | xargs grep -n '_ = ' 2>/dev/null | head -10 > /tmp/errors.txt; then
        local err_count=$(wc -l < /tmp/errors.txt | tr -d ' ')
        if [[ $err_count -gt 0 ]]; then
            review+="### Error Handling ($err_count ignored errors)\n\n"
            review+="Several errors are being silently ignored. Consider handling or logging these.\n\n"
        fi
    fi
    
    echo -e "$review"
}

# Generate the status report
generate_status() {
    local iteration=$1
    local now=$(date '+%Y-%m-%d %H:%M:%S UTC')
    local elapsed=$(( $(date +%s) - START_TIME ))
    local elapsed_str="$((elapsed / 3600))h $(((elapsed % 3600) / 60))m"
    
    # Gather metrics
    IFS='|' read -r go_files go_lines ts_files ts_lines md_files md_lines total_files docker_files <<< "$(analyze_codebase)"
    IFS='|' read -r git_branch uncommitted last_commit <<< "$(check_git_status)"
    IFS='|' read -r completed in_progress total_milestones <<< "$(check_milestones)"
    local has_docker=$(check_docker)
    
    # Generate code review
    local review=$(generate_code_review)
    
    # Calculate progress percentage
    local progress=$((completed * 100 / total_milestones))
    
    cat > "$STATUS_FILE" << EOF
# Project Status Report

**Generated:** $now  
**Monitoring Duration:** $elapsed_str  
**Iteration:** $iteration  
**Branch:** $git_branch  

## Quick Stats

| Metric | Value |
|--------|-------|
| Total Files | $total_files |
| Go Files | $go_files (${go_lines} lines) |
| TypeScript Files | $ts_files (${ts_lines} lines) |
| Markdown Files | $md_files (${md_lines} lines) |
| Docker Config | $has_docker |
| Uncommitted Changes | $uncommitted |
| Milestones Complete | $completed/$total_milestones (${progress}%) |

## Recent Activity

**Last Commit:** $last_commit

## Milestone Progress

- [ ] Milestone 1: Foundation
- [ ] Milestone 2: Sync Protocol
- [ ] Milestone 3: Authentication
- [ ] Milestone 4: Collaboration
- [ ] Milestone 5: Search & UI
- [ ] Milestone 6: Production

**Current Focus:** $([[ $in_progress -gt 0 ]] && echo "In Progress" || echo "Not Started")

$review

## Notes for Human Review

EOF

    # Add contextual notes based on what we see
    if [[ $go_files -eq 0 ]]; then
        echo ">> **No Go files found.** Codex may be working on other aspects or hasn't started yet." >> "$STATUS_FILE"
    elif [[ $go_files -lt 5 ]]; then
        echo ">> **Early stage.** Only $go_files Go files exist. Foundation work likely in progress." >> "$STATUS_FILE"
    else
        echo ">> **Active development.** $go_files Go files with ${go_lines} lines of code." >> "$STATUS_FILE"
    fi
    
    if [[ $uncommitted -gt 0 ]]; then
        echo ">> **$uncommitted uncommitted changes** detected. Codex may be mid-work." >> "$STATUS_FILE"
    fi
    
    if [[ -n "$review" ]]; then
        echo ">> **Code review items found.** See Action Items above." >> "$STATUS_FILE"
    fi
    
    cat >> "$STATUS_FILE" << EOF

## Files Changed This Session

EOF

    # List recently modified files
    if [[ -f "$HASH_FILE" ]]; then
        find "$PROJECT_DIR" \
            -type f \
            -mtime -0.007 \
            -not -path '*/node_modules/*' \
            -not -path '*/.git/*' \
            -not -path '*/data/*' \
            -not -name '.last_state_hash' \
            -not -name 'STATUS.md' \
            | sort | head -20 \
            | sed 's|^| - |' >> "$STATUS_FILE" || true
    fi
    
    cat >> "$STATUS_FILE" << EOF

---

*This report auto-generated by Cairnquire progress monitor.*  
*Next update in ~10 minutes or when filesystem changes detected.*
EOF

    success "Status report updated: $STATUS_FILE"
}

# Main monitoring loop
main() {
    log "Starting Cairnquire progress monitor..."
    log "Project: $PROJECT_DIR"
    log "Watching for filesystem changes every 10 minutes"
    log "Press Ctrl+C to stop, or wait for auto-exit on inactivity"
    
    # Ensure docs directory exists
    mkdir -p "$DOCS_DIR"
    
    while true; do
        ITERATION=$((ITERATION + 1))
        
        if [[ $ITERATION -gt $MAX_ITERATIONS ]]; then
            warn "Maximum iterations ($MAX_ITERATIONS) reached. Stopping."
            exit 0
        fi
        
        log "Iteration $ITERATION - checking for changes..."
        
        if [[ $ITERATION -gt 1 ]] && ! has_changes; then
            warn "No filesystem changes detected since last check."
            warn "Stopping monitor (Codex may have finished or is inactive)."
            
            # Add final note to status
            cat >> "$STATUS_FILE" << EOF

## Monitor Stopped

**Stopped:** $(date '+%Y-%m-%d %H:%M:%S UTC')  
**Reason:** No filesystem activity detected

No changes were observed between this check and the previous one.  
This could mean:
- Codex has completed work
- Codex is paused or idle
- No files have been modified recently

To restart monitoring, run: `./scripts/monitor.sh`
EOF
            exit 0
        fi
        
        generate_status $ITERATION
        
        success "Iteration $ITERATION complete. Sleeping for 10 minutes..."
        sleep 600  # 10 minutes
    done
}

# Handle signals
trap 'error "Monitor interrupted"; exit 1' INT TERM

# Run main loop
main
