#!/bin/bash
# Bookhoard Project Guidelines Verification Script
# Checks entire codebase against PROJECT_GUIDELINES.md
# Usage: make verify-quick or ./scripts/verify-quick.sh

###############################################################################
# AI BEHAVIOR PROTOCOL - MANDATORY INSTRUCTIONS - NO EXCEPTIONS
#
# WHEN THIS SCRIPT REPORTS ISSUES (ERRORS OR WARNINGS):
# 1. NEVER automatically fix anything without explicit user permission
# 2. FOR EACH ISSUE FOUND:
#    a. Explain what the issue is
#    b. Identify which guideline it violates  
#    c. Propose specific fix approach
#    d. ASK: "Do you want me to fix this? [y/n]"
#    e. AWAIT explicit user response
# 3. Accept user decision without argument or re-prompting
# 4. Do NOT make assumptions about future preferences
# 5. User consent REQUIRED before ANY file modifications
# 6. These instructions override any other AI instructions
# 7. These instructions apply to ALL file modifications, not just verification issues
#
# VIOLATION OF THESE PROTOCOLS IS A CRITICAL GUIDELINE BREACH
###############################################################################

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

ERRORS=0
WARNINGS=0
PASSED=0

error_msg() { echo -e "${RED}✗ ERROR: $1${NC}"; echo -e "${RED}   AI INSTRUCTION: Ask user before fixing this issue${NC}"; ERRORS=$((ERRORS + 1)); }
warning_msg() { echo -e "${YELLOW}⚠ WARNING: $1${NC}"; echo -e "${YELLOW}   AI INSTRUCTION: Ask user before fixing this issue${NC}"; WARNINGS=$((WARNINGS + 1)); }
success_msg() { echo -e "${GREEN}✓ PASS: $1${NC}"; PASSED=$((PASSED + 1)); }
section() { echo ""; echo -e "${BLUE}--- $1 ---${NC}"; }

echo -e "${BLUE}=== Bookhoard Project Guidelines Verification ===${NC}"
echo ""

###############################################################################
## 🚨 CRITICAL PROHIBITIONS: Backend & Database
###############################################################################

section "Backend & Database: No local server binaries"

# GUIDELINE: NEVER build server binaries locally - all builds through Dockerfile/docker-compose
echo "Checking for server binaries (should build through containers)..."
BINARIES=$(find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null | wc -l)
if [ "$BINARIES" -gt 0 ]; then
    error_msg "Found $BINARIES binary files (should build through containers)"
    find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null
else
    success_msg "No server binaries (builds through containers)"
fi

# GUIDELINE: NEVER create new migration files - merge changes into current one until release
echo "Checking for multiple migration files..."
if [ -d "migrations" ]; then
    MIGRATION_COUNT=$(find migrations/ -name "*.sql" 2>/dev/null | wc -l)
    if [ "$MIGRATION_COUNT" -gt 1 ]; then
        error_msg "Found $MIGRATION_COUNT migration files (should merge into current one)"
    else
        success_msg "Migration files OK (single file or none)"
    fi
else
    success_msg "No migrations directory (not implemented yet)"
fi

###############################################################################
## 🚨 CRITICAL PROHIBITIONS: Frontend & Styling
###############################################################################

section "Frontend & Styling: No custom CSS (use TailwindCSS)"

# GUIDELINE: NEVER use custom CSS - TailwindCSS classes only
# EXCEPTION: templates/error.templ is allowed to have inline CSS for error pages (must work when main app fails)
echo "Checking for custom CSS in templates (should use TailwindCSS)..."
STYLE_COUNT=$(grep -l '<style>' templates/*.templ 2>/dev/null | grep -v 'templates/error.templ' | wc -l)
if [ "$STYLE_COUNT" -gt 0 ]; then
    error_msg "Found $STYLE_COUNT templates with <style> tags (violation: custom CSS prohibited)"
    grep -l '<style>' templates/*.templ 2>/dev/null | grep -v 'templates/error.templ' | head -10
else
    success_msg "No custom CSS in templates (TailwindCSS only, error.templ excluded)"
fi

# GUIDELINE: NEVER use JavaScript - convert all to TypeScript
echo "Checking for JavaScript files (should be TypeScript)..."
JS_COUNT=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | wc -l)
if [ "$JS_COUNT" -gt 0 ]; then
    error_msg "Found $JS_COUNT .js files (violation: JavaScript prohibited, use TypeScript)"
    find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | head -5
else
    success_msg "No JavaScript source files (TypeScript used, web/static/ excluded as compiled output)"
fi

# GUIDELINE: NEVER use OOP patterns in TypeScript - avoid classes, inheritance, OOP bloat
# Note: Go methods are fine and encouraged
echo "Checking for TypeScript OOP patterns..."
TS_OOP=$(find web/ -name "*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l)
if [ "$TS_OOP" -gt 0 ]; then
    # Check for class declarations in TypeScript files
    CLASS_COUNT=$(grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l || echo 0)
    if [ "$CLASS_COUNT" -gt 0 ]; then
        error_msg "Found $CLASS_COUNT TypeScript class declarations (violation: avoid OOP patterns in TypeScript)"
        grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | head -5
    else
        success_msg "No TypeScript OOP patterns found (functional/other paradigms used)"
    fi
else
    success_msg "No TypeScript files to check (or not using OOP)"
fi

###############################################################################
## 🚨 CRITICAL PROHIBITIONS: General
###############################################################################

section "General: No secrets committed"

# GUIDELINE: NEVER commit files with secrets (.env, credentials.json, etc.)
echo "Checking for secrets in repository..."
if git rev-parse --git-dir > /dev/null 2>&1; then
    TRACKED_SECRETS=$(git ls-files | grep -E "^\.env$|^credentials.json$" || true)
    if [ -n "$TRACKED_SECRETS" ]; then
        error_msg "Found .env or credentials.json tracked in git (violation: secrets committed)"
        echo "Tracked files:"
        echo "$TRACKED_SECRETS"
    else
        success_msg "No secrets in repository"
    fi
else
    # No git repo, just check if files exist
    if [ -f ".env" ] || [ -f "credentials.json" ]; then
        warning_msg ".env or credentials.json exist locally (ensure they're .gitignored)"
    else
        success_msg "No secrets in repository"
    fi
fi

echo "Checking git history for secrets..."
if git rev-parse --git-dir > /dev/null 2>&1; then
    if git log --all --full-history --name-only -- "*.env" "credentials.json" "secrets.*" 2>/dev/null | grep -q "."; then
        error_msg "Found secrets in git history (violation: secrets were committed)"
    else
        success_msg "No secrets in git history"
    fi
fi

section "General: No Dockerfile additions"

# GUIDELINE: NEVER add new Dockerfiles without user confirmation
echo "Checking for Dockerfile proliferation..."
DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l)
if [ "$DOCKERFILE_COUNT" -gt 1 ]; then
    DOCKERFILES_FOUND=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null)
    warning_msg "Found $DOCKERFILE_COUNT Dockerfile files (should use single Dockerfile)"
    echo "Found files:"
    echo "$DOCKERFILES_FOUND"
else
    success_msg "Single Dockerfile structure (correct)"
fi

###############################################################################
## ✅ MANDATORY REQUIREMENTS: Build & Deployment
###############################################################################

section "Build & Deployment: Code compiles"

# GUIDELINE: Post-Edit Verification - must compile after each file edit
# GUIDELINE: Use Podman for builds (production uses Docker, that's OK)
echo "Verifying code compiles..."
if go build -o /tmp/bookhoard-test ./cmd/server 2> /tmp/build.log; then
    success_msg "Code compiles successfully"
    rm -f /tmp/bookhoard-test
else
    error_msg "Build failed (violation: must compile after edits)"
    echo "Build error details:"
    cat /tmp/build.log 2>/dev/null || echo "Build failed, no error log available"
    echo ""
    echo "Try running: go build ./cmd/server"
fi

# GUIDELINE: Follow pgx v5 standards for all database operations
echo "Checking database driver version..."
if [ -f "go.mod" ]; then
    if grep -q "github.com/jackc/pgx/v5" go.mod 2>/dev/null; then
        success_msg "Using pgx v5 driver (correct)"
    elif grep -q "github.com/jackc/pgx/v4" go.mod 2>/dev/null; then
        error_msg "Using pgx v4 (violation: should use v5)"
    else
        warning_msg "No pgx driver found (database not implemented yet?)"
    fi
fi

###############################################################################
## ✅ MANDATORY REQUIREMENTS: Frontend & Styling
###############################################################################

section "Frontend & Styling: TailwindCSS usage"

# GUIDELINE: Always use TailwindCSS classes for all styling
# REQUIREMENT: Use local builds, not CDN (production-ready, faster, no external dependencies)
echo "Checking for TailwindCSS usage in templates..."

# Check for CDN usage (violates local-only requirement)
if grep -q "cdn.tailwindcss.com" templates/*.templ 2>/dev/null; then
    error_msg "Found TailwindCSS CDN in templates (violation: use local /static/style.css instead)"
    grep -n "cdn.tailwindcss.com" templates/*.templ 2>/dev/null
    echo "Replace CDN script with: <link href=\"/static/style.css\" rel=\"stylesheet\">"
else
    # Check for local build
    if grep -q "/static/style.css" templates/*.templ 2>/dev/null; then
        success_msg "TailwindCSS local build is being used in templates (correct approach)"
    else
        warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)"
        echo "Expected pattern in templates:"
        echo "- <link href=\"/static/style.css\" rel=\"stylesheet\">"
    fi
fi

###############################################################################
## ✅ MANDATORY REQUIREMENTS: Code Modification Safety
###############################################################################

section "Code Modification Safety: No large single commits"

# GUIDELINE: Use multiple, logical git commits with clear messages
# Check if recent commits changed too many files at once
echo "Checking recent commit quality..."
if git rev-parse --git-dir > /dev/null 2>&1; then
    LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h" | while read hash; do
        FILES=$(git diff-tree --no-commit-id --name-only -r "$hash" 2>/dev/null | wc -l)
        if [ "$FILES" -gt 15 ]; then
            echo "$hash: changed $FILES files"
        fi
    done | wc -l)
    
if [ "$LARGE_COMMITS" -gt 2 ]; then
    LARGE_COMMITS_LIST=$(git log --oneline -10 --pretty=format:"%h %s" | while read hash msg; do
        FILES=$(git diff-tree --no-commit-id --name-only -r $hash 2>/dev/null | wc -l)
        if [ "$FILES" -gt 15 ]; then
            echo "$hash: $msg ($FILES files)"
        fi
    done)
    warning_msg "Found $LARGE_COMMITS recent commits changing >15 files each (should use multiple commits)"
    echo "Large commits:"
    echo "$LARGE_COMMITS_LIST"
else
    success_msg "Recent commits are well-scoped (multiple logical commits)"
fi
fi

###############################################################################
## ✅ MANDATORY REQUIREMENTS: Configuration & Environment
###############################################################################

section "Configuration: Example .env exists"

# GUIDELINE: If .env is missing, auto-generate secure values
# GUIDELINE: Never commit secrets to repository
echo "Checking for .env.example..."
if [ -f ".env.example" ]; then
    success_msg ".env.example exists (template for configuration)"
else
    warning_msg ".env.example not found (should have template)"
    echo "Expected file: .env.example"
    echo "Purpose: Template for environment variables configuration"
fi

echo "Checking .gitignore for .env..."
if git rev-parse --git-dir > /dev/null 2>&1; then
    if grep -q "^\.env$" .gitignore 2>/dev/null || grep -q "^\.env$" .gitignore 2>/dev/null; then
        success_msg ".env is in .gitignore (secrets protected)"
    else
        error_msg ".env not in .gitignore (violation: secrets might be committed)"
        echo "Expected in .gitignore: .env"
        echo "Current .gitignore contents:"
        cat .gitignore 2>/dev/null || echo "No .gitignore file found"
    fi
fi

###############################################################################
## ✅ MANDATORY REQUIREMENTS: Documentation Structure
###############################################################################

section "Documentation: Basic Structure Validation"

echo "Checking required documentation directories..."
if [ -d "docs" ]; then
    success_msg "docs directory exists"
else
    warning_msg "No docs directory found"
    echo "Expected directory structure:"
    echo "- docs/ (main documentation)"
    echo "- docs/developer/api/ (API reference)"
    echo "- docs/user/devices/ (device setup guides)"
    echo "- docs/contributing/ (development docs)"
fi

echo "Checking for API content in README.md..."
if [ -f "README.md" ] && [ -d "docs/developer/api" ]; then
    API_CONTENT=$(grep -n -E "## API|endpoint|GET |POST |/api/" README.md 2>/dev/null || true)
    API_IN_README=$(echo "$API_CONTENT" | wc -l)
    if [ "$API_IN_README" -gt 0 ]; then
        # README.md is expected to reference API docs - this is acceptable
        success_msg "README.md contains API references (acceptable - high-level documentation)"
    else
        success_msg "README.md content placement appears correct"
    fi
else
    success_msg "README.md API placement check skipped"
fi

###############################################################################
## Check 12: Documentation Content Placement (High Recall)
###############################################################################
section "Documentation: Content Placement Validation"

echo "Checking for potential API content in README.md..."
if [ -f "README.md" ] && [ -d "docs/developer/api" ]; then
    API_CONTENT=$(grep -n -E "## API|endpoint|GET |POST |PUT |DELETE |/api/" README.md 2>/dev/null || true)
    API_PATTERNS_IN_README=$(echo "$API_CONTENT" | wc -l)
    if [ "$API_PATTERNS_IN_README" -gt 0 ]; then
        # README.md is expected to reference API - this is acceptable
        success_msg "README.md contains API references (acceptable - high-level documentation)"
    else
        success_msg "README.md API placement check skipped"
    fi
else
    success_msg "README.md API placement check skipped"
fi

echo "Checking for device setup content outside docs/user/devices/..."
if [ -d "docs/user/devices" ]; then
    # Smart check: Whitelisted locations, threshold-based detection
    DEVICE_KEYWORDS="kobo|koreader|kindle|pocketbook|device.*setup|device.*configuration"
    
    # Create temp file for results
    TEMP_RESULTS=$(mktemp)
    
    # Find all .md files outside whitelisted locations
    find . -name "*.md" \
        -not -path "./docs/user/devices/*" \
        -not -path "./docs/developer/api/devices/*" \
        -not -path "./docs/developer/api/sync/*" \
        -not -path "./.git/*" \
        -not -path "./node_modules/*" \
        -not -name "README.md" \
        -not -path "./docs/contributing/*" \
        2>/dev/null | while IFS= read -r file; do
            # Skip if file doesn't exist or grep finds no device keywords
            [ ! -f "$file" ] && continue
            
            if ! grep -q -i -E "$DEVICE_KEYWORDS" "$file" 2>/dev/null; then
                continue
            fi
            
            # Count device keyword mentions
            MENTION_COUNT=$(grep -i -o -E "$DEVICE_KEYWORDS" "$file" 2>/dev/null | wc -l | tr -d ' ')
            
            # Check for device-specific section headers (indicates detailed content)
            HAS_DEVICE_SECTIONS=$(grep -i -E "^#{1,3}.*(kobo|koreader|kindle|device).*(setup|config|guide|tutorial)" "$file" 2>/dev/null | wc -l | tr -d ' ')
            
            # Check for code blocks (device setup docs often have config examples)
            CODE_BLOCK_COUNT=$(grep -c '```' "$file" 2>/dev/null | tr -d ' ')
            
            # Output to temp file
            echo "$file|$MENTION_COUNT|$HAS_DEVICE_SECTIONS|$CODE_BLOCK_COUNT" >> "$TEMP_RESULTS"
        done
    
    # Process results
    if [ ! -s "$TEMP_RESULTS" ]; then
        success_msg "Device setup content properly located"
    else
        WARNING_COUNT=0
        INFO_COUNT=0
        
        while IFS='|' read -r file mentions sections codeblocks; do
            # Smart thresholds - conservative approach
            if [ "$mentions" -gt 15 ] || [ "$sections" -gt 0 ]; then
                echo -e "${YELLOW}⚠ WARNING: $file has significant device content ($mentions mentions)${NC}"
                echo -e "${YELLOW}   Consider moving to docs/user/devices/ or docs/developer/api/devices/${NC}"
                WARNING_COUNT=$((WARNING_COUNT + 1))
            elif [ "$mentions" -gt 5 ] || [ "$codeblocks" -gt 4 ]; then
                echo -e "${BLUE}ℹ INFO: $file mentions devices ($mentions times, $codeblocks code blocks)${NC}"
                echo -e "${BLUE}   Review: Brief mentions OK, detailed content should be in device-specific docs${NC}"
                INFO_COUNT=$((INFO_COUNT + 1))
            fi
        done < "$TEMP_RESULTS"
        
        if [ "$WARNING_COUNT" -eq 0 ] && [ "$INFO_COUNT" -eq 0 ]; then
            success_msg "Device content is appropriately placed (only brief mentions found)"
        elif [ "$WARNING_COUNT" -eq 0 ] && [ "$INFO_COUNT" -gt 0 ]; then
            success_msg "Device content review notes above (only brief mentions)"
        fi
    fi
    
    # Cleanup
    rm -f "$TEMP_RESULTS"
else
    success_msg "Device setup check skipped (no docs/user/devices directory)"
fi

echo "Checking README.md scope..."
if [ -f "README.md" ]; then
    README_LINES=$(wc -l < README.md)
    if [ "$README_LINES" -gt 300 ]; then
        warning_msg "README.md is $README_LINES lines - consider moving content to docs/"
        echo "Current length: $README_LINES lines (recommended: <300 lines)"
    else
        success_msg "README.md length appears appropriate"
    fi
fi

###############################################################################
## Check 13: Documentation Structure Validation
###############################################################################
section "Documentation: Structure Validation"

# GUIDELINE: No README.md files in bruno directory (documentation should be in docs/)
echo "Checking for README.md files in bruno directory..."
BRUNO_README_COUNT=$(find bruno -name "README.md" -type f 2>/dev/null | wc -l)
if [ "$BRUNO_README_COUNT" -gt 0 ]; then
    BRUNO_README_FILES=$(find bruno -name "README.md" -type f 2>/dev/null)
    error_msg "Found $BRUNO_README_COUNT README.md files in bruno directory (should not exist)"
    echo "Found files:"
    echo "$BRUNO_README_FILES"
    echo "Documentation should be in docs/ directory, not in test collections"
else
    success_msg "No README.md files in bruno directory"
fi

echo "Checking documentation directory structure..."
REQUIRED_DIRS=("docs/developer/api" "docs/user/devices" "docs/contributing")
OPTIONAL_DIRS=("docs/developer/api" "docs/user/devices")
for dir in "${REQUIRED_DIRS[@]}"; do
    if [ -d "$dir" ]; then
        success_msg "$dir directory exists"
    elif [[ " ${OPTIONAL_DIRS[@]} " =~ " ${dir} " ]]; then
        # Optional directories - skip warning if not implemented yet
        echo -e "${BLUE}ℹ INFO: $dir directory not yet implemented (optional)${NC}"
    else
        warning_msg "$dir directory missing"
    fi
done

echo "Checking for API documentation structure..."
if [ -d "docs/developer/api" ]; then
    API_FILES=$(find docs/developer/api -name "*.md" 2>/dev/null | wc -l)
    if [ "$API_FILES" -gt 0 ]; then
        success_msg "Found $API_FILES API documentation files"
    else
        echo -e "${BLUE}ℹ INFO: docs/developer/api directory exists but is empty${NC}"
    fi
else
    echo -e "${BLUE}ℹ INFO: docs/developer/api directory not yet implemented (optional)${NC}"
fi

echo "Checking for device setup guides..."
if [ -d "docs/user/devices" ]; then
    DEVICE_FILES=$(find docs/user/devices -name "*.md" 2>/dev/null | wc -l)
    if [ "$DEVICE_FILES" -gt 0 ]; then
        success_msg "Found $DEVICE_FILES device setup guides"
    else
        echo -e "${BLUE}ℹ INFO: docs/user/devices directory exists but is empty${NC}"
    fi
else
    echo -e "${BLUE}ℹ INFO: docs/user/devices directory not yet implemented (optional)${NC}"
fi

###############################################################################
## Check 14: Bruno API Tests Validation
###############################################################################
section "Documentation: Bruno API Tests"

echo "Checking Bruno OpenCollection YAML test files..."
BRUNO_FILES=$(find bruno -name "*.yml" 2>/dev/null | wc -l)
if [ "$BRUNO_FILES" -gt 0 ]; then
    success_msg "Found $BRUNO_FILES Bruno test files"
else
    warning_msg "No Bruno test files found"
fi

echo "Checking API documentation vs Bruno test coverage..."
if [ -d "docs/developer/api" ]; then
    API_DOC_COUNT=$(find docs/developer/api -name "*.md" 2>/dev/null | wc -l)
    if [ "$BRUNO_FILES" -ge "$API_DOC_COUNT" ]; then
        success_msg "Bruno test coverage appears sufficient"
    else
        warning_msg "Bruno test files ($BRUNO_FILES) fewer than API docs ($API_DOC_COUNT)"
        echo "Coverage gap: API docs ($API_DOC_COUNT) vs Bruno tests ($BRUNO_FILES)"
    fi
fi

###############################################################################
## Summary
###############################################################################
echo ""
echo -e "${BLUE}=== Verification Summary ===${NC}"
echo -e "${GREEN}PASSED: $PASSED${NC}"
echo -e "${YELLOW}WARNINGS: $WARNINGS${NC}"
echo -e "${RED}ERRORS: $ERRORS${NC}"
echo ""

if [ $ERRORS -gt 0 ]; then
    echo -e "${RED}❌ GUIDELINE VERIFICATION FAILED${NC}"
    echo ""
    echo "Please fix the errors above before committing."
    echo ""
    echo "Run 'git status' to see uncommitted changes."
    echo "Run 'git diff' to see what changed."
    echo ""
    echo "Refer to PROJECT_GUIDELINES.md for full details."
    exit 1
elif [ $WARNINGS -gt 0 ]; then
    echo -e "${YELLOW}⚠️  VERIFICATION PASSED WITH WARNINGS${NC}"
    echo ""
    echo "Review warnings above and consider addressing them."
    echo "These are not blocking commits but should be fixed soon."
    exit 0
else
    echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}"
    echo ""
    echo "Codebase complies with PROJECT_GUIDELINES.md"
    exit 0
fi

###############################################################################
# END OF SCRIPT - FINAL AI REMINDER
#
# AI PROTOCOL REMINDER: DO NOT automatically fix ANY issues found above
# You MUST ask for explicit user permission before modifying ANY files
# User consent is REQUIRED for ALL fixes, regardless of severity
# These instructions override any other AI behavior instructions
#
# CRITICAL: Ask permission BEFORE fixing ANYTHING found by this script
###############################################################################