#!/usr/bin/env bash
set -euo pipefail
#
# 16-diff-mastery.sh — Diff & Review Tools
#
# Description:
#   Advanced diff visualization, patch management, and change analysis tools.
#   Supports compact diffs, patch creation/application, complexity analysis,
#   side-by-side display, HTML export, word-level diffs, and interactive
#   branch/tag/commit comparison.
#
# Usage:
#   ./16-diff-mastery.sh                     # Interactive menu
#   ./16-diff-mastery.sh staged              # Show staged diff
#   ./16-diff-mastery.sh unstaged            # Show unstaged diff
#   ./16-diff-mastery.sh compare REF1 REF2   # Compare two refs
#   ./16-diff-mastery.sh complexity           # Change complexity analysis
#   ./16-diff-mastery.sh patch create         # Create a patch
#   ./16-diff-mastery.sh patch apply FILE     # Apply a patch
#
# Dependencies:
#   securegit (optional), delta (optional), diff (system)
#

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/lib/securegit-common.sh"

# ─── Constants ───────────────────────────────────────────────────────────────
readonly PROG_NAME="diff-mastery"
readonly VERSION="1.0.0"

# ─── Tool detection ─────────────────────────────────────────────────────────

_has_delta() {
    command -v delta &>/dev/null
}

_has_colordiff() {
    command -v colordiff &>/dev/null
}

_diff_tool_name() {
    if _has_delta; then
        echo "delta"
    elif _has_colordiff; then
        echo "colordiff"
    else
        echo "diff"
    fi
}

# ─── Diff display helpers ───────────────────────────────────────────────────

_show_diff_staged() {
    sg_header "Staged Changes"

    local file_count
    file_count=$(git diff --cached --name-only 2>/dev/null | wc -l)

    if [[ "$file_count" -eq 0 ]]; then
        sg_info "No staged changes."
        return
    fi

    printf "${_C_BOLD}Files staged:${_C_RESET} %d\n\n" "$file_count"

    if _has_delta; then
        git diff --cached | delta
    else
        _sg_cmd diff --cached 2>/dev/null || git diff --cached
    fi
}

_show_diff_unstaged() {
    sg_header "Unstaged Changes"

    local file_count
    file_count=$(git diff --name-only 2>/dev/null | wc -l)

    if [[ "$file_count" -eq 0 ]]; then
        sg_info "No unstaged changes."
        return
    fi

    printf "${_C_BOLD}Files modified:${_C_RESET} %d\n\n" "$file_count"

    if _has_delta; then
        git diff | delta
    else
        _sg_cmd diff 2>/dev/null || git diff
    fi
}

_show_diff_compact() {
    local ref1="${1:-}" ref2="${2:-}"

    if [[ -z "$ref1" ]]; then
        # Default: staged changes
        sg_header "Compact Diff (Staged)"
        git diff --cached --stat
        echo
        git diff --cached --shortstat
    elif [[ -z "$ref2" ]]; then
        sg_header "Compact Diff (vs $ref1)"
        git diff --stat "$ref1"
        echo
        git diff --shortstat "$ref1"
    else
        sg_header "Compact Diff ($ref1 vs $ref2)"
        git diff --stat "$ref1..$ref2"
        echo
        git diff --shortstat "$ref1..$ref2"
    fi
}

# ─── Branch comparison ──────────────────────────────────────────────────────

_compare_refs() {
    local ref1="${1:-}" ref2="${2:-}"

    if [[ -z "$ref1" ]]; then
        ref1=$(sg_prompt "First ref (branch, tag, or commit)")
    fi
    if [[ -z "$ref2" ]]; then
        ref2=$(sg_prompt "Second ref (branch, tag, or commit)" "$(sg_current_branch)")
    fi

    # Validate refs
    if ! git rev-parse --verify "$ref1" &>/dev/null; then
        sg_die "Invalid ref: $ref1"
    fi
    if ! git rev-parse --verify "$ref2" &>/dev/null; then
        sg_die "Invalid ref: $ref2"
    fi

    sg_header "Comparing $ref1 .. $ref2"

    # Summary stats
    local stats
    stats="$(git diff --shortstat "$ref1..$ref2" 2>/dev/null || echo "No differences")"
    printf "${_C_BOLD}Summary:${_C_RESET} %s\n\n" "$stats"

    # Commit count
    local commit_count
    commit_count=$(git rev-list --count "$ref1..$ref2" 2>/dev/null || echo 0)
    printf "${_C_BOLD}Commits:${_C_RESET} %s\n\n" "$commit_count"

    # Files changed
    sg_info "Files changed:"
    git diff --name-status "$ref1..$ref2" 2>/dev/null | while IFS=$'\t' read -r status file; do
        local color=""
        case "$status" in
            A)  color="${_C_GREEN}" ;;
            D)  color="${_C_RED}" ;;
            M)  color="${_C_YELLOW}" ;;
            R*) color="${_C_CYAN}" ;;
            *)  color="" ;;
        esac
        printf "  ${color}%-5s${_C_RESET} %s\n" "$status" "$file"
    done

    echo
    local view_choice
    view_choice=$(sg_menu "View Options" \
        "Full diff" \
        "Stat only (compact)" \
        "File-by-file diff" \
        "Word-level diff" \
        "Commit log between refs" \
        "Back")

    case "$view_choice" in
        1)
            if _has_delta; then
                git diff "$ref1..$ref2" | delta
            else
                _sg_cmd diff "$ref1..$ref2" 2>/dev/null || git diff "$ref1..$ref2"
            fi
            ;;
        2)
            git diff --stat "$ref1..$ref2"
            ;;
        3)
            _file_by_file_diff "$ref1" "$ref2"
            ;;
        4)
            _word_diff "$ref1" "$ref2"
            ;;
        5)
            git log --oneline "$ref1..$ref2"
            ;;
        6) return ;;
    esac
}

_file_by_file_diff() {
    local ref1="$1" ref2="$2"

    local files
    files="$(git diff --name-only "$ref1..$ref2" 2>/dev/null)"

    if [[ -z "$files" ]]; then
        sg_info "No differences between $ref1 and $ref2."
        return
    fi

    local file_arr=()
    while IFS= read -r f; do
        [[ -n "$f" ]] && file_arr+=("$f")
    done <<< "$files"

    sg_info "Select a file to view diff:"
    local i
    for i in "${!file_arr[@]}"; do
        printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((i + 1))" "${file_arr[$i]}"
    done
    echo

    local file_choice
    while true; do
        printf "Select [1-%d, or 'q' to quit]: " "${#file_arr[@]}"
        read -r file_choice
        [[ "$file_choice" == "q" ]] && return

        if [[ "$file_choice" =~ ^[0-9]+$ ]] && (( file_choice >= 1 && file_choice <= ${#file_arr[@]} )); then
            local selected_file="${file_arr[$((file_choice - 1))]}"
            sg_header "Diff: $selected_file"
            if _has_delta; then
                git diff "$ref1..$ref2" -- "$selected_file" | delta
            else
                git diff "$ref1..$ref2" -- "$selected_file"
            fi
        else
            sg_warn "Invalid selection."
        fi
    done
}

# ─── Word-level diff ────────────────────────────────────────────────────────

_word_diff() {
    local ref1="${1:-}" ref2="${2:-}"

    sg_header "Word-Level Diff"
    sg_info "Showing inline word changes (useful for documentation)."
    echo

    if [[ -z "$ref1" && -z "$ref2" ]]; then
        # Working tree vs index
        git diff --word-diff=color --word-diff-regex='[^[:space:]]+' 2>/dev/null \
            || git diff --word-diff
    elif [[ -z "$ref2" ]]; then
        git diff --word-diff=color --word-diff-regex='[^[:space:]]+' "$ref1" 2>/dev/null \
            || git diff --word-diff "$ref1"
    else
        git diff --word-diff=color --word-diff-regex='[^[:space:]]+' "$ref1..$ref2" 2>/dev/null \
            || git diff --word-diff "$ref1..$ref2"
    fi
}

# ─── Patch management ───────────────────────────────────────────────────────

_create_patch() {
    sg_header "Create Patch"

    local patch_choice
    patch_choice=$(sg_menu "Patch Source" \
        "From staged changes" \
        "From unstaged changes" \
        "From commit range" \
        "From branch comparison" \
        "From specific commits (format-patch)")

    local root
    root="$(git rev-parse --show-toplevel)"
    local patch_dir="$root"
    local timestamp
    timestamp="$(date +%Y%m%d-%H%M%S)"

    case "$patch_choice" in
        1)  # Staged
            local patch_file="$patch_dir/staged-$timestamp.patch"
            git diff --cached > "$patch_file"
            if [[ -s "$patch_file" ]]; then
                sg_success "Patch created: $patch_file"
                printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$patch_file" | cut -f1)"
            else
                rm -f "$patch_file"
                sg_info "No staged changes to create patch from."
            fi
            ;;

        2)  # Unstaged
            local patch_file="$patch_dir/unstaged-$timestamp.patch"
            git diff > "$patch_file"
            if [[ -s "$patch_file" ]]; then
                sg_success "Patch created: $patch_file"
                printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$patch_file" | cut -f1)"
            else
                rm -f "$patch_file"
                sg_info "No unstaged changes to create patch from."
            fi
            ;;

        3)  # Commit range
            local range_start range_end
            range_start=$(sg_prompt "Start ref (e.g., HEAD~5, v1.0.0)")
            range_end=$(sg_prompt "End ref" "HEAD")
            local patch_file="$patch_dir/range-${range_start//\//-}-$timestamp.patch"
            git diff "$range_start..$range_end" > "$patch_file"
            if [[ -s "$patch_file" ]]; then
                sg_success "Patch created: $patch_file"
                printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$patch_file" | cut -f1)"
            else
                rm -f "$patch_file"
                sg_info "No differences in specified range."
            fi
            ;;

        4)  # Branch comparison
            local branch1 branch2
            branch1=$(sg_prompt "Base branch" "$(sg_default_branch)")
            branch2=$(sg_prompt "Compare branch" "$(sg_current_branch)")
            local patch_file="$patch_dir/branch-${branch2//\//-}-$timestamp.patch"
            git diff "$branch1..$branch2" > "$patch_file"
            if [[ -s "$patch_file" ]]; then
                sg_success "Patch created: $patch_file"
                printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$patch_file" | cut -f1)"
            else
                rm -f "$patch_file"
                sg_info "No differences between branches."
            fi
            ;;

        5)  # format-patch (individual commit patches)
            local ref
            ref=$(sg_prompt "Base ref (creates patches for commits after this)" "$(sg_default_branch)")
            local output_dir="$patch_dir/patches-$timestamp"
            mkdir -p "$output_dir"
            local count
            count=$(git format-patch -o "$output_dir" "$ref" 2>/dev/null | wc -l)
            if [[ "$count" -gt 0 ]]; then
                sg_success "Created $count patch file(s) in $output_dir/"
                ls -1 "$output_dir/"
            else
                rmdir "$output_dir" 2>/dev/null || true
                sg_info "No commits to create patches from."
            fi
            ;;
    esac
}

_apply_patch() {
    sg_header "Apply Patch"

    local patch_file
    patch_file=$(sg_prompt "Path to patch file")

    if [[ ! -f "$patch_file" ]]; then
        sg_die "Patch file not found: $patch_file"
    fi

    sg_info "Patch file: $patch_file"
    printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$patch_file" | cut -f1)"
    echo

    # Dry run first
    sg_info "Checking if patch applies cleanly..."
    if git apply --check "$patch_file" 2>/dev/null; then
        sg_success "Patch applies cleanly."
    else
        sg_error "Patch has conflicts."
        sg_info "Attempting three-way merge check..."
        if git apply --check --3way "$patch_file" 2>/dev/null; then
            sg_warn "Patch can be applied with 3-way merge."
        else
            sg_error "Patch cannot be applied. Manual resolution required."
            return 1
        fi
    fi

    # Show patch stats
    sg_info "Patch statistics:"
    git apply --stat "$patch_file" 2>/dev/null
    echo

    local apply_choice
    apply_choice=$(sg_menu "Apply Method" \
        "Apply (git apply)" \
        "Apply with 3-way merge (git apply --3way)" \
        "Apply as commits (git am)" \
        "Preview only (no changes)" \
        "Cancel")

    case "$apply_choice" in
        1)
            if git apply "$patch_file"; then
                sg_success "Patch applied successfully."
                sg_undo_available
            else
                sg_error "Failed to apply patch."
            fi
            ;;
        2)
            if git apply --3way "$patch_file"; then
                sg_success "Patch applied with 3-way merge."
                sg_undo_available
            else
                sg_error "Failed to apply patch. Resolve conflicts manually."
            fi
            ;;
        3)
            if git am "$patch_file" 2>/dev/null; then
                sg_success "Patch applied as commit(s)."
                sg_undo_available
            else
                sg_error "Failed to apply patch. Run 'git am --abort' to cancel."
            fi
            ;;
        4)
            sg_info "Preview (no changes applied):"
            git apply --stat "$patch_file"
            ;;
        5)
            sg_info "Cancelled."
            ;;
    esac
}

# ─── Complexity analysis ────────────────────────────────────────────────────

_complexity_analysis() {
    local ref1="${1:-}" ref2="${2:-}"

    sg_header "Change Complexity Analysis"

    # Determine what to analyze
    if [[ -z "$ref1" ]]; then
        local analysis_choice
        analysis_choice=$(sg_menu "Analyze Changes" \
            "Staged changes" \
            "Unstaged changes" \
            "Current branch vs default branch" \
            "Custom ref comparison")

        case "$analysis_choice" in
            1) ref1="--cached"; ref2="" ;;
            2) ref1=""; ref2="" ;;
            3) ref1="${SG_PRIMARY_REMOTE:-origin}/$(sg_default_branch)"; ref2="HEAD" ;;
            4)
                ref1=$(sg_prompt "Base ref")
                ref2=$(sg_prompt "Compare ref" "HEAD")
                ;;
        esac
    fi

    # Compute stats
    local diff_args=""
    if [[ "$ref1" == "--cached" ]]; then
        diff_args="--cached"
    elif [[ -n "$ref1" && -n "$ref2" ]]; then
        diff_args="$ref1..$ref2"
    elif [[ -n "$ref1" ]]; then
        diff_args="$ref1"
    fi

    local numstat
    numstat="$(git diff --numstat $diff_args 2>/dev/null || echo "")"

    if [[ -z "$numstat" ]]; then
        sg_info "No changes to analyze."
        return
    fi

    # Parse statistics
    local total_files=0 total_insertions=0 total_deletions=0
    local max_file="" max_churn=0

    # Track file types
    declare -A type_counts
    declare -A type_insertions
    declare -A type_deletions

    sg_info "Per-file breakdown:"
    sg_divider

    printf "  ${_C_BOLD}%-50s %8s %8s %8s${_C_RESET}\n" "File" "+Lines" "-Lines" "Churn"
    sg_divider

    while IFS=$'\t' read -r ins del file; do
        [[ -z "$file" ]] && continue
        # Binary files show "-" for stats
        [[ "$ins" == "-" ]] && ins=0
        [[ "$del" == "-" ]] && del=0

        total_files=$((total_files + 1))
        total_insertions=$((total_insertions + ins))
        total_deletions=$((total_deletions + del))

        local churn=$((ins + del))
        if (( churn > max_churn )); then
            max_churn=$churn
            max_file="$file"
        fi

        # Color based on churn
        local color=""
        if (( churn > 200 )); then
            color="${_C_RED}"
        elif (( churn > 50 )); then
            color="${_C_YELLOW}"
        else
            color="${_C_GREEN}"
        fi

        printf "  ${color}%-50s %+8d %8d %8d${_C_RESET}\n" \
            "$(echo "$file" | tail -c 50)" "$ins" "-$del" "$churn"

        # Track by file type
        local ext
        ext="${file##*.}"
        [[ "$ext" == "$file" ]] && ext="(no ext)"
        type_counts["$ext"]=$(( ${type_counts["$ext"]:-0} + 1 ))
        type_insertions["$ext"]=$(( ${type_insertions["$ext"]:-0} + ins ))
        type_deletions["$ext"]=$(( ${type_deletions["$ext"]:-0} + del ))
    done <<< "$numstat"

    sg_divider
    printf "  ${_C_BOLD}%-50s %+8d %8d %8d${_C_RESET}\n" \
        "TOTAL" "$total_insertions" "-$total_deletions" "$((total_insertions + total_deletions))"
    echo

    # Summary metrics
    sg_header "Complexity Metrics"

    printf "  ${_C_BOLD}Files changed:${_C_RESET}    %d\n" "$total_files"
    printf "  ${_C_BOLD}Insertions:${_C_RESET}       %d\n" "$total_insertions"
    printf "  ${_C_BOLD}Deletions:${_C_RESET}        %d\n" "$total_deletions"
    printf "  ${_C_BOLD}Total churn:${_C_RESET}      %d\n" "$((total_insertions + total_deletions))"
    printf "  ${_C_BOLD}Net change:${_C_RESET}       %+d\n" "$((total_insertions - total_deletions))"
    echo

    if [[ -n "$max_file" ]]; then
        printf "  ${_C_BOLD}Hotspot:${_C_RESET}          %s (%d lines churned)\n" "$max_file" "$max_churn"
    fi

    # Churn risk assessment
    local total_churn=$((total_insertions + total_deletions))
    local max_diff="${SG_MAX_DIFF_LINES:-200}"
    echo
    if (( total_churn > max_diff * 3 )); then
        sg_error "HIGH complexity: $total_churn lines (${max_diff}x3 threshold). Strongly consider splitting."
    elif (( total_churn > max_diff )); then
        sg_warn "MODERATE complexity: $total_churn lines (over $max_diff threshold). Consider splitting."
    else
        sg_success "LOW complexity: $total_churn lines (under $max_diff threshold). Good size."
    fi

    # File type breakdown
    if [[ ${#type_counts[@]} -gt 1 ]]; then
        echo
        sg_info "Changes by file type:"
        for ext in $(echo "${!type_counts[@]}" | tr ' ' '\n' | sort); do
            printf "  ${_C_DIM}.%-10s${_C_RESET} %3d file(s)  +%-6d -%d\n" \
                "$ext" "${type_counts[$ext]}" "${type_insertions[$ext]}" "${type_deletions[$ext]}"
        done
    fi
}

# ─── Side-by-side diff ──────────────────────────────────────────────────────

_side_by_side_diff() {
    local ref1="${1:-}" ref2="${2:-}"

    sg_header "Side-by-Side Diff"

    if _has_delta; then
        sg_info "Using delta for side-by-side view."
        if [[ -z "$ref1" ]]; then
            git diff | delta --side-by-side
        elif [[ -z "$ref2" ]]; then
            git diff "$ref1" | delta --side-by-side
        else
            git diff "$ref1..$ref2" | delta --side-by-side
        fi
    else
        # Fall back to system diff with --side-by-side if available, or git's own
        local width
        width=$(tput cols 2>/dev/null || echo 120)

        sg_info "Using git diff with diffstat. Install 'delta' for better side-by-side display."
        sg_info "  brew install git-delta / cargo install git-delta"
        echo

        if [[ -z "$ref1" ]]; then
            git diff --stat --color
            echo
            git diff --color
        elif [[ -z "$ref2" ]]; then
            git diff --stat --color "$ref1"
            echo
            git diff --color "$ref1"
        else
            git diff --stat --color "$ref1..$ref2"
            echo
            git diff --color "$ref1..$ref2"
        fi
    fi
}

# ─── HTML diff export ───────────────────────────────────────────────────────

_export_html_diff() {
    sg_header "Export Diff as HTML"

    local ref1 ref2
    ref1=$(sg_prompt "Base ref (or press Enter for working tree)" "")
    ref2=$(sg_prompt "Compare ref (or press Enter for HEAD)" "")

    local root
    root="$(git rev-parse --show-toplevel)"
    local timestamp
    timestamp="$(date +%Y%m%d-%H%M%S)"
    local output_file="$root/diff-report-$timestamp.html"

    # Get raw diff
    local diff_content
    if [[ -z "$ref1" && -z "$ref2" ]]; then
        diff_content="$(git diff --cached 2>/dev/null; git diff 2>/dev/null)"
    elif [[ -z "$ref2" ]]; then
        diff_content="$(git diff "$ref1" 2>/dev/null)"
    else
        diff_content="$(git diff "$ref1..$ref2" 2>/dev/null)"
    fi

    if [[ -z "$diff_content" ]]; then
        sg_info "No differences to export."
        return
    fi

    # Get stats
    local stat_content
    if [[ -z "$ref1" && -z "$ref2" ]]; then
        stat_content="$(git diff --cached --stat 2>/dev/null; git diff --stat 2>/dev/null)"
    elif [[ -z "$ref2" ]]; then
        stat_content="$(git diff --stat "$ref1" 2>/dev/null)"
    else
        stat_content="$(git diff --stat "$ref1..$ref2" 2>/dev/null)"
    fi

    local repo_name
    repo_name="$(basename "$root")"
    local ref_desc
    if [[ -z "$ref1" && -z "$ref2" ]]; then
        ref_desc="Working tree changes"
    elif [[ -z "$ref2" ]]; then
        ref_desc="$ref1 vs working tree"
    else
        ref_desc="$ref1 .. $ref2"
    fi

    # Generate HTML
    cat > "$output_file" <<HTMLEOF
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Diff Report - $repo_name</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, monospace; margin: 2rem; background: #0d1117; color: #c9d1d9; }
        h1 { color: #58a6ff; border-bottom: 1px solid #30363d; padding-bottom: 0.5rem; }
        h2 { color: #8b949e; }
        .meta { color: #8b949e; margin-bottom: 1rem; }
        .stats { background: #161b22; padding: 1rem; border-radius: 6px; margin-bottom: 1.5rem; white-space: pre-wrap; font-family: monospace; }
        .diff { background: #161b22; padding: 1rem; border-radius: 6px; overflow-x: auto; white-space: pre-wrap; font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; font-size: 13px; line-height: 1.5; }
        .diff .add { color: #3fb950; background: rgba(63, 185, 80, 0.1); }
        .diff .del { color: #f85149; background: rgba(248, 81, 73, 0.1); }
        .diff .hunk { color: #79c0ff; font-weight: bold; }
        .diff .file { color: #d2a8ff; font-weight: bold; }
    </style>
</head>
<body>
    <h1>Diff Report: $repo_name</h1>
    <div class="meta">
        <p>Generated: $(date -u)</p>
        <p>Comparison: $ref_desc</p>
        <p>Branch: $(sg_current_branch)</p>
    </div>

    <h2>Statistics</h2>
    <div class="stats">$(echo "$stat_content" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')</div>

    <h2>Changes</h2>
    <div class="diff">$(echo "$diff_content" | sed \
        -e 's/&/\&amp;/g' \
        -e 's/</\&lt;/g' \
        -e 's/>/\&gt;/g' \
        -e 's|^+\(.*\)$|<span class="add">+\1</span>|' \
        -e 's|^-\(.*\)$|<span class="del">-\1</span>|' \
        -e 's|^@@\(.*\)@@|<span class="hunk">@@\1@@</span>|' \
        -e 's|^diff --git\(.*\)|<span class="file">diff --git\1</span>|'
    )</div>
</body>
</html>
HTMLEOF

    sg_success "HTML diff report exported: $output_file"
    printf "  ${_C_DIM}Size: %s${_C_RESET}\n" "$(du -h "$output_file" | cut -f1)"

    # Try to open in browser
    if command -v xdg-open &>/dev/null; then
        if sg_confirm "Open in browser?" "y"; then
            xdg-open "$output_file" &>/dev/null &
        fi
    elif command -v open &>/dev/null; then
        if sg_confirm "Open in browser?" "y"; then
            open "$output_file" &>/dev/null &
        fi
    fi
}

# ─── Files changed between refs ─────────────────────────────────────────────

_files_changed() {
    sg_header "Files Changed Between Refs"

    local ref1 ref2
    ref1=$(sg_prompt "First ref" "$(sg_default_branch)")
    ref2=$(sg_prompt "Second ref" "$(sg_current_branch)")

    if ! git rev-parse --verify "$ref1" &>/dev/null; then
        sg_die "Invalid ref: $ref1"
    fi
    if ! git rev-parse --verify "$ref2" &>/dev/null; then
        sg_die "Invalid ref: $ref2"
    fi

    sg_info "Files changed between $ref1 and $ref2:"
    echo

    local added=0 modified=0 deleted=0 renamed=0

    git diff --name-status "$ref1..$ref2" 2>/dev/null | while IFS=$'\t' read -r status file extra; do
        case "$status" in
            A)
                printf "  ${_C_GREEN}[ADDED]${_C_RESET}    %s\n" "$file"
                ;;
            M)
                printf "  ${_C_YELLOW}[MODIFIED]${_C_RESET} %s\n" "$file"
                ;;
            D)
                printf "  ${_C_RED}[DELETED]${_C_RESET}  %s\n" "$file"
                ;;
            R*)
                printf "  ${_C_CYAN}[RENAMED]${_C_RESET}  %s -> %s\n" "$file" "$extra"
                ;;
            C*)
                printf "  ${_C_BLUE}[COPIED]${_C_RESET}   %s -> %s\n" "$file" "$extra"
                ;;
            *)
                printf "  [%s] %s\n" "$status" "$file"
                ;;
        esac
    done

    echo
    git diff --shortstat "$ref1..$ref2" 2>/dev/null
}

# ─── Interactive comparison picker ──────────────────────────────────────────

_interactive_compare() {
    sg_header "Interactive Comparison"

    # List available branches and recent tags
    sg_info "Available branches:"
    local branches
    branches="$(git branch --format='%(refname:short)' 2>/dev/null | head -20)"
    local branch_arr=()
    while IFS= read -r b; do
        [[ -n "$b" ]] && branch_arr+=("$b")
    done <<< "$branches"

    local i
    for i in "${!branch_arr[@]}"; do
        local marker=""
        [[ "${branch_arr[$i]}" == "$(sg_current_branch)" ]] && marker=" ${_C_GREEN}(current)${_C_RESET}"
        printf "  ${_C_BOLD}%d)${_C_RESET} %s%s\n" "$((i + 1))" "${branch_arr[$i]}" "$marker"
    done

    echo
    sg_info "Recent tags:"
    local tags
    tags="$(git tag -l --sort=-version:refname 2>/dev/null | head -10)"
    if [[ -n "$tags" ]]; then
        local tag_arr=()
        while IFS= read -r t; do
            [[ -n "$t" ]] && tag_arr+=("$t")
        done <<< "$tags"
        local offset="${#branch_arr[@]}"
        for i in "${!tag_arr[@]}"; do
            printf "  ${_C_BOLD}%d)${_C_RESET} %s\n" "$((i + offset + 1))" "${tag_arr[$i]}"
        done
    fi

    echo
    local ref1 ref2

    ref1=$(sg_prompt "First ref (number or name)" "$(sg_default_branch)")
    # Resolve number to name
    if [[ "$ref1" =~ ^[0-9]+$ ]]; then
        local total_arr=("${branch_arr[@]}" ${tag_arr[@]+"${tag_arr[@]}"})
        if (( ref1 >= 1 && ref1 <= ${#total_arr[@]} )); then
            ref1="${total_arr[$((ref1 - 1))]}"
        fi
    fi

    ref2=$(sg_prompt "Second ref (number or name)" "$(sg_current_branch)")
    if [[ "$ref2" =~ ^[0-9]+$ ]]; then
        local total_arr=("${branch_arr[@]}" ${tag_arr[@]+"${tag_arr[@]}"})
        if (( ref2 >= 1 && ref2 <= ${#total_arr[@]} )); then
            ref2="${total_arr[$((ref2 - 1))]}"
        fi
    fi

    _compare_refs "$ref1" "$ref2"
}

# ─── Main ────────────────────────────────────────────────────────────────────

main() {
    sg_require_repo

    # Handle direct arguments
    case "${1:-}" in
        staged)
            _show_diff_staged
            exit 0
            ;;
        unstaged)
            _show_diff_unstaged
            exit 0
            ;;
        compare)
            _compare_refs "${2:-}" "${3:-}"
            exit 0
            ;;
        complexity)
            _complexity_analysis "${2:-}" "${3:-}"
            exit 0
            ;;
        patch)
            case "${2:-}" in
                create) _create_patch ;;
                apply)  _apply_patch "${3:-}" ;;
                *)      echo "Usage: $0 patch [create|apply FILE]" ;;
            esac
            exit 0
            ;;
        --help|-h)
            echo "Usage: $0 [staged|unstaged|compare REF1 REF2|complexity|patch create|apply FILE|--help]"
            echo
            echo "Commands:"
            echo "  staged          Show staged changes"
            echo "  unstaged        Show unstaged changes"
            echo "  compare R1 R2   Compare two refs"
            echo "  complexity      Analyze change complexity"
            echo "  patch create    Create a patch file"
            echo "  patch apply F   Apply a patch file"
            exit 0
            ;;
    esac

    # Interactive menu
    sg_info "Diff tool: $(_diff_tool_name)"
    echo

    while true; do
        local choice
        choice=$(sg_menu "Diff & Review Tools" \
            "Show staged diff" \
            "Show unstaged diff" \
            "Compact diff overview" \
            "Compare branches/tags/commits" \
            "Interactive comparison picker" \
            "Word-level diff (documentation)" \
            "Side-by-side diff" \
            "Change complexity analysis" \
            "Create patch file" \
            "Apply patch file" \
            "Export diff as HTML report" \
            "Files changed between refs" \
            "Exit")

        case "$choice" in
            1)  _show_diff_staged ;;
            2)  _show_diff_unstaged ;;
            3)
                local compact_ref
                compact_ref=$(sg_prompt "Ref to compare against (or press Enter for staged)" "")
                _show_diff_compact "$compact_ref"
                ;;
            4)  _compare_refs ;;
            5)  _interactive_compare ;;
            6)
                local wref1 wref2
                wref1=$(sg_prompt "First ref (or press Enter for working tree)" "")
                wref2=$(sg_prompt "Second ref (or press Enter for none)" "")
                _word_diff "$wref1" "$wref2"
                ;;
            7)
                local sref1 sref2
                sref1=$(sg_prompt "First ref (or press Enter for working tree)" "")
                sref2=$(sg_prompt "Second ref (or press Enter for none)" "")
                _side_by_side_diff "$sref1" "$sref2"
                ;;
            8)  _complexity_analysis ;;
            9)  _create_patch ;;
            10) _apply_patch ;;
            11) _export_html_diff ;;
            12) _files_changed ;;
            13)
                sg_success "Done."
                exit 0
                ;;
        esac

        echo
    done
}

main "$@"
