#!/bin/bash

# Script to compare manual files across different languages
# Usage: ./compare_manuals.sh

set -euo pipefail

# Global variables for tracking issues and options
HAS_ISSUES=0
REMOVE_MODE=false

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

# Base directory for manuals
MANUAL_DIR="manual"
ENGLISH_DIR="${MANUAL_DIR}/english"

# Function to print colored output
print_colored() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
}

# Function to get all language directories
get_language_dirs() {
    find "${MANUAL_DIR}" -mindepth 1 -maxdepth 1 -type d | grep -v "${ENGLISH_DIR}" | sort
}

# Function to get all .md files and directories relative to base path
get_structure() {
    local base_dir=$1
    if [[ ! -d "$base_dir" ]]; then
        return 1
    fi

    # Get all .md files and directories
    find "$base_dir" -name "*.md" -o -type d | \
    sed "s|^${base_dir}/||" | \
    grep -v "^$" | \
    sort
}

# Function to compare file content line by line
compare_files() {
    local file1=$1
    local file2=$2

    if [[ ! -f "$file1" ]] || [[ ! -f "$file2" ]]; then
        return 1
    fi

    local f1_lines f2_lines
    f1_lines=$(wc -l < "$file1")
    f2_lines=$(wc -l < "$file2")

    # First check line count
    if [[ $f1_lines -ne $f2_lines ]]; then
        echo "$f1_lines:$f2_lines"
        return 1
    fi

    # Check empty/non-empty line alignment
    local line_num=1
    local misaligned_lines=()
    
    while IFS= read -r line1 && IFS= read -r line2 <&3; do
        # Remove \r and check if line is empty
        local clean_line1="${line1//$'\r'/}"
        local clean_line2="${line2//$'\r'/}"
        
        local is_empty1=false
        local is_empty2=false
        
        [[ -z "$clean_line1" ]] && is_empty1=true
        [[ -z "$clean_line2" ]] && is_empty2=true
        
        # Check if empty/non-empty state matches
        if [[ "$is_empty1" != "$is_empty2" ]]; then
            misaligned_lines+=("$line_num")
        fi
        
        ((line_num++))
    done < "$file1" 3< "$file2"
    
    # Return misaligned lines if any found
    if [[ ${#misaligned_lines[@]} -gt 0 ]]; then
        echo "alignment:$(IFS=,; echo "${misaligned_lines[*]}")"
        return 1
    fi

    # Check HTML comments are identical (not translated)
    local comments1 comments2
    comments1=$(grep -o '<!--.*-->' "$file1" | sort)
    comments2=$(grep -o '<!--.*-->' "$file2" | sort)
    
    if [[ "$comments1" != "$comments2" ]]; then
        echo "comments:translated"
        return 1
    fi

    return 0
}

# Function to check if path exists in language directory
path_exists() {
    local lang_dir=$1
    local relative_path=$2

    local full_path="${lang_dir}/${relative_path}"
    [[ -e "$full_path" ]]
}

# Function to check that Markdown ATX titles use a space after the opening # marker
check_markdown_title_spacing() {
    local manual_dir=$1

    print_colored "$BLUE" "=== Markdown Title Spacing Check ==="

    local violations
    violations=$(
        find "$manual_dir" -type f -name "*.md" -print0 | \
        while IFS= read -r -d '' md_file; do
            awk -v file="$md_file" '
                {
                    line = $0
                    sub(/\r$/, "", line)

                    # Ignore fenced code blocks so examples like shell prompts do not fail the check.
                    fence_line = line
                    sub(/^[ ]{0,3}/, "", fence_line)

                    if (in_fence) {
                        if (fence_char == "`" && fence_line ~ /^```+/) {
                            match(fence_line, /^`+/)
                            if (RLENGTH >= fence_len) {
                                in_fence = 0
                            }
                        } else if (fence_char == "~" && fence_line ~ /^~~~+/) {
                            match(fence_line, /^~+/)
                            if (RLENGTH >= fence_len) {
                                in_fence = 0
                            }
                        }
                        next
                    }

                    if (fence_line ~ /^```+/) {
                        match(fence_line, /^`+/)
                        fence_char = "`"
                        fence_len = RLENGTH
                        in_fence = 1
                        next
                    }
                    if (fence_line ~ /^~~~+/) {
                        match(fence_line, /^~+/)
                        fence_char = "~"
                        fence_len = RLENGTH
                        in_fence = 1
                        next
                    }

                    # Bad: #Title or ##Title. Good: # Title or ## Title.
                    if (line ~ /^[ ]{0,3}#{1,6}[^ #]/) {
                        printf "%s:%d:%s\n", file, FNR, line
                    }
                }
            ' "$md_file"
        done
    )

    if [[ -n "$violations" ]]; then
        HAS_ISSUES=1
        print_colored "$RED" "Markdown titles without a space after the opening # marker:"
        printf '%s\n' "$violations" | while IFS= read -r violation; do
            printf '  %s\n' "$violation"
        done
        echo
    else
        print_colored "$GREEN" "✓ All markdown titles have a space after the opening # marker."
        echo
    fi
}

# Main comparison function
compare_with_languages() {
    local english_dir=$1

    if [[ ! -d "$english_dir" ]]; then
        print_colored "$RED" "Error: English directory '$english_dir' not found!"
        exit 1
    fi

    print_colored "$BLUE" "=== Manual Structure Comparison ==="
    print_colored "$BLUE" "Base directory: $english_dir"
    if [[ "$REMOVE_MODE" == "true" ]]; then
        print_colored "$YELLOW" "REMOVE MODE: Files with mismatched line counts will be automatically removed"
    fi
    echo

    # Get English structure
    local english_structure
    english_structure=$(get_structure "$english_dir")

    if [[ -z "$english_structure" ]]; then
        print_colored "$YELLOW" "Warning: No .md files or directories found in $english_dir"
        return
    fi

    # Get all language directories
    local lang_dirs
    lang_dirs=$(get_language_dirs)

    if [[ -z "$lang_dirs" ]]; then
        print_colored "$YELLOW" "Warning: No other language directories found in $MANUAL_DIR"
        return
    fi

    print_colored "$GREEN" "Found language directories:"
    echo "$lang_dirs" | while read -r lang_dir; do
        echo "  - $(basename "$lang_dir")"
    done
    echo

    # Compare each language with English
    while IFS= read -r lang_dir; do
        local lang_name
        lang_name=$(basename "$lang_dir")

        print_colored "$BLUE" "--- Comparing with $lang_name ---"

        local missing_files=()
        local different_files=()
        local missing_dirs=()
        local removed_files=()

        # Check each item in English structure
        while IFS= read -r item; do
            local english_path="${english_dir}/${item}"
            local lang_path="${lang_dir}/${item}"

            if [[ ! -e "$lang_path" ]]; then
                if [[ -d "$english_path" ]]; then
                    missing_dirs+=("$item")
                    HAS_ISSUES=1
                elif [[ -f "$english_path" ]]; then
                    missing_files+=("$item")
                    HAS_ISSUES=1
                fi
            elif [[ -f "$english_path" ]] && [[ -f "$lang_path" ]]; then
                # Both are files, compare content
                local diff_result
                set +e  # Temporarily disable exit on error
                diff_result=$(compare_files "$english_path" "$lang_path")
                local compare_exit_code=$?
                set -e  # Re-enable exit on error

                if [[ $compare_exit_code -ne 0 ]]; then
                    HAS_ISSUES=1
                    if [[ "$REMOVE_MODE" == "true" ]]; then
                        # Remove the file with mismatched line count
                        rm -f "$lang_path"
                        removed_files+=("$item")
                        print_colored "$RED" "REMOVED: $lang_path (line count mismatch)"
                    else
                        if [[ -n "$diff_result" ]]; then
                            different_files+=("$item|$diff_result")
                        else
                            different_files+=("$item")
                        fi
                    fi
                fi
            fi
        done <<< "$english_structure"

        # Report results
        if [[ ${#missing_dirs[@]} -gt 0 ]]; then
            print_colored "$RED" "Missing directories in $lang_name:"
            printf '  %s\n' "${missing_dirs[@]}"
            echo
        fi

        if [[ ${#missing_files[@]} -gt 0 ]]; then
            print_colored "$RED" "Missing files in $lang_name:"
            printf '  %s\n' "${missing_files[@]}"
            echo
        fi

        if [[ ${#removed_files[@]} -gt 0 ]]; then
            print_colored "$RED" "Removed files with mismatched line counts in $lang_name:"
            printf '  %s\n' "${removed_files[@]}"
            echo
        fi

        if [[ ${#different_files[@]} -gt 0 ]]; then
            print_colored "$YELLOW" "Files with different content in $lang_name:"
            for file_info in "${different_files[@]}"; do
                if [[ "$file_info" == *"|"* ]]; then
                    local file="${file_info%|*}"
                    local error_info="${file_info#*|}"
                    if [[ "$error_info" == *":"* ]] && [[ "$error_info" != "alignment:"* ]] && [[ "$error_info" != "comments:"* ]]; then
                        # Line count mismatch
                        local eng_lines="${error_info%:*}"
                        local lang_lines="${error_info#*:}"
                        printf '  %s (English: %d lines, %s: %d lines)\n' "$file" "$eng_lines" "$lang_name" "$lang_lines"
                    elif [[ "$error_info" == "alignment:"* ]]; then
                        # Empty/non-empty line alignment issue
                        local misaligned_lines="${error_info#alignment:}"
                        printf '  %s (empty/non-empty line alignment mismatch at lines: %s)\n' "$file" "$misaligned_lines"
                    elif [[ "$error_info" == "comments:"* ]]; then
                        # HTML comments translated
                        printf '  %s (HTML comments <!-- --> were translated, must remain in English)\n' "$file"
                    else
                        printf '  %s (%s)\n' "$file" "$error_info"
                    fi
                else
                    printf '  %s\n' "$file_info"
                fi
            done
            echo
        fi

        if [[ ${#missing_dirs[@]} -eq 0 ]] && [[ ${#missing_files[@]} -eq 0 ]] && [[ ${#different_files[@]} -eq 0 ]] && [[ ${#removed_files[@]} -eq 0 ]]; then
            print_colored "$GREEN" "✓ $lang_name structure and content matches English perfectly!"
            echo
        fi
    done <<< "$lang_dirs"
}

# Function to show detailed diff for specific files
show_detailed_diff() {
    local english_dir=$1
    local lang_dir=$2
    local file_path=$3

    local english_file="${english_dir}/${file_path}"
    local lang_file="${lang_dir}/${file_path}"

    if [[ -f "$english_file" ]] && [[ -f "$lang_file" ]]; then
        print_colored "$BLUE" "--- Detailed diff for $file_path ---"
        print_colored "$BLUE" "English: $english_file"
        print_colored "$BLUE" "$(basename "$lang_dir"): $lang_file"
        echo

        # Show side-by-side diff with line numbers
        diff -u "$english_file" "$lang_file" || true
        echo
    fi
}

# Function to show summary statistics
show_summary() {
    local english_dir=$1

    print_colored "$BLUE" "=== Summary Statistics ==="

    # Count English files and directories
    local english_files
    local english_dirs
    english_files=$(find "$english_dir" -name "*.md" | wc -l | tr -d ' ')
    english_dirs=$(find "$english_dir" -type d | wc -l | tr -d ' ')

    echo "English structure:"
    echo "  - Directories: $english_dirs"
    echo "  - .md files: $english_files"
    echo

    # Count for each language
    get_language_dirs | while read -r lang_dir; do
        local lang_name
        lang_name=$(basename "$lang_dir")

        local lang_files
        local lang_dirs_count
        lang_files=$(find "$lang_dir" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
        lang_dirs_count=$(find "$lang_dir" -type d 2>/dev/null | wc -l | tr -d ' ')

        echo "$lang_name structure:"
        echo "  - Directories: $lang_dirs_count"
        echo "  - .md files: $lang_files"
        echo
    done
}

# Main execution
main() {
    # Check if manual directory exists
    if [[ ! -d "$MANUAL_DIR" ]]; then
        print_colored "$RED" "Error: Manual directory '$MANUAL_DIR' not found in current directory!"
        print_colored "$YELLOW" "Current directory: $(pwd)"
        exit 1
    fi

    # Check if English directory exists
    if [[ ! -d "$ENGLISH_DIR" ]]; then
        print_colored "$RED" "Error: English directory '$ENGLISH_DIR' not found!"
        exit 1
    fi

    print_colored "$GREEN" "Starting manual comparison..."
    echo "Current directory: $(pwd)"
    echo

    # Show summary first
    show_summary "$ENGLISH_DIR"

    # Check all manual Markdown titles before comparing translations
    check_markdown_title_spacing "$MANUAL_DIR"

    # Compare structures and content
    # Compare structures and content
    compare_with_languages "$ENGLISH_DIR"

    if [[ $HAS_ISSUES -eq 0 ]]; then
        print_colored "$GREEN" "Comparison completed! All translations are perfect."
        exit 0
    else
        print_colored "$RED" "Comparison completed with issues found."
        exit 1
    fi
}

# Handle command line arguments
# Handle command line arguments
case "${1:-}" in
    -h|--help)
        echo "Usage: $0 [OPTIONS]"
        echo ""
        echo "Compare manual files across different languages"
        echo ""
        echo "OPTIONS:"
        echo "  -h, --help     Show this help message"
        echo "  -s, --summary  Show only summary statistics"
        echo "  --remove       Automatically remove files with mismatched line counts"
        echo ""
        echo "EXIT CODES:"
        echo "  0              All translations perfect and Markdown titles have valid spacing"
        echo "  1              Issues found (missing translations, content mismatches, or Markdown title spacing errors)"
        echo ""
        echo "This script compares the structure and content of .md files"
        echo "in manual/english/ with all other language directories, and checks"
        echo "that Markdown titles in manual/ use '# Title' spacing."
        echo "With --remove flag, files with different line counts are automatically deleted."
        exit 0
        ;;
    -s|--summary)
        show_summary "$ENGLISH_DIR"
        exit 0
        ;;
    --remove)
        REMOVE_MODE=true
        main
        ;;
    "")
        main
        ;;
    *)
        print_colored "$RED" "Unknown option: $1"
        print_colored "$YELLOW" "Use -h or --help for usage information"
        exit 1
        ;;
esac
