// registry-editor.js

// Initialize the registry with some default values
let candidateRegistry = [];

// Built-in preset names (loaded from CSV files on demand)
const builtInPresetNames = ["mahjong", "mahjong-english", "us-states", "colors", "debug"];
const builtInPresetCache = {}; // Cache for loaded presets

// CSV Parser functions
function parseCSVRow(line) {
    // Handle quoted fields with commas
    const result = [];
    let current = '';
    let inQuotes = false;
    for (const char of line) {
        if (char === '"') {
            inQuotes = !inQuotes;
        } else if (char === ',' && !inQuotes) {
            result.push(current.trim());
            current = '';
        } else {
            current += char;
        }
    }
    result.push(current.trim());
    return result;
}

function parseCSVPreset(csvText) {
    const lines = csvText.trim().split('\n');
    // Skip header row (line 0)
    const entries = [];

    for (let i = 1; i < lines.length; i++) {
        const row = parseCSVRow(lines[i]);
        if (row.length >= 2) {
            entries.push({
                candidate: row[0],
                aliases: row[1].split(',').map(a => a.trim()).filter(a => a),
                isAction: row[2]?.toLowerCase() === 'true'
            });
        }
    }
    return entries;
}

// Load a built-in preset from CSV file
async function loadBuiltInPreset(name) {
    if (builtInPresetCache[name]) {
        return builtInPresetCache[name];
    }
    try {
        const response = await fetch(`/presets/${name}.csv`);
        if (!response.ok) throw new Error(`Failed to load preset: ${name}`);
        const csv = await response.text();
        builtInPresetCache[name] = parseCSVPreset(csv);
        return builtInPresetCache[name];
    } catch (error) {
        console.error(`Error loading preset ${name}:`, error);
        return null;
    }
}

// Export current registry to CSV
function exportToCSV() {
    let csv = 'candidate,aliases,isAction\n';
    candidateRegistry.forEach(entry => {
        const aliases = entry.aliases.join(',');
        const quotedAliases = aliases.includes(',') ? `"${aliases}"` : aliases;
        csv += `${entry.candidate},${quotedAliases},${entry.isAction || false}\n`;
    });

    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'preset.csv';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

// Import preset from URL
async function importFromUrl(url) {
    try {
        const response = await fetch(url);
        if (!response.ok) throw new Error('Failed to fetch URL');
        const text = await response.text();
        const preset = parseCSVPreset(text);
        if (preset.length === 0) {
            throw new Error('No valid entries found in CSV');
        }
        loadPreset(preset);
        return true;
    } catch (error) {
        alert('Failed to import from URL: ' + error.message);
        return false;
    }
}

// Helper to check if a candidate is an action (for combo voting)
function isActionCandidate(candidateName) {
    const entry = candidateRegistry.find(e => e.candidate === candidateName);
    return entry?.isAction || false;
}
// Expose globally for parseMessageForVote.js
window.isActionCandidate = isActionCandidate;

// Function to load the registry from localStorage or use defaults
async function loadRegistry() {
    const savedRegistry = localStorage.getItem('candidateRegistry');
    if (savedRegistry) {
        candidateRegistry = JSON.parse(savedRegistry);
    } else {
        // Load mahjong preset as default for first-time users
        const mahjongPreset = await loadBuiltInPreset('mahjong');
        if (mahjongPreset) {
            candidateRegistry = JSON.parse(JSON.stringify(mahjongPreset));
        } else {
            candidateRegistry = [];
        }
    }
}

// Get saved user presets
function getUserPresets() {
    const presets = localStorage.getItem('userPresets');
    return presets ? JSON.parse(presets) : {};
}

// Save a user preset
function saveUserPreset(name, registry) {
    const presets = getUserPresets();
    presets[name] = registry;
    localStorage.setItem('userPresets', JSON.stringify(presets));
    updatePresetDropdown();
}

// Update the preset dropdown with user presets
function updatePresetDropdown() {
    const presetList = document.getElementById('presetList');
    const noUserPresets = document.getElementById('noUserPresets');

    // Remove existing user presets
    document.querySelectorAll('.user-preset-item').forEach(item => item.remove());

    const userPresets = getUserPresets();
    const presetNames = Object.keys(userPresets);

    if (presetNames.length > 0) {
        noUserPresets.style.display = 'none';

        presetNames.forEach(name => {
            const listItem = document.createElement('li');
            listItem.className = 'user-preset-item';
            listItem.innerHTML = `
                <div class="dropdown-item d-flex justify-content-between align-items-center">
                    <a href="#" class="preset-link" data-preset-user="${name}">${name}</a>
                    <button class="btn btn-sm btn-outline-danger delete-preset-btn" data-preset-name="${name}">
                        <i class="fas fa-trash-alt"></i>
                    </button>
                </div>
            `;
            presetList.appendChild(listItem);

            // Add event listener to the preset link
            listItem.querySelector('.preset-link').addEventListener('click', (e) => {
                e.preventDefault();
                const presetName = e.target.getAttribute('data-preset-user');
                loadPreset(userPresets[presetName]);
            });

            // Add event listener to the delete button
            listItem.querySelector('.delete-preset-btn').addEventListener('click', (e) => {
                e.stopPropagation();
                const presetName = e.target.closest('.delete-preset-btn').getAttribute('data-preset-name');
                deleteUserPreset(presetName);
            });
        });
    } else {
        noUserPresets.style.display = 'block';
    }
}

// Delete a user preset
function deleteUserPreset(name) {
    const presets = getUserPresets();
    delete presets[name];
    localStorage.setItem('userPresets', JSON.stringify(presets));
    updatePresetDropdown();
}

// Load a preset into the registry
function loadPreset(preset) {
    candidateRegistry = JSON.parse(JSON.stringify(preset)); // Deep copy
    renderRegistryEntries();
}

// Function to save the registry to localStorage
function saveRegistry() {
    localStorage.setItem('candidateRegistry', JSON.stringify(candidateRegistry));
}

// Function to update the translate Map from the registry
function updateTranslateFromRegistry() {
    // First, clear the translate map completely
    if (typeof translate !== 'undefined') {
        translate.clear();
    } else {
        console.error("translate map is not defined!");
        return;
    }

    // Now rebuild it from the candidateRegistry
    candidateRegistry.forEach(entry => {
        // Skip empty entries
        if (!entry.candidate) return;

        // Add each alias as a translation
        entry.aliases.forEach(alias => {
            if (alias) { // Skip empty aliases
                addToTranslate(alias.toLowerCase(), entry.candidate);
            }
        });

        // Also add the candidate name itself as a translation
        addToTranslate(entry.candidate.toLowerCase(), entry.candidate);
    });

    console.log("Translate map completely rebuilt from registry with", translate.size, "entries");
}

// Track collapsed state for entries
let collapsedEntries = new Set();

// Function to render the registry entries in the modal
function renderRegistryEntries() {
    const container = document.getElementById('registryEntries');
    container.innerHTML = '';

    candidateRegistry.forEach((entry, index) => {
        const entryDiv = document.createElement('div');
        entryDiv.className = 'registry-entry card mb-3';
        entryDiv.dataset.index = index;

        const isCollapsed = collapsedEntries.has(index);
        const collapseId = `entryCollapse${index}`;
        const displayName = entry.candidate || '(unnamed)';
        const aliasCount = entry.aliases.filter(a => a).length;

        entryDiv.innerHTML = `
            <div class="card-header d-flex justify-content-between align-items-center" style="cursor: pointer;" data-bs-toggle="collapse" data-bs-target="#${collapseId}">
                <div class="d-flex align-items-center gap-2">
                    <i class="fas fa-chevron-${isCollapsed ? 'right' : 'down'} collapse-icon"></i>
                    <strong class="candidate-display-name">${displayName}</strong>
                    <span class="badge bg-secondary">${aliasCount} alias${aliasCount !== 1 ? 'es' : ''}</span>
                    <div class="form-check form-switch ms-2">
                        <input class="form-check-input is-action-toggle" type="checkbox" ${entry.isAction ? 'checked' : ''} title="Mark as action for combo voting" onclick="event.stopPropagation();">
                        <label class="form-check-label small text-muted" onclick="event.stopPropagation();">Action</label>
                    </div>
                </div>
                <button class="btn btn-danger btn-sm delete-entry-btn" onclick="event.stopPropagation();">
                    <i class="fas fa-trash"></i> Delete
                </button>
            </div>
            <div id="${collapseId}" class="collapse ${isCollapsed ? '' : 'show'}">
                <div class="card-body">
                    <div class="row mb-2">
                        <div class="col-12">
                            <label class="form-label">Candidate Name:</label>
                            <input type="text" class="form-control candidate-name" value="${entry.candidate}" placeholder="Candidate Name">
                        </div>
                    </div>
                    <div class="aliases-container">
                        <label class="form-label">Aliases (Words that will be counted for this candidate):</label>
                        <div class="aliases-list mb-2">
                            ${entry.aliases.map((alias, aliasIndex) => `
                                <div class="input-group mb-2 alias-input-group">
                                    <input type="text" class="form-control alias-input" value="${alias}" placeholder="Alias">
                                    <button class="btn btn-outline-info swap-alias-btn" data-alias-index="${aliasIndex}" title="Use as candidate name">
                                        <i class="fas fa-exchange-alt"></i>
                                    </button>
                                    <button class="btn btn-outline-danger remove-alias-btn" data-alias-index="${aliasIndex}">
                                        <i class="fas fa-times"></i>
                                    </button>
                                </div>
                            `).join('')}
                        </div>
                        <button class="btn btn-outline-primary add-alias-btn" data-entry-index="${index}">
                            <i class="fas fa-plus"></i> Add Alias
                        </button>
                    </div>
                </div>
            </div>
        `;

        container.appendChild(entryDiv);

        // Track collapse state changes
        const collapseEl = entryDiv.querySelector(`#${collapseId}`);
        collapseEl.addEventListener('hidden.bs.collapse', () => {
            collapsedEntries.add(index);
            entryDiv.querySelector('.collapse-icon').classList.replace('fa-chevron-down', 'fa-chevron-right');
        });
        collapseEl.addEventListener('shown.bs.collapse', () => {
            collapsedEntries.delete(index);
            entryDiv.querySelector('.collapse-icon').classList.replace('fa-chevron-right', 'fa-chevron-down');
        });

        // Add event listeners for this entry
        const deleteEntryBtn = entryDiv.querySelector('.delete-entry-btn');
        deleteEntryBtn.addEventListener('click', () => {
            candidateRegistry.splice(index, 1);
            renderRegistryEntries();
        });

        const addAliasBtn = entryDiv.querySelector('.add-alias-btn');
        addAliasBtn.addEventListener('click', () => {
            candidateRegistry[index].aliases.push('');
            renderRegistryEntries();
        });

        const removeAliasBtns = entryDiv.querySelectorAll('.remove-alias-btn');
        removeAliasBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                const aliasIndex = parseInt(btn.dataset.aliasIndex);
                candidateRegistry[index].aliases.splice(aliasIndex, 1);
                renderRegistryEntries();
            });
        });

        const swapAliasBtns = entryDiv.querySelectorAll('.swap-alias-btn');
        swapAliasBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                const aliasIndex = parseInt(btn.dataset.aliasIndex);
                const oldName = candidateRegistry[index].candidate;
                const aliasValue = candidateRegistry[index].aliases[aliasIndex];
                if (!aliasValue) return;
                candidateRegistry[index].candidate = aliasValue;
                candidateRegistry[index].aliases[aliasIndex] = oldName;
                renderRegistryEntries();
            });
        });
    });

    // Add event listeners for input changes
    const nameInputs = document.querySelectorAll('.candidate-name');
    nameInputs.forEach((input, index) => {
        input.addEventListener('change', () => {
            candidateRegistry[index].candidate = input.value;
            // Update the display name in the header
            const entryDiv = input.closest('.registry-entry');
            const displayName = entryDiv.querySelector('.candidate-display-name');
            if (displayName) {
                displayName.textContent = input.value || '(unnamed)';
            }
        });
    });

    const aliasInputs = document.querySelectorAll('.alias-input');
    aliasInputs.forEach(input => {
        input.addEventListener('change', () => {
            const entryDiv = input.closest('.registry-entry');
            const entryIndex = parseInt(entryDiv.dataset.index);

            const aliasGroup = input.closest('.alias-input-group');
            const aliasInputs = entryDiv.querySelectorAll('.alias-input');
            const aliasIndex = Array.from(aliasInputs).indexOf(input);

            candidateRegistry[entryIndex].aliases[aliasIndex] = input.value;
        });
    });

    // Add event listeners for isAction toggle
    const actionToggles = document.querySelectorAll('.is-action-toggle');
    actionToggles.forEach((toggle, index) => {
        toggle.addEventListener('change', () => {
            candidateRegistry[index].isAction = toggle.checked;
        });
    });
}

// Initialize everything when the DOM is loaded
document.addEventListener('DOMContentLoaded', async function () {
    // Load Font Awesome if not already loaded
    if (!document.querySelector('link[href*="fontawesome"]')) {
        const fontAwesome = document.createElement('link');
        fontAwesome.rel = 'stylesheet';
        fontAwesome.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
        document.head.appendChild(fontAwesome);
    }

    // Load the registry
    await loadRegistry();

    // Add event listener for the edit button
    const editBtn = document.getElementById('editRegistryBtn');
    if (editBtn) {
        editBtn.addEventListener('click', function () {
            collapsedEntries.clear(); // Reset collapsed state when opening
            renderRegistryEntries();
            updatePresetDropdown(); // Update the preset dropdown
            const registryModal = new bootstrap.Modal(document.getElementById('registryModal'));
            registryModal.show();
        });
    }

    // Add event listener for adding new entry
    const addNewEntryBtn = document.getElementById('addNewEntryBtn');
    if (addNewEntryBtn) {
        addNewEntryBtn.addEventListener('click', function () {
            candidateRegistry.push({
                candidate: "",
                aliases: [""]
            });
            renderRegistryEntries();
        });
    }

    // Add event listener for collapse all button
    const collapseAllBtn = document.getElementById('collapseAllBtn');
    if (collapseAllBtn) {
        collapseAllBtn.addEventListener('click', function () {
            document.querySelectorAll('#registryEntries .collapse.show').forEach(el => {
                bootstrap.Collapse.getOrCreateInstance(el).hide();
            });
        });
    }

    // Add event listener for expand all button
    const expandAllBtn = document.getElementById('expandAllBtn');
    if (expandAllBtn) {
        expandAllBtn.addEventListener('click', function () {
            document.querySelectorAll('#registryEntries .collapse:not(.show)').forEach(el => {
                bootstrap.Collapse.getOrCreateInstance(el).show();
            });
        });
    }

    // Add event listener for saving changes
    const saveRegistryBtn = document.getElementById('saveRegistryBtn');
    if (saveRegistryBtn) {
        saveRegistryBtn.addEventListener('click', function () {
            saveRegistry();
            updateTranslateFromRegistry();

            // If a poll is currently open, close it
            if (typeof isOpen !== 'undefined' && isOpen) {
                // Get the toggle button
                const toggleButton = document.getElementById('toggleButton');
                if (toggleButton) {
                    // Update button appearance
                    toggleButton.textContent = 'CLOSED';
                    toggleButton.classList.add('off');

                    // Set the poll to closed
                    isOpen = false;

                    console.log('Poll automatically closed due to registry change');
                }
            }

            // Reset chart if needed
            if (typeof chart !== 'undefined' && typeof stats !== 'undefined') {
                chart.destroy();

                // Clear existing stats
                stats.clear();

                // Initialize stats for all candidates
                candidateRegistry.forEach(entry => {
                    stats.set(entry.candidate, 0);
                });

                if (typeof VoteChart !== 'undefined') {
                    VoteChart.setData(stats);
                    VoteChart.render();
                }
            }

            const registryModal = bootstrap.Modal.getInstance(document.getElementById('registryModal'));
            registryModal.hide();
        });
    }

    // Add event listeners for built-in presets
    document.querySelectorAll('#presetList [data-preset]').forEach(presetLink => {
        presetLink.addEventListener('click', async function (e) {
            e.preventDefault();
            const presetName = this.getAttribute('data-preset');
            if (builtInPresetNames.includes(presetName)) {
                const preset = await loadBuiltInPreset(presetName);
                if (preset) {
                    loadPreset(preset);
                }
            }
        });
    });

    // Add event listener for saving a preset
    const savePresetBtn = document.getElementById('savePresetBtn');
    if (savePresetBtn) {
        savePresetBtn.addEventListener('click', function () {
            const presetName = document.getElementById('presetNameInput').value.trim();
            if (presetName) {
                saveUserPreset(presetName, candidateRegistry);
                document.getElementById('presetNameInput').value = '';
            } else {
                // Show error or alert
                alert('Please enter a name for your preset');
            }
        });
    }

    // Add event listener for export button
    const exportCsvBtn = document.getElementById('exportCsvBtn');
    if (exportCsvBtn) {
        exportCsvBtn.addEventListener('click', exportToCSV);
    }

    // Add event listener for file import
    const importFileBtn = document.getElementById('importFileBtn');
    const presetFileInput = document.getElementById('presetFileInput');
    if (importFileBtn && presetFileInput) {
        importFileBtn.addEventListener('click', function (e) {
            e.preventDefault();
            presetFileInput.click();
        });

        presetFileInput.addEventListener('change', async function (e) {
            const file = e.target.files[0];
            if (file) {
                try {
                    const text = await file.text();
                    const preset = parseCSVPreset(text);
                    if (preset.length === 0) {
                        throw new Error('No valid entries found in CSV');
                    }
                    loadPreset(preset);
                } catch (error) {
                    alert('Failed to import file: ' + error.message);
                }
                // Reset file input so same file can be selected again
                presetFileInput.value = '';
            }
        });
    }

    // Add event listener for URL import
    const importUrlBtn = document.getElementById('importUrlBtn');
    if (importUrlBtn) {
        importUrlBtn.addEventListener('click', function (e) {
            e.preventDefault();
            const urlModal = new bootstrap.Modal(document.getElementById('urlImportModal'));
            urlModal.show();
        });
    }

    // Add event listener for URL import confirm button
    const confirmUrlImportBtn = document.getElementById('confirmUrlImportBtn');
    if (confirmUrlImportBtn) {
        confirmUrlImportBtn.addEventListener('click', async function () {
            const urlInput = document.getElementById('importUrlInput');
            const url = urlInput.value.trim();
            if (url) {
                const success = await importFromUrl(url);
                if (success) {
                    const urlModal = bootstrap.Modal.getInstance(document.getElementById('urlImportModal'));
                    urlModal.hide();
                    urlInput.value = '';
                }
            } else {
                alert('Please enter a URL');
            }
        });
    }

    // Initialize the translate map from the registry
    updateTranslateFromRegistry();
});