// --- App State ---
        let categories = [], rules = [], transactions = [], vendors = [];
        let expensePieChart = null;
        let jwtToken = localStorage.getItem('simpleLedgerToken');
        let transactionSort = { column: 'date', direction: 'desc' };
        let transactionDateFilter = 'lastMonth';
        let customDateRange = { start: null, end: null };

        // --- API Base ---
        const API_URL = '/api';

        // --- API Fetch Helper ---
        async function apiFetch(endpoint, options = {}) {
            const headers = {
                'Authorization': `Bearer ${jwtToken}`,
                ...options.headers
            };
            
            if (!(options.body instanceof FormData)) {
                headers['Content-Type'] = 'application/json';
            }
            
            const res = await fetch(`${API_URL}${endpoint}`, { ...options, headers });

            if (res.status === 401 || res.status === 403) {
                // Token is invalid or expired
                logout();
                throw new Error('Authentication error. Please log in again.');
            }

            if (!res.ok) {
                const errorText = await res.text();
                throw new Error(errorText || 'API request failed');
            }
            
            const contentType = res.headers.get("content-type");
            if (contentType && contentType.indexOf("application/json") !== -1) {
                return res.json();
            } else {
                return res.text();
            }
        }

        // --- Auth Functions ---
        function showAuthError(message) {
            const el = document.getElementById('authError');
            el.textContent = message;
            el.classList.remove('hidden');
        }
        
        function hideAuthError() {
            document.getElementById('authError').classList.add('hidden');
        }

        function toggleAuthForm(showLogin) {
            hideAuthError();
            if (showLogin) {
                document.getElementById('authTitle').textContent = 'Login';
                document.getElementById('loginForm').classList.remove('hidden');
                document.getElementById('registerForm').classList.add('hidden');
                document.getElementById('toggleAuth').textContent = 'Need an account? Register';
            } else {
                document.getElementById('authTitle').textContent = 'Register';
                document.getElementById('loginForm').classList.add('hidden');
                document.getElementById('registerForm').classList.remove('hidden');
                document.getElementById('toggleAuth').textContent = 'Have an account? Login';
            }
        }
        
        async function handleLogin(e) {
            e.preventDefault();
            const form = e.target;
            const username = form.username.value;
            const password = form.password.value;
            
            try {
                const data = await fetch('/api/login', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ username, password })
                });
                
                if (!data.ok) {
                    const errorText = await data.text();
                    throw new Error(errorText);
                }
                
                const { accessToken } = await data.json();
                jwtToken = accessToken;
                localStorage.setItem('simpleLedgerToken', jwtToken);
                
                document.getElementById('authView').classList.add('hidden');
                document.getElementById('appContainer').classList.remove('hidden');
                showView('dashboard');
                await loadAllData();
                
            } catch (err) {
                showAuthError(err.message);
            }
        }

        async function handleRegister(e) {
            e.preventDefault();
            const form = e.target;
            const username = form.username.value;
            const password = form.password.value;
            
            try {
                const data = await fetch('/api/register', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ username, password })
                });

                if (!data.ok) {
                    const errorText = await data.text();
                    throw new Error(errorText);
                }

                swal('Success', 'Registration successful! Please log in.', 'success');
                toggleAuthForm(true); // Show login form

            } catch (err) {
                showAuthError(err.message);
            }
        }

        function logout() {
            jwtToken = null;
            localStorage.removeItem('simpleLedgerToken');
            document.getElementById('authView').classList.remove('hidden');
            document.getElementById('appContainer').classList.add('hidden');
        }

        // --- Data Loading ---
        async function loadAllData() {
            showLoadingModal(true, "Loading your data...");
            try {
                // Must load categories and vendors *first*
                await loadCategories();
                await loadVendors();
                // Then load rules and transactions
                await Promise.all([
                    loadRules(),
                    loadTransactions()
                ]);
                updateDashboard(); // Update dashboard after all data is loaded
            } catch (error) {
                swal('Error loading data', error.message, 'error');
            } finally {
                showLoadingModal(false);
            }
        }

        async function loadCategories() {
            categories = await apiFetch('/categories');
            renderCategories();
            renderCategoryDropdowns(); // Renders for all existing selects
        }

        async function loadVendors() {
            vendors = await apiFetch('/vendors');
            renderVendors();
            renderVendorDropdowns(); // Renders for all existing selects
        }

        async function loadRules() {
            rules = await apiFetch('/rules');
            renderRules();
        }

        async function loadTransactions() {
            transactions = await apiFetch(`/transactions?v=${new Date().getTime()}`);
            // Dates are already strings from server, convert to Date objects
            transactions.forEach(tx => tx.date = new Date(tx.date));
            renderTransactions(); // Will sort and render
        }

        // --- UI Rendering ---
        
        function renderCategories() {
            const list = document.getElementById('categoryList');
            if (!list) return;
            list.innerHTML = '';
            categories.sort((a,b) => a.name.localeCompare(b.name)).forEach(cat => {
                const el = document.createElement('div');
                el.className = 'flex justify-between items-center p-2 bg-white rounded-lg shadow-sm';
                el.innerHTML = `
                    <span>${cat.name} (${cat.type})</span>
                    <button data-id="${cat.id}" class="text-red-500 hover:text-red-700">&times;</button>
                `;
                el.querySelector('button').onclick = () => deleteCategory(cat.id);
                list.appendChild(el);
            });
        }
        
        function renderCategoryDropdowns(selector = '.category-select') {
            const selects = document.querySelectorAll(selector);
            const options = categories
                .sort((a,b) => a.name.localeCompare(b.name))
                .map(c => `<option value="${c.name}">${c.name}</option>`)
                .join('');
            selects.forEach(sel => {
                const currentVal = sel.value;
                sel.innerHTML = options;
                if (currentVal) sel.value = currentVal;
            });
        }

        function renderVendors() {
            const list = document.getElementById('vendorList');
            if (!list) return;
            list.innerHTML = '';
            vendors.forEach(v => {
                const el = document.createElement('div');
                el.className = 'flex justify-between items-center p-2 bg-white rounded-lg shadow-sm';
                el.innerHTML = `
                    <span>${v.name}</span>
                    <button data-id="${v.id}" class="text-red-500 hover:text-red-700">&times;</button>
                `;
                el.querySelector('button').onclick = () => deleteVendor(v.id);
                list.appendChild(el);
            });
        }
        
        function renderVendorDropdowns(selector = '.vendor-select') {
            const selects = document.querySelectorAll(selector);
            const options = vendors
                .sort((a,b) => a.name.localeCompare(b.name))
                .map(c => `<option value="${c.id}">${c.name}</option></span>`)
                .join('');
            selects.forEach(sel => {
                const currentVal = sel.value;
                sel.innerHTML = '<option value="">-- None --</option>' + options;
                sel.value = currentVal || "";
            });
        }

        function renderRules() {
            const list = document.getElementById('rulesList');
            if (!list) return;
            list.innerHTML = '';
            rules.forEach(rule => {
                const el = document.createElement('div');
                el.className = 'flex justify-between items-center p-2 bg-white rounded-lg shadow-sm';
                el.innerHTML = `
                    <span>If description contains "<strong>${rule.keyword}</strong>", set category to <strong>${rule.category}</strong></span>
                    <button data-id="${rule.id}" class="text-red-500 hover:text-red-700">&times;</button>
                `;
                el.querySelector('button').onclick = () => deleteRule(rule.id);
                list.appendChild(el);
            });
        }

        function renderTransactions() {
            const tbody = document.getElementById('transactionsTableBody');
            const filter = document.getElementById('transactionFilter').value;
            const search = document.getElementById('transactionSearch').value.toLowerCase();
            if (!tbody) return;
            
            let txsToRender = [...transactions];
            
            // 1. Filter by Date
            if (transactionDateFilter === 'lastMonth') {
                const oneMonthAgo = new Date();
                oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1);
                txsToRender = txsToRender.filter(tx => new Date(tx.date) >= oneMonthAgo);
            } else if (transactionDateFilter === 'custom' && customDateRange.start && customDateRange.end) {
                // Adjust end date to include the whole day
                const endDate = new Date(customDateRange.end);
                endDate.setHours(23, 59, 59, 999);
                txsToRender = txsToRender.filter(tx => {
                    const txDate = new Date(tx.date);
                    return txDate >= customDateRange.start && txDate <= endDate;
                });
            }

            // 2. Sort
            txsToRender.sort((a, b) => {
                let valA = a[transactionSort.column];
                let valB = b[transactionSort.column];
                
                if (transactionSort.column === 'date') {
                    valA = valA.getTime();
                    valB = valB.getTime();
                } else if (transactionSort.column === 'amount') {
                    valA = valA;
                    valB = valB;
                } else {
                    valA = (valA || '').toLowerCase();
                    valB = (valB || '').toLowerCase();
                }

                if (valA < valB) return transactionSort.direction === 'asc' ? -1 : 1;
                if (valA > valB) return transactionSort.direction === 'asc' ? 1 : -1;
                return 0;
            });
            
            // 2. Filter by Category Status
            if (filter === 'uncategorized') {
                txsToRender = txsToRender.filter(tx => tx.reconciliation_status === 'uncategorized');
            }
            
            // 3. Filter by Search
            if (search) {
                txsToRender = txsToRender.filter(tx => tx.description.toLowerCase().includes(search));
            }
            
            // 4. Update Header styles
            document.querySelectorAll('.sortable-header').forEach(th => {
                th.classList.remove('sort-asc', 'sort-desc');
                if (th.dataset.sort === transactionSort.column) {
                    th.classList.add(transactionSort.direction === 'asc' ? 'sort-asc' : 'sort-desc');
                }
            });
            
            // 5. Render
            tbody.innerHTML = '';
            if (txsToRender.length === 0) {
                tbody.innerHTML = '<tr><td colspan="6" class="text-center p-4">No transactions found.</td></tr>';
                return;
            }
            
            txsToRender.forEach(tx => {
                const txDate = new Date(tx.date);
                const tr = document.createElement('tr');
                tr.className = 'border-b hover:bg-gray-50';
                
                // Determine Category/Vendor display
                let categoryDisplay = '';
                let vendorDisplay = '';
                if (tx.reconciliation_status === 'uncategorized') {
                    categoryDisplay = '<span class="text-red-500">Uncategorized</span>';
                    vendorDisplay = 'N/A';
                } else if (tx.split_count === 1) {
                    categoryDisplay = tx.category || 'N/A';
                    vendorDisplay = tx.vendorName || 'N/A';
                } else if (tx.split_count > 1) {
                    categoryDisplay = '— Split —';
                    vendorDisplay = '— Split —';
                } else { // split_count is 0 or null
                    categoryDisplay = '<span class="text-orange-500">Needs Attention</span>';
                    vendorDisplay = 'N/A';
                }

                tr.innerHTML = `
                    <td class="p-3">${txDate.toLocaleDateString()}</td>
                    <td class="p-3 truncate max-w-xs">${tx.description}</td>
                    <td class="p-3">${categoryDisplay}</td>
                    <td class="p-3">${vendorDisplay}</td>
                    <td class="p-3 text-right font-medium ${tx.amount >= 0 ? 'text-green-600' : 'text-red-600'}">
                        ${tx.amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}
                    </td>
                    <td class="p-3 text-center">
                        <button data-id="${tx.id}" class="edit-tx-btn text-blue-600 hover:underline text-sm">Edit</button>
                        <button data-id="${tx.id}" class="delete-tx-btn text-red-600 hover:underline text-sm ml-2">Del</button>
                    </td>
                `;
                tbody.appendChild(tr);
            });
            
            tbody.querySelectorAll('.edit-tx-btn').forEach(btn => {
                btn.onclick = (e) => showSplitTransactionModal(e.target.dataset.id);
            });
            tbody.querySelectorAll('.delete-tx-btn').forEach(btn => {
                btn.onclick = (e) => deleteTransaction(e.target.dataset.id);
            });
        }
        
        function handleSort(e) {
            const column = e.target.dataset.sort;
            if (!column) return;
            
            if (transactionSort.column === column) {
                transactionSort.direction = transactionSort.direction === 'asc' ? 'desc' : 'asc';
            } else {
                transactionSort.column = column;
                transactionSort.direction = 'desc'; // Default to desc for new columns
            }
            renderTransactions();
        }
        
        async function updateDashboard() {
            try {
                const summary = await apiFetch('/dashboard-summary');
                const { totalIncome, totalReturns, totalExpenses } = summary.stats;
                
                const netIncome = totalIncome + totalReturns; // Returns are negative
                const netProfit = netIncome + totalExpenses; // Expenses are negative
                
                document.getElementById('statGrossIncome').textContent = totalIncome.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
                document.getElementById('statReturns').textContent = totalReturns.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
                document.getElementById('statNetIncome').textContent = netIncome.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
                document.getElementById('statTotalExpenses').textContent = totalExpenses.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
                document.getElementById('statNetProfit').textContent = netProfit.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
                
                if (netProfit >= 0) {
                    document.getElementById('statNetProfit').classList.remove('text-red-600');
                    document.getElementById('statNetProfit').classList.add('text-green-600');
                } else {
                    document.getElementById('statNetProfit').classList.remove('green-red-600');
                    document.getElementById('statNetProfit').classList.add('text-red-600');
                }
                
                // Render Pie Chart
                const ctx = document.getElementById('expensePieChart').getContext('2d');
                if (expensePieChart) {
                    expensePieChart.destroy();
                }
                expensePieChart = new Chart(ctx, {
                    type: 'pie',
                    data: {
                        labels: summary.pieData.labels,
                        datasets: [{
                            label: 'Expenses',
                            data: summary.pieData.data,
                            backgroundColor: [
                                'rgba(239, 68, 68, 0.7)', 'rgba(59, 130, 246, 0.7)', 'rgba(234, 179, 8, 0.7)',
                                'rgba(34, 197, 94, 0.7)', 'rgba(168, 85, 247, 0.7)', 'rgba(236, 72, 153, 0.7)',
                                'rgba(249, 115, 22, 0.7)', 'rgba(13, 148, 136, 0.7)', 'rgba(107, 114, 128, 0.7)',
                                'rgba(217, 119, 6, 0.7)'
                            ],
                            borderColor: '#fff',
                            borderWidth: 1
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        plugins: {
                            legend: { position: 'right' }
                        }
                    }
                });
            } catch (error) {
                console.error("Error updating dashboard:", error);
                swal('Error', "Could not load dashboard summary.", 'error');
            }
        }
        
        function generateReport() {
            // This function is still flawed and needs a server-side endpoint for 100% accuracy.
            // For now, it will only report on transactions with a single, categorized split.
            const startVal = document.getElementById('reportStartDate').value;
            const endVal = document.getElementById('reportEndDate').value;
            
            const start = new Date(startVal + 'T00:00:00');
            const end = new Date(endVal + 'T23:59:59');
            
            if (!startVal || !endVal) {
                swal('Error', "Please select valid start and end dates.", 'error');
                return;
            }

            let incomeByCat = {};
            let expensesByCat = {};
            let totalIncome = 0;
            let totalExpenses = 0;

            const txs = transactions.filter(tx => {
                const txDate = new Date(tx.date);
                return txDate >= start && txDate <= end;
            });

            txs.forEach(tx => {
                if (tx.split_count === 1 && tx.reconciliation_status === 'categorized') {
                    const category = categories.find(c => c.name === tx.category);
                    if (!category) return; // Skip if category not found

                    const type = category.type;
                    
                    if (type === 'income') {
                        totalIncome += tx.amount;
                        incomeByCat[tx.category] = (incomeByCat[tx.category] || 0) + tx.amount;
                    } else if (type === 'expense') {
                        totalExpenses += tx.amount;
                        expensesByCat[tx.category] = (expensesByCat[tx.category] || 0) + tx.amount;
                    }
                }
                // We are intentionally skipping uncategorized and multi-split txs
                // because we don't have their split data on the client.
            });
            
            if (txs.length > 0 && (totalIncome === 0 && totalExpenses === 0)) {
                 swal('Warning', "This report is a client-side estimate and may be incomplete. It does not include multi-split or uncategorized transactions. A server-side report is needed for full accuracy.", 'warning');
            }

            const netProfit = totalIncome + totalExpenses;
            const reportBody = document.getElementById('plReportBody');
            reportBody.innerHTML = '';
            
            let incomeHtml = '<tr class="font-bold bg-gray-100"><td class="p-2" colspan="2">Income</td></tr>';
            const incomeCategories = Object.keys(incomeByCat).sort();
            for (const cat of incomeCategories) {
                const amt = incomeByCat[cat];
                incomeHtml += `<tr><td class="p-2 pl-6">${cat}</td><td class="p-2 text-right">${amt.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</td></tr>`;
            }
            incomeHtml += `<tr class="font-semibold border-t"><td class="p-2">Total Income (Net Sales)</td><td class="p-2 text-right">${totalIncome.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</td></tr>`;
            
            let expensesHtml = '<tr class="font-bold bg-gray-100 mt-4"><td class="p-2" colspan="2">Expenses</td></tr>';
            const expenseCategories = Object.keys(expensesByCat).sort();
            for (const cat of expenseCategories) {
                const amt = expensesByCat[cat];
                expensesHtml += `<tr><td class="p-2 pl-6">${cat}</td><td class="p-2 text-right">${amt.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</td></tr>`;
            }
            expensesHtml += `<tr class="font-semibold border-t"><td class="p-2">Total Expenses</td><td class="p-2 text-right">${totalExpenses.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</td></tr>`;

            let netHtml = `<tr class="font-bold text-lg border-t-2 ${netProfit >= 0 ? 'text-green-700' : 'text-red-700'}">
                <td class="p-2">Net Profit / (Loss)</td>
                <td class="p-2 text-right">${netProfit.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</td>
            </tr>`;
            
            reportBody.innerHTML = incomeHtml + expensesHtml + netHtml;
            document.getElementById('exportReportBtn').classList.remove('hidden');
        }
        
        function exportReport() {
            let csvContent = "data:text/csv;charset=utf-8,";
            csvContent += "Item,Category,Amount\n";
            
            const reportBody = document.getElementById('plReportBody');
            reportBody.querySelectorAll('tr').forEach(tr => {
                const cells = tr.querySelectorAll('td');
                if (cells.length === 2) {
                    let col1 = cells[0].textContent.replace(/,/g, '');
                    let col2 = cells[1].textContent.replace(/[$(),]/g, '');
                    if (cells[0].classList.contains('pl-6')) {
                         csvContent += ` ,${col1},${col2}\n`;
                    } else {
                         csvContent += `${col1}, ,${col2}\n`;
                    }
                }
            });

            const encodedUri = encodeURI(csvContent);
            const link = document.createElement("a");
            link.setAttribute("href", encodedUri);
            link.setAttribute("download", "profit_loss_report.csv");
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }

        // --- Data Actions ---
        
        async function addCategory(e) {
            e.preventDefault();
            const form = e.target;
            const name = form.categoryName.value;
            const type = form.categoryType.value;
            if (!name) return;
            
            try {
                await apiFetch('/categories', {
                    method: 'POST',
                    body: JSON.stringify({ name, type })
                });
                form.reset();
                await loadCategories(); // Refresh
            } catch (error) {
                console.error("Error adding category: ", error);
                swal('Error', error.message, 'error');
            }
        }
        
        async function deleteCategory(id) {
            swal({
                title: "Are you sure?",
                text: "Are you sure you want to delete this category?",
                icon: "warning",
                buttons: true,
                dangerMode: true,
            })
            .then(async (willDelete) => {
                if (willDelete) {
                    try {
                        await apiFetch(`/categories/${id}`, { method: 'DELETE' });
                        await loadCategories(); // Refresh
                        swal("Poof! The category has been deleted!", {
                            icon: "success",
                        });
                    } catch (error) {
                        console.error("Error deleting category: ", error);
                        swal('Error', error.message, 'error');
                    }
                }
            });
        }
        
        async function addVendor(e) {
            e.preventDefault();
            const form = e.target;
            const name = form.vendorName.value;
            if (!name) return;
            
            try {
                await apiFetch('/vendors', {
                    method: 'POST',
                    body: JSON.stringify({ name })
                });
                form.reset();
                await loadVendors(); // Refresh
            } catch (error) {
                console.error("Error adding vendor: ", error);
                swal('Error', error.message, 'error');
            }
        }
        
                async function deleteVendor(id) {
        
                    swal({
        
                        title: "Are you sure?",
        
                        text: "Are you sure you want to delete this vendor?",
        
                        icon: "warning",
        
                        buttons: true,
        
                        dangerMode: true,
        
                    })
        
                    .then(async (willDelete) => {
        
                        if (willDelete) {
        
                            try {
        
                                await apiFetch(`/vendors/${id}`, { method: 'DELETE' });
        
                                await loadVendors(); // Refresh
        
                                swal("Poof! The vendor has been deleted!", {
        
                                    icon: "success",
        
                                });
        
                            } catch (error) {
        
                                console.error("Error deleting vendor: ", error);
        
                                swal('Error', error.message, 'error');
        
                            }
        
                        }
        
                    });
        
                }

        async function addRule(e) {
            e.preventDefault();
            const form = e.target;
            const keyword = form.ruleKeyword.value;
            const category = form.ruleCategory.value;
            if (!keyword || !category) return;
            
            try {
                await apiFetch('/rules', {
                    method: 'POST',
                    body: JSON.stringify({ keyword, category })
                });
                form.reset();
                await loadRules(); // Refresh
                
                swal({
                    title: "Rule added!",
                    text: "Apply all rules to uncategorized transactions now?",
                    icon: "success",
                    buttons: true,
                })
                .then((willApply) => {
                    if (willApply) {
                        applyAllRules();
                    }
                });

            } catch (error) {
                console.error("Error adding rule: ", error);
                swal('Error', error.message, 'error');
            }
        }
        
        async function deleteRule(id) {
            swal({
                title: "Are you sure?",
                text: "Are you sure you want to delete this rule?",
                icon: "warning",
                buttons: true,
                dangerMode: true,
            })
            .then(async (willDelete) => {
                if (willDelete) {
                    try {
                        await apiFetch(`/rules/${id}`, { method: 'DELETE' });
                        await loadRules(); // Refresh
                        swal("Poof! The rule has been deleted!", {
                            icon: "success",
                        });
                    } catch (error) {
                        console.error("Error deleting rule: ", error);
                        swal('Error', error.message, 'error');
                    }
                }
            });
        }
        
        async function applyAllRules() {
            showLoadingModal(true, "Applying rules...");
            try {
                const message = await apiFetch('/rules/apply-all', { method: 'POST' });
                swal('Success', message, 'success');
                await loadTransactions(); // Refresh transactions
            } catch (error) {
                console.error("Error applying rules:", error);
                alert(error.message);
            } finally {
                showLoadingModal(false);
            }
        }

        // --- NEW: Split Modal Functions ---

        /**
         * Creates a new 'split' row element for the modal.
         * This is the FIXED function.
         */
        function createSplitRow(split = {}) {
            const row = document.createElement('div');
            row.className = 'split-row grid grid-cols-12 gap-2 items-center';
            
            // 1. Build Category Options
            const categoryOptions = categories
                .sort((a,b) => a.name.localeCompare(b.name))
                .map(c => `<option value="${c.name}">${c.name}</option>`)
                .join('');
                
            // 2. Build Vendor Options
            const vendorOptions = vendors
                .sort((a,b) => a.name.localeCompare(b.name))
                .map(c => `<option value="${c.id}">${c.name}</option>`)
                .join('');
            
            // 3. Set innerHTML
            row.innerHTML = `
                <div class="col-span-5">
                    <label class="text-xs text-gray-500">Category</label>
                    <select class="split-category w-full p-2 border rounded-md shadow-sm">${categoryOptions}</select>
                </div>
                <div class="col-span-3">
                    <label class="text-xs text-gray-500">Vendor</label>
                    <select class="split-vendor w-full p-2 border rounded-md shadow-sm">
                        <option value="">-- None --</option>
                        ${vendorOptions}
                    </select>
                </div>
                <div class="col-span-3">
                    <label class="text-xs text-gray-500">Amount</label>
                    <input type="number" step="0.01" class="split-amount w-full p-2 border rounded-md shadow-sm" value="0.00">
                </div>
                <div class="col-span-1 flex items-end">
                    <button type="button" class="delete-split-btn text-red-500 hover:text-red-700 p-2">&times;</button>
                </div>
                <div class="col-span-12">
                     <label class="text-xs text-gray-500">Description</label>
                     <input type="text" class="split-description w-full p-2 border rounded-md shadow-sm">
                </div>
            `;
            
            // 4. Set values from the split object
            const categorySelect = row.querySelector('.split-category');
            const vendorSelect = row.querySelector('.split-vendor');
            const amountInput = row.querySelector('.split-amount');
            const descriptionInput = row.querySelector('.split-description');

            if (split.category) categorySelect.value = split.category;
            if (split.vendorId) vendorSelect.value = split.vendorId;
            if (split.amount) amountInput.value = split.amount.toFixed(2);
            if (split.description) descriptionInput.value = split.description;
            
            // Add listeners
            amountInput.addEventListener('input', validateSplitAmounts);
            row.querySelector('.delete-split-btn').addEventListener('click', () => {
                row.remove();
                validateSplitAmounts();
            });

            return row;
        }
        
        function validateSplitAmounts() {
            const total = parseFloat(document.getElementById('splitTxTotal').value);
            const allSplitRows = document.querySelectorAll('#splitsContainer .split-row');
            let currentSplitSum = 0;
            
            allSplitRows.forEach(row => {
                currentSplitSum += parseFloat(row.querySelector('.split-amount').value) || 0;
            });
            
            const remaining = total - currentSplitSum;
            const remainingEl = document.getElementById('splitModalRemaining');
            const saveBtn = document.getElementById('saveSplitsBtn');

            remainingEl.textContent = `Remaining: ${remaining.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}`;
            
            // Use a small tolerance for floating point errors
            if (Math.abs(remaining) < 0.001) {
                remainingEl.classList.remove('text-red-600');
                remainingEl.classList.add('text-green-600');
                saveBtn.disabled = false;
            } else {
                remainingEl.classList.remove('text-green-600');
                remainingEl.classList.add('text-red-600');
                saveBtn.disabled = true;
            }
        }

        async function showSplitTransactionModal(txId) {
            const tx = transactions.find(t => t.id == txId);
            if (!tx) return;
            
            // Store transaction data
            document.getElementById('splitTxId').value = tx.id;
            document.getElementById('splitTxTotal').value = tx.amount;
            
            // Set modal header
            document.getElementById('splitModalTitle').textContent = `Edit / Split Transaction`;
            document.getElementById('splitModalDescription').textContent = `${new Date(tx.date).toLocaleDateString()} - ${tx.description}`;
            document.getElementById('splitModalTotal').textContent = `Total: ${tx.amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}`;
            
            // Fetch and render splits
            const splitsContainer = document.getElementById('splitsContainer');
            splitsContainer.innerHTML = '<div class="spinner"></div>'; // Show loading
            
            try {
                // --- FIX: Ensure categories and vendors are loaded before opening modal ---
                if (categories.length === 0 || vendors.length === 0) {
                    console.log("Categories or vendors empty, re-fetching...");
                    await loadCategories();
                    await loadVendors();
                }

                const splits = await apiFetch(`/transactions/${tx.id}/splits`);
                splitsContainer.innerHTML = ''; // Clear spinner
                
                if (splits.length === 0) {
                    // This shouldn't happen, but as a fallback, create one default split
                    splitsContainer.appendChild(createSplitRow({
                        description: tx.description,
                        amount: tx.amount,
                        category: 'Expense - Uncategorized'
                    }));
                } else {
                    splits.forEach(split => {
                        splitsContainer.appendChild(createSplitRow(split));
                    });
                }
                
                validateSplitAmounts();
                document.getElementById('editTxModal').classList.remove('hidden');
            } catch (error) {
                // This catch block will now *correctly* catch API errors
                console.error("Error fetching splits:", error);
                swal('Error', "Could not load transaction splits. API error: " + error.message, 'error');
            }
        }

        function closeEditTransactionModal() {
            document.getElementById('editTxModal').classList.add('hidden');
        }

        async function handleSaveSplits(e) {
            e.preventDefault();
            const transactionId = parseInt(document.getElementById('splitTxId').value, 10);
            const allSplitRows = document.querySelectorAll('#splitsContainer .split-row');
            
            if (isNaN(transactionId)) {
                alert('Error: Invalid transaction ID.');
                return;
            }

            let splitsPayload = [];
            allSplitRows.forEach(row => {
                const vendorIdValue = row.querySelector('.split-vendor').value;
                splitsPayload.push({
                    category: row.querySelector('.split-category').value,
                    vendorId: vendorIdValue ? parseInt(vendorIdValue, 10) : null,
                    description: row.querySelector('.split-description').value,
                    amount: parseFloat(row.querySelector('.split-amount').value)
                });
            });

            try {
                await apiFetch(`/transactions/${transactionId}/splits`, {
                    method: 'PUT',
                    body: JSON.stringify(splitsPayload)
                });
                closeEditTransactionModal();
                
                swal("Success", "Transaction saved!", "success");
                await loadTransactions(); // Refresh transactions
                
                await updateDashboard();

            } catch (error) {
                swal('Error', error.message, 'error');
            }
        }
        
        async function handleCreateRuleFromSplit() {
            // Use the first split row to create a rule
            const firstSplitRow = document.querySelector('#splitsContainer .split-row');
            if (!firstSplitRow) {
                swal('Error', "No split to create rule from.", 'error');
                return;
            }

            // --- FIX 2: Get description robustly ---
            const txId = document.getElementById('splitTxId').value;
            const tx = transactions.find(t => t.id == txId);
            if (!tx) {
                swal('Error', "Error: Could not find parent transaction.", 'error');
                return;
            }
            const description = tx.description;
            const category = firstSplitRow.querySelector('.split-category').value;
            
            swal({
                title: "Create a new rule",
                text: `Create rule for "${description}"?\n\nEnter the part of the description to use as a keyword:`, 
                content: {
                    element: "input",
                    attributes: {
                        placeholder: "Type your keyword here",
                        value: description,
                    },
                },
            })
            .then(async (keyword) => {
                if (keyword) {
                    try {
                        await apiFetch('/rules', {
                            method: 'POST',
                            body: JSON.stringify({ keyword, category })
                        });
                        await loadRules();
                        swal('Success', `Rule created: If description contains "${keyword}", set to "${category}".`, 'success');
                    } catch (error) {
                        console.error("Error creating rule:", error);
                        swal('Error', error.message, 'error');
                    }
                }
            });
        }

        async function deleteTransaction(txId) {
            swal({
                title: "Are you sure?",
                text: "Are you sure you want to delete this transaction (and all its splits) permanently?",
                icon: "warning",
                buttons: true,
                dangerMode: true,
            })
            .then(async (willDelete) => {
                if (willDelete) {
                    try {
                        await apiFetch(`/transactions/${txId}`, { method: 'DELETE' });
                        await loadTransactions(); // Full refresh
                        await updateDashboard();
                        swal("Poof! The transaction has been deleted!", {
                            icon: "success",
                        });
                    } catch (error) {
                        console.error("Error deleting transaction: ", error);
                        swal('Error', error.message, 'error');
                    }
                }
            });
        }
        
        // --- File Processing ---
        
        async function handleFiles(e) {
            e.preventDefault();
            const bankFile = document.getElementById('bankFile').files[0];
            const salesFile = document.getElementById('salesFile').files[0];
            
            if (!bankFile && !salesFile) {
                swal('Error', "Please select at least one file to upload.", 'error');
                return;
            }
            
            const formData = new FormData();
            if (bankFile) formData.append('bankFile', bankFile);
            if (salesFile) formData.append('salesFile', salesFile);
            
            showLoadingModal(true, "Uploading and processing files...");
            
            try {
                const result = await apiFetch('/upload', {
                    method: 'POST',
                    body: formData
                });
                
                swal('Success', result, 'success');
                document.getElementById('uploadForm').reset();
                await loadTransactions(); // Refresh data
                await updateDashboard(); // Refresh dashboard
                showView('transactions');

            } catch (error) {
                console.error("Error uploading files:", error);
                alert(error.message);
            } finally {
                showLoadingModal(false);
            }
        }
        

        // --- UI Navigation ---
        function showView(viewId) {
            document.querySelectorAll('main > section').forEach(section => {
                section.classList.add('hidden');
            });
            document.querySelectorAll('nav a').forEach(a => {
                a.classList.remove('bg-blue-700', 'text-white');
                a.classList.add('text-blue-100', 'hover:bg-blue-600');
            });
            
            const activeView = document.getElementById(viewId);
            const activeLink = document.querySelector(`nav a[data-view="${viewId}"]`);
            
            if (activeView) activeView.classList.remove('hidden');
            if (activeLink) {
                activeLink.classList.add('bg-blue-700', 'text-white');
                activeLink.classList.remove('text-blue-100', 'hover:bg-blue-600');
            }

            // Refresh dashboard data only when switching to it
            if (viewId === 'dashboard') {
                updateDashboard();
            }
        }
        
        function showLoadingModal(show, text = 'Loading...') {
            const modal = document.getElementById('loadingModal');
            const textEl = document.getElementById('loadingModalText');
            if (show) {
                textEl.textContent = text;
                modal.classList.remove('hidden');
            } else {
                modal.classList.add('hidden');
            }
        }
        
        // --- Initial App Load ---
        document.addEventListener('DOMContentLoaded', () => {
            // Auth form toggling
            document.getElementById('toggleAuth').onclick = (e) => {
                e.preventDefault();
                const isLogin = document.getElementById('loginForm').classList.contains('hidden');
                toggleAuthForm(isLogin);
            };

            // Auth form submission
            document.getElementById('loginForm').onsubmit = handleLogin;
            document.getElementById('registerForm').onsubmit = handleRegister;
            
            // App Navigation
            document.querySelectorAll('nav a').forEach(a => {
                a.onclick = (e) => {
                    e.preventDefault();
                    if(e.target.id === 'logoutButton') return logout();
                    showView(e.target.dataset.view);
                }
            });
            
            // --- Event Listeners ---
            document.getElementById('uploadForm').onsubmit = handleFiles;
            document.getElementById('categoryForm').onsubmit = addCategory;
            document.getElementById('vendorForm').onsubmit = addVendor;
            document.getElementById('ruleForm').onsubmit = addRule;
            document.getElementById('transactionFilter').onchange = renderTransactions;
            document.getElementById('transactionSearch').oninput = renderTransactions;
            document.getElementById('generateReportBtn').onclick = generateReport;
            document.getElementById('exportReportBtn').onclick = exportReport;
            document.getElementById('applyAllRulesBtn').onclick = applyAllRules;

            document.getElementById('dateFilterSelect').onchange = (e) => {
                const customPicker = document.getElementById('customDateRangePicker');
                if (e.target.value === 'custom') {
                    customPicker.classList.remove('hidden');
                    customPicker.classList.add('flex');
                } else {
                    customPicker.classList.add('hidden');
                    customPicker.classList.remove('flex');
                }
            };

            document.getElementById('filterByDateBtn').onclick = () => {
                const filterType = document.getElementById('dateFilterSelect').value;
                transactionDateFilter = filterType;

                if (filterType === 'custom') {
                    const startDate = document.getElementById('startDate').value;
                    const endDate = document.getElementById('endDate').value;
                    if (startDate && endDate) {
                        customDateRange = { start: new Date(startDate), end: new Date(endDate) };
                    } else {
                        swal('Error', 'Please select a start and end date for the custom range.', 'error');
                        return;
                    }
                }
                renderTransactions();
            };

            // Mobile menu
            const sidebar = document.getElementById('sidebar');
            const mobileMenuBtn = document.getElementById('mobileMenuBtn');

            if (mobileMenuBtn) {
                mobileMenuBtn.onclick = () => {
                    sidebar.classList.toggle('-translate-x-full');
                    sidebar.classList.toggle('hidden');
                };
            }

            // Close sidebar when a nav link is clicked on mobile
            sidebar.querySelectorAll('a').forEach(link => {
                link.addEventListener('click', () => {
                    if (window.innerWidth < 768) { // md breakpoint
                        sidebar.classList.add('-translate-x-full');
                        sidebar.classList.add('hidden');
                    }
                });
            });

            // Transaction table sorting
            document.querySelectorAll('.sortable-header').forEach(th => {
                th.onclick = handleSort;
            });
            
            // Edit/Split Tx Modal
            document.getElementById('closeTxModalBtn').onclick = closeEditTransactionModal;
            document.getElementById('saveSplitsBtn').onclick = handleSaveSplits;
            document.getElementById('createRuleFromSplit').onclick = handleCreateRuleFromSplit;
            document.getElementById('addSplitBtn').onclick = () => {
                document.getElementById('splitsContainer').appendChild(createSplitRow());
            };
            
            // Check if already logged in
            if (jwtToken) {
                document.getElementById('authView').classList.add('hidden');
                document.getElementById('appContainer').classList.remove('hidden');
                showView('dashboard');
                loadAllData();
            } else {
                document.getElementById('authView').classList.remove('hidden');
                document.getElementById('appContainer').classList.add('hidden');
            }
        });
