{% extends "base.html" %}

{% block title %}Consolidation - {% if current_project == all_projects_value %}All Projects{% else %}{{ current_project|display_name }}{% endif %} - CodeContext{% endblock %}

{% block content %}
<div class="consolidation-page">
    <h1>Group Consolidation{% if current_project == all_projects_value %} - All Projects{% endif %}</h1>
    <p class="page-description">
        Find and merge clusters of semantically similar memories to reduce duplicates.
    </p>

    <!-- View Tabs -->
    <div class="conflict-tabs">
        <a href="/consolidation?project={{ current_project }}&view=scan"
           class="conflict-tab {% if current_view == 'scan' %}active{% endif %}">
            Scan
        </a>
        <a href="/consolidation?project={{ current_project }}&view=history"
           class="conflict-tab {% if current_view == 'history' %}active{% endif %}">
            History
            {% if history_entries|length > 0 %}
            <span class="tab-badge">{{ history_entries|length }}</span>
            {% endif %}
        </a>
    </div>

    {% if current_view == 'scan' %}
    <!-- Auto-Consolidation Settings Panel -->
    <div class="auto-consolidation-settings">
        <div class="settings-toggle-row">
            <label class="toggle-switch">
                <input type="checkbox" id="auto-consolidation-toggle" onchange="updateConsolidationSettings()">
                <span class="toggle-slider"></span>
            </label>
            <span class="setting-label">Auto-Consolidation</span>
            <span class="setting-hint">(runs on session start/end)</span>

            <select id="consolidation-mode" class="mode-select" onchange="updateConsolidationSettings()" style="display: none;">
                <option value="session">Session</option>
                <option value="periodic">Periodic</option>
                <option value="both">Both</option>
            </select>

            <select id="periodic-interval" class="interval-select" onchange="updateConsolidationSettings()" style="display: none;">
                <option value="5">5 min</option>
                <option value="15">15 min</option>
                <option value="30">30 min</option>
                <option value="60">1 hour</option>
            </select>
        </div>
    </div>

    <div class="stats-grid" id="stats-grid">
        <div class="stat-card">
            <div class="stat-value" id="cluster-count">{{ clusters|length if clusters else 0 }}</div>
            <div class="stat-label">Clusters Found</div>
        </div>
        <div class="stat-card">
            <div class="stat-value" id="memory-count">{{ total_memories }}</div>
            <div class="stat-label">Memories in Clusters</div>
        </div>
        <div class="stat-card">
            <div class="stat-value">{{ info.memory_count if info else 0 }}</div>
            <div class="stat-label">Total Memories</div>
        </div>
        <div class="stat-card">
            <div class="stat-value">{{ info.device|upper if info else 'CPU' }}</div>
            <div class="stat-label">Device</div>
        </div>
    </div>

    <!-- Progress Indicator (hidden by default) -->
    <div id="progress-container" class="progress-container" style="display: none;">
        <div class="progress-header">
            <span class="progress-phase" id="progress-phase">Initializing...</span>
            <span class="progress-time" id="progress-time"></span>
        </div>
        <div class="progress-bar-wrapper">
            <div class="progress-bar" id="progress-bar"></div>
        </div>
        <div class="progress-detail" id="progress-detail">Preparing to analyze clusters...</div>
    </div>

    <!-- Controls -->
    <div class="consolidation-controls">
        <div class="control-group">
            <label for="threshold">Distance Threshold:</label>
            <input type="range" id="threshold" min="0.3" max="0.65" step="0.05" value="{{ threshold }}"
                   oninput="document.getElementById('threshold-value').textContent = this.value; saveThreshold(this.value)">
            <span id="threshold-value">{{ threshold }}</span>
            <span class="threshold-hint">(lower = stricter matching)</span>
        </div>

        <div class="control-buttons">
            <button id="scan-btn" class="btn btn-secondary" onclick="scanClusters()">
                <span class="btn-text">Scan for Clusters</span>
                <span class="btn-spinner" style="display: none;">
                    <span class="spinner"></span>
                    <span>Scanning...</span>
                </span>
            </button>

            {% if clusters and clusters|length > 0 and current_project != all_projects_value %}
            <button id="consolidate-btn" class="btn btn-primary" onclick="runConsolidation()">
                <span class="btn-text">Consolidate</span>
                <span class="btn-spinner" style="display: none;">
                    <span class="spinner"></span>
                    <span class="btn-progress">Analyzing...</span>
                </span>
            </button>
            {% elif current_project == all_projects_value %}
            <button class="btn btn-primary" disabled title="Select a specific project to run consolidation">
                Consolidate (Select Project)
            </button>
            {% endif %}
        </div>
    </div>

    <!-- Tier Summary -->
    {% if tiers %}
    <div class="tier-summary">
        <span class="tier-item tier-auto" title="Can be auto-resolved without LLM">
            Auto: {{ tiers.auto }}
        </span>
        <span class="tier-item tier-llm-small" title="Small clusters (2-5) for LLM">
            LLM Small: {{ tiers.llm_small }}
        </span>
        <span class="tier-item tier-llm-large" title="Large clusters (5+) for LLM">
            LLM Large: {{ tiers.llm_large }}
        </span>
    </div>
    {% endif %}

    <!-- Cluster List -->
    <div class="cluster-list" id="cluster-list">
        {% if clusters %}
        {% for cluster in clusters %}
        <div class="cluster-card" data-cluster-id="{{ cluster.id }}">
            <div class="cluster-header">
                <span class="cluster-id">{{ cluster.id }}</span>
                <span class="cluster-size">{{ cluster.size }} memories</span>
                {% if cluster.project %}
                <span class="project-tag">{{ cluster.project|display_name }}</span>
                {% endif %}
                <span class="cluster-distance" title="Average distance between memories">
                    Avg Distance: {{ "%.3f"|format(cluster.avg_distance) }}
                </span>
                <button class="btn btn-sm btn-expand" onclick="toggleCluster('{{ cluster.id }}')">
                    <span class="expand-icon">+</span>
                </button>
            </div>

            <div class="cluster-memories" id="memories-{{ cluster.id }}" style="display: none;">
                {% for mem in cluster.memories %}
                <div class="cluster-memory type-{{ mem.type }}">
                    <div class="memory-header">
                        <span class="type-badge type-{{ mem.type }}">{{ mem.type }}</span>
                        <span class="memory-id">{{ mem.id }}</span>
                        {% if mem.created_at %}
                        <span class="memory-date" data-utc-time="{{ mem.created_at }}">{{ mem.created_at | format_datetime }}</span>
                        {% endif %}
                    </div>
                    <h4 class="memory-title">{{ mem.title }}</h4>
                    <p class="memory-fact">{{ mem.fact }}</p>
                    {% if mem.files %}
                    <div class="memory-files">
                        {% for f in mem.files %}
                        <code>{{ f }}</code>
                        {% endfor %}
                    </div>
                    {% endif %}
                </div>
                {% endfor %}
            </div>
        </div>
        {% endfor %}
        {% else %}
        <div class="empty-state" id="empty-state">
            <p>No clusters found. Click "Scan for Clusters" to search for similar memories.</p>
        </div>
        {% endif %}
    </div>
    {% endif %}

    {% if current_view == 'history' %}
    <div class="consolidation-history">
        {% if history_entries %}
        <div class="history-list">
            {% for entry in history_entries %}
            <div class="history-card">
                <div class="history-card-header">
                    <span class="history-status-badge">COMPLETED</span>
                    <span class="history-project">{{ entry.project|display_name }}</span>
                    <span class="history-timestamp" data-utc-time="{{ entry.timestamp }}">{{ entry.timestamp[:19].replace('T', ' ') if entry.timestamp else '' }}</span>
                    <div class="history-stats">
                        <span class="stat-badge stat-clusters">{{ entry.clusters_processed }} clusters</span>
                        <span class="stat-badge stat-merged">{{ entry.consolidated }} merged</span>
                        <span class="stat-badge stat-kept">{{ entry.kept }} kept</span>
                        <span class="stat-badge stat-deleted">{{ entry.deleted }} deleted</span>
                    </div>
                </div>
                {% if entry.results %}
                <div class="history-card-body">
                    {% for result in entry.results %}
                    <div class="history-result">
                        <span class="decision-badge decision-{{ result.decision }}">{{ result.decision }}</span>
                        <span class="history-reasoning">{{ result.reasoning }}</span>
                        {% if result.decision == 'merge' and result.merged_memory %}
                        <div class="history-merged">
                            <strong>Merged to:</strong> {{ result.merged_memory.title }}
                        </div>
                        {% endif %}
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
            </div>
            {% endfor %}
        </div>
        {% else %}
        <div class="empty-state">
            <p>No consolidation history yet.</p>
            <p>Run a consolidation to see results here.</p>
        </div>
        {% endif %}
    </div>
    {% endif %}
</div>

<!-- Consolidation Preview Modal -->
<div id="consolidation-modal" class="modal" style="display: none;">
    <div class="modal-backdrop" onclick="closeConsolidationModal()"></div>
    <div class="modal-content modal-large">
        <div class="modal-header">
            <h3>Preview Consolidation Decisions</h3>
            <button class="modal-close" onclick="closeConsolidationModal()">&times;</button>
        </div>
        <div class="modal-body">
            <p class="preview-summary">
                Claude analyzed <span id="decision-count">0</span> clusters. Review decisions below:
            </p>
            <div id="consolidation-decisions" class="preview-list">
                <!-- Dynamically populated -->
            </div>
        </div>
        <div class="modal-footer">
            <button class="btn btn-secondary" onclick="closeConsolidationModal()">Cancel</button>
            <button id="apply-consolidation-btn" class="btn btn-primary" onclick="applyConsolidation()">
                Apply (<span id="apply-decision-count">0</span>)
            </button>
        </div>
    </div>
</div>

<script>
const currentProject = '{{ current_project }}';
const allProjectsValue = '{{ all_projects_value }}';
const isAllProjects = currentProject === allProjectsValue;
const totalClusters = {{ clusters|length if clusters else 0 }};
let pendingResults = [];
let progressStartTime = null;
let progressInterval = null;

// Threshold persistence
function saveThreshold(value) {
    localStorage.setItem('consolidation_threshold', value);
}

function loadThreshold() {
    return localStorage.getItem('consolidation_threshold') || '0.55';
}

// Progress management
function showProgress(phase, detail, percent) {
    const container = document.getElementById('progress-container');
    const phaseEl = document.getElementById('progress-phase');
    const detailEl = document.getElementById('progress-detail');
    const barEl = document.getElementById('progress-bar');
    const statsGrid = document.getElementById('stats-grid');

    container.style.display = 'block';
    phaseEl.textContent = phase;
    detailEl.textContent = detail;
    barEl.style.width = `${percent}%`;

    // Add pulsing effect to stats
    statsGrid.classList.add('processing');
}

function hideProgress() {
    const container = document.getElementById('progress-container');
    const statsGrid = document.getElementById('stats-grid');

    container.style.display = 'none';
    statsGrid.classList.remove('processing');

    if (progressInterval) {
        clearInterval(progressInterval);
        progressInterval = null;
    }
}

function updateElapsedTime() {
    if (!progressStartTime) return;

    const elapsed = Math.floor((Date.now() - progressStartTime) / 1000);
    const timeEl = document.getElementById('progress-time');

    if (elapsed < 60) {
        timeEl.textContent = `${elapsed}s`;
    } else {
        const mins = Math.floor(elapsed / 60);
        const secs = elapsed % 60;
        timeEl.textContent = `${mins}m ${secs}s`;
    }
}

function startProgressTimer() {
    progressStartTime = Date.now();
    progressInterval = setInterval(updateElapsedTime, 1000);
}

function toggleCluster(clusterId) {
    const memories = document.getElementById('memories-' + clusterId);
    const btn = document.querySelector(`[data-cluster-id="${clusterId}"] .expand-icon`);

    if (memories.style.display === 'none') {
        memories.style.display = 'block';
        btn.textContent = '-';
    } else {
        memories.style.display = 'none';
        btn.textContent = '+';
    }
}

async function scanClusters() {
    const btn = document.getElementById('scan-btn');
    const btnText = btn.querySelector('.btn-text');
    const btnSpinner = btn.querySelector('.btn-spinner');
    const threshold = document.getElementById('threshold').value;

    btn.disabled = true;
    btnText.style.display = 'none';
    btnSpinner.style.display = 'inline-flex';

    showProgress('Scanning', 'Searching for similar memory clusters...', 30);
    startProgressTimer();

    try {
        const response = await fetch(
            `/api/consolidation/scan?project=${encodeURIComponent(currentProject)}&threshold=${threshold}`
        );
        const data = await response.json();

        if (response.ok) {
            showProgress('Complete', `Found ${data.total_clusters} clusters`, 100);
            // Reload page with scan=true to trigger server-side scanning
            setTimeout(() => {
                window.location.href = `/consolidation?project=${encodeURIComponent(currentProject)}&threshold=${threshold}&scan=true`;
            }, 500);
        } else {
            hideProgress();
            showToast(data.detail || 'Scan failed', 'error');
            restoreButton(btn, btnText, btnSpinner);
        }
    } catch (err) {
        console.error('Scan error:', err);
        hideProgress();
        showToast('Network error during scan', 'error');
        restoreButton(btn, btnText, btnSpinner);
    }
}

async function runConsolidation() {
    if (isAllProjects) {
        showToast('Please select a specific project to run consolidation', 'error');
        return;
    }

    const btn = document.getElementById('consolidate-btn');
    const btnText = btn.querySelector('.btn-text');
    const btnSpinner = btn.querySelector('.btn-spinner');
    const btnProgress = btn.querySelector('.btn-progress');
    const threshold = document.getElementById('threshold').value;

    btn.disabled = true;
    btnText.style.display = 'none';
    btnSpinner.style.display = 'inline-flex';

    showProgress(
        'Initializing',
        `Preparing to analyze ${totalClusters} clusters...`,
        0
    );
    startProgressTimer();
    btnProgress.textContent = 'Starting...';

    // Use Server-Sent Events for real-time progress
    const url = `/api/consolidation/stream?project=${encodeURIComponent(currentProject)}&threshold=${threshold}&max_clusters=10`;
    const eventSource = new EventSource(url);

    eventSource.onmessage = (event) => {
        try {
            const data = JSON.parse(event.data);
            const phase = data.phase;
            const progress = data.progress || 0;
            const message = data.message || '';

            // Update progress display
            showProgress(formatPhase(phase), message, progress);
            btnProgress.textContent = formatPhase(phase) + '...';

            // Handle completion
            if (phase === 'complete') {
                eventSource.close();

                const results = data.results;
                if (!results || results.clusters_processed === 0) {
                    setTimeout(() => {
                        hideProgress();
                        showToast('No clusters to consolidate', 'info');
                        restoreButton(btn, btnText, btnSpinner);
                    }, 1000);
                    return;
                }

                // Play completion sound
                playCompletionSound();

                pendingResults = results.results || [];

                setTimeout(() => {
                    hideProgress();
                    showConsolidationModal(results);
                    restoreButton(btn, btnText, btnSpinner);
                }, 1500);
            }

            // Handle error
            if (phase === 'error') {
                eventSource.close();
                hideProgress();
                showToast(message || 'Consolidation failed', 'error');
                restoreButton(btn, btnText, btnSpinner);
            }
        } catch (e) {
            console.error('Error parsing SSE event:', e);
        }
    };

    eventSource.onerror = (error) => {
        console.error('SSE connection error:', error);
        eventSource.close();
        hideProgress();
        showToast('Connection lost during consolidation', 'error');
        restoreButton(btn, btnText, btnSpinner);
    };
}

function formatPhase(phase) {
    // Convert snake_case to Title Case
    const phaseNames = {
        'starting': 'Starting',
        'finding_clusters': 'Scanning',
        'found_clusters': 'Found Clusters',
        'tiering': 'Organizing',
        'tiered': 'Organized',
        'processing_auto': 'Auto-Resolving',
        'processing_llm': 'Analyzing',
        'llm_complete': 'Analysis Complete',
        'processing_cluster': 'Processing',
        'complete': 'Complete',
        'error': 'Error'
    };
    return phaseNames[phase] || phase.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
}

function playCompletionSound() {
    // Create a subtle completion sound using Web Audio API
    try {
        const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        const oscillator = audioCtx.createOscillator();
        const gainNode = audioCtx.createGain();

        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);

        oscillator.frequency.value = 800;
        oscillator.type = 'sine';
        gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime);
        gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);

        oscillator.start(audioCtx.currentTime);
        oscillator.stop(audioCtx.currentTime + 0.3);
    } catch (e) {
        // Audio not supported, skip silently
    }
}

function showConsolidationModal(data) {
    document.getElementById('decision-count').textContent = data.clusters_processed;

    // Calculate total memories to be deleted
    const totalDeleted = data.results.reduce((sum, r) => sum + (r.deleted_ids?.length || 0), 0);
    document.getElementById('apply-decision-count').textContent = `${data.clusters_processed} clusters, ${totalDeleted} deletions`;

    const container = document.getElementById('consolidation-decisions');
    container.innerHTML = data.results.map((r, i) => {
        const decision = r.decision;
        const reasoning = r.reasoning || 'No reasoning provided';
        const deletedCount = r.deleted_ids?.length || 0;

        let detailHtml = '';
        let deleteInfo = '';

        if (decision === 'keep_one' && r.kept_id) {
            detailHtml = `<p class="decision-detail"><strong>Keep:</strong> <code>${escapeHtml(r.kept_id)}</code></p>`;
            deleteInfo = `<p class="delete-info">Will delete ${deletedCount} duplicate(s)</p>`;
        } else if (decision === 'merge' && r.merged_memory) {
            const merged = r.merged_memory;
            detailHtml = `
                <div class="decision-merged">
                    <p><strong>Merged Title:</strong> ${escapeHtml(merged.title || 'N/A')}</p>
                    <p><strong>Merged Fact:</strong> ${escapeHtml(merged.fact || 'N/A')}</p>
                </div>
            `;
            deleteInfo = `<p class="delete-info">Will delete ${deletedCount} memories and create 1 merged memory</p>`;
        } else if (decision === 'keep_all') {
            detailHtml = `<p class="decision-detail">All memories will be kept (false positive cluster)</p>`;
            deleteInfo = `<p class="delete-info keep-all">No changes</p>`;
        }

        return `
            <div class="preview-item" data-index="${i}">
                <div class="preview-item-header">
                    <span class="preview-number">#${i + 1}</span>
                    <span class="preview-cluster-id">${escapeHtml(r.cluster_id)}</span>
                    <span class="decision-badge decision-${decision}">${decision.replace('_', ' ')}</span>
                    ${deletedCount > 0 ? `<span class="delete-count">-${deletedCount}</span>` : ''}
                </div>
                <div class="preview-item-body">
                    <p class="preview-reasoning">${escapeHtml(reasoning)}</p>
                    ${detailHtml}
                    ${deleteInfo}
                </div>
            </div>
        `;
    }).join('');

    document.getElementById('consolidation-modal').style.display = 'flex';
}

function closeConsolidationModal() {
    document.getElementById('consolidation-modal').style.display = 'none';
    pendingResults = [];
}

async function applyConsolidation() {
    if (pendingResults.length === 0) {
        showToast('No decisions to apply', 'error');
        return;
    }

    const btn = document.getElementById('apply-consolidation-btn');
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner"></span> Applying...';

    try {
        const response = await fetch(
            `/api/consolidation/apply?project=${encodeURIComponent(currentProject)}`,
            {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ results: pendingResults })
            }
        );
        const data = await response.json();

        if (response.ok) {
            // Calculate actual deletions for better feedback
            const deletedCount = pendingResults.reduce((sum, r) => sum + (r.deleted_ids?.length || 0), 0);
            const mergedCount = pendingResults.filter(r => r.decision === 'merge').length;

            let message = `Applied ${data.applied} consolidation(s)`;
            if (deletedCount > 0) {
                message += ` - deleted ${deletedCount} duplicate(s)`;
            }
            if (mergedCount > 0) {
                message += `, created ${mergedCount} merged`;
            }
            message += '!';

            showToast(message, 'success');
            playCompletionSound();
            closeConsolidationModal();
            // Navigate to clean URL (without scan=true) to show updated state
            setTimeout(() => {
                window.location.href = `/consolidation?project=${encodeURIComponent(currentProject)}&view=scan`;
            }, 1500);
        } else {
            showToast(data.detail || 'Apply failed', 'error');
            btn.disabled = false;
            btn.innerHTML = `Apply (<span id="apply-decision-count">${pendingResults.length}</span>)`;
        }
    } catch (err) {
        console.error('Apply error:', err);
        showToast('Network error', 'error');
        btn.disabled = false;
        btn.innerHTML = `Apply (<span id="apply-decision-count">${pendingResults.length}</span>)`;
    }
}

function restoreButton(btn, btnText, btnSpinner) {
    btn.disabled = false;
    btnText.style.display = 'inline';
    btnSpinner.style.display = 'none';
}

// Close modal on Escape
document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') {
        closeConsolidationModal();
    }
});

// ============== AUTO-CONSOLIDATION SETTINGS ==============

async function loadConsolidationSettings() {
    try {
        const response = await fetch('/api/settings/consolidation');
        if (response.ok) {
            const settings = await response.json();
            const toggle = document.getElementById('auto-consolidation-toggle');
            const modeSelect = document.getElementById('consolidation-mode');
            const intervalSelect = document.getElementById('periodic-interval');

            toggle.checked = settings.enabled || false;
            modeSelect.value = settings.mode || 'session';
            intervalSelect.value = (settings.periodic_minutes || 30).toString();

            // Show/hide options based on state
            modeSelect.style.display = toggle.checked ? 'inline-block' : 'none';
            const showInterval = toggle.checked && (settings.mode === 'periodic' || settings.mode === 'both');
            intervalSelect.style.display = showInterval ? 'inline-block' : 'none';
        }
    } catch (err) {
        console.error('Failed to load consolidation settings:', err);
    }
}

async function updateConsolidationSettings() {
    const toggle = document.getElementById('auto-consolidation-toggle');
    const modeSelect = document.getElementById('consolidation-mode');
    const intervalSelect = document.getElementById('periodic-interval');

    const enabled = toggle.checked;
    const mode = modeSelect.value;
    const periodicMinutes = parseInt(intervalSelect.value);

    // Update UI visibility
    modeSelect.style.display = enabled ? 'inline-block' : 'none';
    intervalSelect.style.display = (enabled && (mode === 'periodic' || mode === 'both')) ? 'inline-block' : 'none';

    try {
        const params = new URLSearchParams({
            enabled: enabled,
            mode: mode,
            periodic_minutes: periodicMinutes,
            threshold: loadThreshold()
        });

        const response = await fetch(`/api/settings/consolidation?${params}`, { method: 'POST' });

        if (response.ok) {
            showToast(`Auto-consolidation ${enabled ? 'enabled' : 'disabled'}`, 'success');
        } else {
            showToast('Failed to update settings', 'error');
        }
    } catch (err) {
        console.error('Failed to update consolidation settings:', err);
        showToast('Network error', 'error');
    }
}

// Load settings on page load
document.addEventListener('DOMContentLoaded', () => {
    loadConsolidationSettings();

    // Restore saved threshold if no URL param override
    const urlParams = new URLSearchParams(window.location.search);
    if (!urlParams.has('threshold')) {
        const saved = loadThreshold();
        const slider = document.getElementById('threshold');
        if (slider && saved) {
            slider.value = saved;
            document.getElementById('threshold-value').textContent = saved;
        }
    }
});
</script>

<!-- Styles moved to static/style.css -->
{% endblock %}
