// ==========================================
// CSV Table Viewer — Browser Extension
// ==========================================
// Renders ```csv and ```tsv code blocks as sortable HTML tables.
// No external dependencies.
// ==========================================

Extensions.register({
    id: 'csv-table',

    async init(ctx) {
        const self = this;

        // ── Inject styles ──
        this._injectStyles();

        ctx.renderers.register('csv-block', {
            type: 'block',
            priority: 10,
            match(lang) {
                const l = (lang || '').toLowerCase();
                return l === 'csv' || l === 'tsv';
            },
            render(lang, code, container) {
                const delimiter = lang.toLowerCase() === 'tsv' ? '\t' : ',';
                const rows = self._parseCSV(code.trim(), delimiter);

                if (rows.length === 0) {
                    container.innerHTML = '<div class="csv-empty">No data</div>';
                    return;
                }

                const headers = rows[0];
                const data = rows.slice(1);
                const tableId = 'csv-' + Math.random().toString(36).slice(2, 9);

                container.innerHTML = `
                    <div class="csv-table-block ext-rendered" data-csv-id="${tableId}">
                        <div class="csv-toolbar">
                            <span class="csv-info">${data.length} row${data.length !== 1 ? 's' : ''} × ${headers.length} col${headers.length !== 1 ? 's' : ''}</span>
                            <button class="csv-copy-btn" title="Copy as CSV">📋 Copy</button>
                        </div>
                        <div class="csv-table-scroll">
                            <table class="csv-table">
                                <thead>
                                    <tr>${headers.map((h, i) => `<th data-col="${i}" title="Click to sort">${self._escapeHtml(h)}<span class="csv-sort-icon"></span></th>`).join('')}</tr>
                                </thead>
                                <tbody>
                                    ${data.map(row => `<tr>${row.map(cell => `<td>${self._escapeHtml(cell)}</td>`).join('')}</tr>`).join('')}
                                </tbody>
                            </table>
                        </div>
                        <details class="csv-source">
                            <summary>📄 View raw</summary>
                            <pre><code>${self._escapeHtml(code.trim())}</code></pre>
                        </details>
                    </div>
                `;

                // Attach sort handlers + copy
                self._attachHandlers(container, tableId, code.trim());
            }
        });
    },

    _attachHandlers(container, tableId, rawCSV) {
        const block = container.querySelector(`[data-csv-id="${tableId}"]`);
        if (!block) return;

        // ── Column sorting ──
        const ths = block.querySelectorAll('th[data-col]');
        let sortCol = -1;
        let sortAsc = true;

        ths.forEach(th => {
            th.style.cursor = 'pointer';
            th.addEventListener('click', () => {
                const col = parseInt(th.dataset.col, 10);
                if (sortCol === col) {
                    sortAsc = !sortAsc;
                } else {
                    sortCol = col;
                    sortAsc = true;
                }

                const tbody = block.querySelector('tbody');
                const rows = Array.from(tbody.querySelectorAll('tr'));

                rows.sort((a, b) => {
                    const cellA = (a.children[col]?.textContent || '').trim();
                    const cellB = (b.children[col]?.textContent || '').trim();
                    const numA = parseFloat(cellA);
                    const numB = parseFloat(cellB);

                    // Numeric sort if both are numbers
                    if (!isNaN(numA) && !isNaN(numB)) {
                        return sortAsc ? numA - numB : numB - numA;
                    }
                    // String sort
                    const cmp = cellA.localeCompare(cellB, undefined, { numeric: true, sensitivity: 'base' });
                    return sortAsc ? cmp : -cmp;
                });

                rows.forEach(row => tbody.appendChild(row));

                // Update sort icons
                ths.forEach(h => {
                    const icon = h.querySelector('.csv-sort-icon');
                    if (icon) {
                        const hCol = parseInt(h.dataset.col, 10);
                        icon.textContent = hCol === sortCol ? (sortAsc ? ' ▲' : ' ▼') : '';
                    }
                });
            });
        });

        // ── Copy button ──
        const copyBtn = block.querySelector('.csv-copy-btn');
        if (copyBtn) {
            copyBtn.addEventListener('click', () => {
                navigator.clipboard.writeText(rawCSV).then(() => {
                    copyBtn.textContent = '✓ Copied';
                    setTimeout(() => { copyBtn.textContent = '📋 Copy'; }, 1500);
                }).catch(() => {
                    copyBtn.textContent = '✗ Failed';
                    setTimeout(() => { copyBtn.textContent = '📋 Copy'; }, 1500);
                });
            });
        }
    },

    /**
     * Simple CSV parser that handles quoted fields.
     */
    _parseCSV(text, delimiter) {
        const rows = [];
        let row = [];
        let field = '';
        let inQuotes = false;
        let i = 0;

        while (i < text.length) {
            const ch = text[i];

            if (inQuotes) {
                if (ch === '"') {
                    // Peek ahead: escaped quote or end of quoted field
                    if (i + 1 < text.length && text[i + 1] === '"') {
                        field += '"';
                        i += 2;
                    } else {
                        inQuotes = false;
                        i++;
                    }
                } else {
                    field += ch;
                    i++;
                }
            } else {
                if (ch === '"' && field === '') {
                    inQuotes = true;
                    i++;
                } else if (ch === delimiter) {
                    row.push(field.trim());
                    field = '';
                    i++;
                } else if (ch === '\n' || (ch === '\r' && text[i + 1] === '\n')) {
                    row.push(field.trim());
                    if (row.some(cell => cell !== '')) rows.push(row);
                    row = [];
                    field = '';
                    i += (ch === '\r') ? 2 : 1;
                } else {
                    field += ch;
                    i++;
                }
            }
        }

        // Last field/row
        row.push(field.trim());
        if (row.some(cell => cell !== '')) rows.push(row);

        // Normalize: pad short rows to header length
        if (rows.length > 0) {
            const maxCols = Math.max(...rows.map(r => r.length));
            rows.forEach(r => {
                while (r.length < maxCols) r.push('');
            });
        }

        return rows;
    },

    _escapeHtml(str) {
        const div = document.createElement('div');
        div.textContent = str;
        return div.innerHTML;
    },

    _injectStyles() {
        if (document.getElementById('ext-style-csv-table')) return;
        const style = document.createElement('style');
        style.id = 'ext-style-csv-table';
        style.textContent = `
.csv-table-block {
    background: var(--bg-2); border: 1px solid var(--border);
    border-radius: 8px; overflow: hidden; margin: 12px 0;
}
.csv-toolbar {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 12px; border-bottom: 1px solid var(--border);
    font-size: 12px; color: var(--text-3);
}
.csv-info { flex: 1; }
.csv-copy-btn {
    background: none; border: 1px solid var(--border); border-radius: 4px;
    padding: 2px 8px; font-size: 12px; cursor: pointer; color: var(--text-3);
}
.csv-copy-btn:hover { color: var(--text-2); border-color: var(--text-3); }
.csv-table-scroll { overflow-x: auto; }
.csv-table {
    width: 100%; border-collapse: collapse; font-size: 13px;
    font-family: var(--mono);
}
.csv-table th {
    background: var(--bg-3); color: var(--text-2); font-weight: 600;
    padding: 6px 12px; text-align: left; white-space: nowrap;
    border-bottom: 2px solid var(--border); user-select: none;
}
.csv-table th:hover { color: var(--text-1); }
.csv-sort-icon { font-size: 11px; opacity: 0.7; }
.csv-table td {
    padding: 4px 12px; border-bottom: 1px solid var(--border);
    white-space: nowrap; max-width: 300px; overflow: hidden; text-overflow: ellipsis;
}
.csv-table tr:hover td { background: var(--bg-3); }
.csv-source, .csv-empty { border-top: 1px solid var(--border); font-size: 12px; }
.csv-source summary {
    padding: 6px 12px; cursor: pointer; color: var(--text-3); user-select: none;
}
.csv-source summary:hover { color: var(--text-2); }
.csv-source pre {
    margin: 0; border-radius: 0; border: none;
    max-height: 200px; overflow: auto;
}
.csv-empty { padding: 16px; text-align: center; color: var(--text-3); }`;
        document.head.appendChild(style);
    },

    destroy() {
        document.getElementById('ext-style-csv-table')?.remove();
    }
});
