<?php
/**
 * Finances - Bank Transactions
 * 
 * Import UI + import history.
 *
 * @package Freelance_Studio
 */

if (!defined('ABSPATH')) {
    exit;
}

$stats = FS_Transaction::get_stats();
$has_transactions = ($stats && $stats->total > 0);
$batches = $has_transactions ? FS_Transaction::get_import_batches() : array();
?>

<?php if (isset($_GET['imported'])): ?>
    <div class="notice notice-success is-dismissible">
        <p><?php echo esc_html(sprintf(
            __('%1$d transactions imported, %2$d duplicates skipped.', 'freelance-studio'),
            intval($_GET['imported']),
            intval($_GET['skipped'] ?? 0)
        )); ?></p>
    </div>
<?php endif; ?>

<?php if (isset($_GET['deleted_batch'])): ?>
    <div class="notice notice-success is-dismissible">
        <p><?php esc_html_e('Import batch deleted.', 'freelance-studio'); ?></p>
    </div>
<?php endif; ?>

<!-- Import Section -->
<div class="fs-settings-section" id="fs-txn-import-section">
    <div class="fs-section-header" style="display:flex; justify-content:space-between; align-items:center;">
        <div>
            <h2><?php esc_html_e('Import Bank Transactions', 'freelance-studio'); ?></h2>
            <p class="description"><?php esc_html_e('Upload a CSV statement from your bank or credit card to import transactions.', 'freelance-studio'); ?></p>
        </div>
        <?php if ($has_transactions): ?>
            <button type="button" class="fs-btn fs-btn-secondary fs-btn-small" id="fs-txn-toggle-import" style="white-space:nowrap;">
                <span class="dashicons dashicons-upload" style="margin-right:4px;"></span><?php esc_html_e('New Import', 'freelance-studio'); ?>
            </button>
        <?php endif; ?>
    </div>

    <div id="fs-txn-import-flow" <?php echo $has_transactions ? 'style="display:none;"' : ''; ?>>

        <!-- Bank Preset -->
        <div class="fs-txn-bank-presets" style="margin-bottom:16px;">
            <label><strong><?php esc_html_e('Bank/Card (optional):', 'freelance-studio'); ?></strong></label>
            <select id="fs-txn-bank-preset" style="margin-left:8px;">
                <option value=""><?php esc_html_e('Auto-detect columns', 'freelance-studio'); ?></option>
                <option value="chase"><?php esc_html_e('Chase', 'freelance-studio'); ?></option>
                <option value="bofa"><?php esc_html_e('Bank of America', 'freelance-studio'); ?></option>
                <option value="wells_fargo"><?php esc_html_e('Wells Fargo', 'freelance-studio'); ?></option>
                <option value="capital_one"><?php esc_html_e('Capital One', 'freelance-studio'); ?></option>
                <option value="citi"><?php esc_html_e('Citi', 'freelance-studio'); ?></option>
                <option value="amex"><?php esc_html_e('American Express', 'freelance-studio'); ?></option>
                <option value="paypal"><?php esc_html_e('PayPal', 'freelance-studio'); ?></option>
                <option value="other"><?php esc_html_e('Other', 'freelance-studio'); ?></option>
            </select>
        </div>

        <!-- Step 1: Upload -->
        <div id="fs-txn-step-upload">
            <div class="fs-import-dropzone" id="fs-txn-dropzone">
                <div class="fs-import-dropzone-content">
                    <span class="dashicons dashicons-upload"></span>
                    <p><?php esc_html_e('Drag & drop your bank CSV here', 'freelance-studio'); ?></p>
                    <p class="fs-import-dropzone-or"><?php esc_html_e('or', 'freelance-studio'); ?></p>
                    <label class="fs-btn fs-btn-secondary">
                        <?php esc_html_e('Browse Files', 'freelance-studio'); ?>
                        <input type="file" accept=".csv" id="fs-txn-file" style="display: none;">
                    </label>
                </div>
                <div class="fs-import-dropzone-selected" style="display: none;">
                    <span class="dashicons dashicons-media-spreadsheet"></span>
                    <span class="fs-import-filename"></span>
                    <button type="button" class="fs-btn-link fs-import-remove-file"><?php esc_html_e('Remove', 'freelance-studio'); ?></button>
                </div>
            </div>
            <p class="description" style="margin-top: 10px;">
                <?php esc_html_e('Required columns: Date, Description, Amount (or separate Debit/Credit columns). Most bank CSV exports work automatically.', 'freelance-studio'); ?>
            </p>
        </div>

        <!-- Step 2: Column Mapping -->
        <div id="fs-txn-step-mapping" style="display:none;">
            <h3><?php esc_html_e('Column Mapping', 'freelance-studio'); ?></h3>
            <p class="description"><?php esc_html_e('Verify the column mappings. We auto-detected based on your headers.', 'freelance-studio'); ?></p>
            <table class="widefat fs-import-mapping-table" id="fs-txn-mapping-table">
                <thead><tr>
                    <th><?php esc_html_e('CSV Column', 'freelance-studio'); ?></th>
                    <th><?php esc_html_e('Maps To', 'freelance-studio'); ?></th>
                    <th><?php esc_html_e('Sample Data', 'freelance-studio'); ?></th>
                </tr></thead>
                <tbody></tbody>
            </table>
            <div style="margin-top: 16px; display: flex; gap: 10px;">
                <button type="button" class="fs-btn fs-btn-secondary" id="fs-txn-back-to-upload"><?php esc_html_e('Back', 'freelance-studio'); ?></button>
                <button type="button" class="fs-btn fs-btn-primary" id="fs-txn-preview-btn"><?php esc_html_e('Preview Import', 'freelance-studio'); ?></button>
            </div>
        </div>

        <!-- Step 3: Preview -->
        <div id="fs-txn-step-preview" style="display:none;">
            <h3><?php esc_html_e('Preview', 'freelance-studio'); ?></h3>
            <div class="fs-import-preview-stats">
                <div class="fs-import-stat-card"><span class="fs-import-stat-number" id="fs-txn-stat-total">0</span><span class="fs-import-stat-label"><?php esc_html_e('Transactions', 'freelance-studio'); ?></span></div>
                <div class="fs-import-stat-card"><span class="fs-import-stat-number" id="fs-txn-stat-credits">0</span><span class="fs-import-stat-label"><?php esc_html_e('Deposits', 'freelance-studio'); ?></span></div>
                <div class="fs-import-stat-card"><span class="fs-import-stat-number" id="fs-txn-stat-debits">0</span><span class="fs-import-stat-label"><?php esc_html_e('Withdrawals', 'freelance-studio'); ?></span></div>
                <div class="fs-import-stat-card"><span class="fs-import-stat-number" id="fs-txn-stat-duplicates">0</span><span class="fs-import-stat-label"><?php esc_html_e('Duplicates (skip)', 'freelance-studio'); ?></span></div>
                <div class="fs-import-stat-card fs-import-stat-total"><span class="fs-import-stat-number" id="fs-txn-stat-date-range" style="font-size:14px;">-</span><span class="fs-import-stat-label"><?php esc_html_e('Date Range', 'freelance-studio'); ?></span></div>
            </div>
            <div class="fs-import-preview-table-wrap" style="margin-top: 20px; max-height: 400px; overflow-y: auto;">
                <table class="widefat" id="fs-txn-preview-table">
                    <thead><tr>
                        <th><?php esc_html_e('Date', 'freelance-studio'); ?></th>
                        <th><?php esc_html_e('Description', 'freelance-studio'); ?></th>
                        <th class="text-right"><?php esc_html_e('Amount', 'freelance-studio'); ?></th>
                        <th><?php esc_html_e('Ref', 'freelance-studio'); ?></th>
                        <th><?php esc_html_e('Status', 'freelance-studio'); ?></th>
                    </tr></thead>
                    <tbody></tbody>
                </table>
            </div>
            <div style="margin-top: 20px; display: flex; gap: 10px;">
                <button type="button" class="fs-btn fs-btn-secondary" id="fs-txn-back-to-mapping"><?php esc_html_e('Back', 'freelance-studio'); ?></button>
                <button type="button" class="fs-btn fs-btn-primary" id="fs-txn-run-import"><?php esc_html_e('Import Transactions', 'freelance-studio'); ?></button>
            </div>
        </div>

        <!-- Step 4: Progress -->
        <div id="fs-txn-step-progress" style="display:none;">
            <h3><?php esc_html_e('Importing...', 'freelance-studio'); ?></h3>
            <div class="fs-import-progress-wrap">
                <div class="fs-import-progress-bar"><div class="fs-import-progress-fill" id="fs-txn-progress-fill" style="width: 0%"></div></div>
                <p class="fs-import-progress-text" id="fs-txn-progress-text"><?php esc_html_e('Starting import...', 'freelance-studio'); ?></p>
            </div>
        </div>

        <!-- Step 5: Results -->
        <div id="fs-txn-step-results" style="display:none;">
            <h3><?php esc_html_e('Import Complete', 'freelance-studio'); ?></h3>
            <div id="fs-txn-results-summary"></div>
            <div style="margin-top: 20px;">
                <button type="button" class="fs-btn fs-btn-secondary" id="fs-txn-import-another"><?php esc_html_e('Import Another File', 'freelance-studio'); ?></button>
            </div>
        </div>
    </div>
</div>

<?php if ($has_transactions): ?>
<!-- Import History -->
<div class="fs-settings-section">
    <h2><?php esc_html_e('Import History', 'freelance-studio'); ?></h2>
    <div class="fs-import-preview-stats" style="margin-bottom: 20px;">
        <div class="fs-import-stat-card"><span class="fs-import-stat-number"><?php echo intval($stats->total); ?></span><span class="fs-import-stat-label"><?php esc_html_e('Total', 'freelance-studio'); ?></span></div>
        <div class="fs-import-stat-card"><span class="fs-import-stat-number"><?php echo intval($stats->unmatched); ?></span><span class="fs-import-stat-label"><?php esc_html_e('Unmatched', 'freelance-studio'); ?></span></div>
        <div class="fs-import-stat-card"><span class="fs-import-stat-number"><?php echo intval($stats->matched); ?></span><span class="fs-import-stat-label"><?php esc_html_e('Matched', 'freelance-studio'); ?></span></div>
        <div class="fs-import-stat-card"><span class="fs-import-stat-number"><?php echo intval($stats->ignored); ?></span><span class="fs-import-stat-label"><?php esc_html_e('Ignored', 'freelance-studio'); ?></span></div>
    </div>
    <?php if (!empty($batches)): ?>
    <div class="fs-table-responsive">
        <table class="widefat fs-table">
            <thead><tr>
                <th><?php esc_html_e('Bank', 'freelance-studio'); ?></th>
                <th><?php esc_html_e('Date Range', 'freelance-studio'); ?></th>
                <th class="text-right"><?php esc_html_e('Transactions', 'freelance-studio'); ?></th>
                <th class="text-right"><?php esc_html_e('Unmatched', 'freelance-studio'); ?></th>
                <th><?php esc_html_e('Imported', 'freelance-studio'); ?></th>
                <th><?php esc_html_e('Actions', 'freelance-studio'); ?></th>
            </tr></thead>
            <tbody>
                <?php foreach ($batches as $batch): ?>
                <tr>
                    <td><?php echo esc_html($batch->source_bank ?: __('Unknown', 'freelance-studio')); ?></td>
                    <td><?php
                        echo esc_html(gmdate('M j, Y', strtotime($batch->date_from)));
                        if ($batch->date_from !== $batch->date_to) echo ' – ' . esc_html(gmdate('M j, Y', strtotime($batch->date_to)));
                    ?></td>
                    <td class="text-right"><?php echo intval($batch->transaction_count); ?></td>
                    <td class="text-right"><?php echo intval($batch->unmatched_count); ?></td>
                    <td><?php echo esc_html(gmdate('M j, Y', strtotime($batch->imported_at))); ?></td>
                    <td>
                        <a href="<?php echo esc_url(wp_nonce_url(admin_url('admin.php?page=fs-finances&tab=transactions&delete_batch=' . urlencode($batch->import_batch)), 'delete_batch_' . $batch->import_batch)); ?>" class="fs-delete-link" onclick="return confirm('<?php esc_attr_e('Delete this entire import batch?', 'freelance-studio'); ?>');"><?php esc_html_e('Delete', 'freelance-studio'); ?></a>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <?php endif; ?>
</div>
<?php endif; ?>

<?php if ($has_transactions): ?>
<!-- Transaction Review Section -->
<div class="fs-settings-section" id="fs-txn-review-section">
    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
        <h2 style="margin:0;"><?php esc_html_e('Review Transactions', 'freelance-studio'); ?></h2>
        <div style="display:flex; gap:8px;">
            <button type="button" class="fs-btn fs-btn-secondary fs-btn-small" id="fs-txn-run-rules" title="<?php esc_attr_e('Apply personal rules to all unmatched transactions', 'freelance-studio'); ?>">
                <span class="dashicons dashicons-controls-play" style="margin-right:4px;"></span><?php esc_html_e('Run Rules', 'freelance-studio'); ?>
            </button>
            <button type="button" class="fs-btn fs-btn-secondary fs-btn-small" id="fs-txn-open-rules">
                <span class="dashicons dashicons-admin-generic" style="margin-right:4px;"></span><?php esc_html_e('Personal Rules', 'freelance-studio'); ?>
            </button>
        </div>
    </div>

    <!-- Filter Tabs -->
    <div class="fs-tab-nav fs-txn-filter-tabs">
        <a href="#" class="fs-tab active" data-filter="all">
            <?php esc_html_e('All', 'freelance-studio'); ?> <span class="fs-tab-count"><?php echo intval($stats->total); ?></span>
        </a>
        <a href="#" class="fs-tab" data-filter="unmatched">
            <?php esc_html_e('Unmatched', 'freelance-studio'); ?> <span class="fs-tab-count"><?php echo intval($stats->unmatched); ?></span>
        </a>
        <a href="#" class="fs-tab" data-filter="matched">
            <?php esc_html_e('Matched', 'freelance-studio'); ?> <span class="fs-tab-count"><?php echo intval($stats->matched); ?></span>
        </a>
        <a href="#" class="fs-tab" data-filter="ignored">
            <?php esc_html_e('Ignored', 'freelance-studio'); ?> <span class="fs-tab-count"><?php echo intval($stats->ignored); ?></span>
        </a>
    </div>

    <!-- Transaction Table -->
    <?php
    $all_transactions = FS_Transaction::get_all(array('limit' => 200, 'orderby' => 'transaction_date', 'order' => 'DESC'));
    $categories = FS_Expense::get_categories();
    $projects = FS_Project::get_for_dropdown();
    ?>
    <div class="fs-table-responsive">
        <table class="widefat fs-table fs-txn-review-table" id="fs-txn-review-table">
            <thead>
                <tr>
                    <th style="width:100px;"><?php esc_html_e('Date', 'freelance-studio'); ?></th>
                    <th><?php esc_html_e('Description', 'freelance-studio'); ?></th>
                    <th class="text-right" style="width:120px;"><?php esc_html_e('Amount', 'freelance-studio'); ?></th>
                    <th style="width:130px;"><?php esc_html_e('Category', 'freelance-studio'); ?></th>
                    <th style="width:100px;"><?php esc_html_e('Status', 'freelance-studio'); ?></th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($all_transactions as $txn):
                    $amt_class = $txn->amount >= 0 ? 'fs-amount-positive' : 'fs-amount-negative';
                    $amt_str = ($txn->amount >= 0 ? '+' : '-') . '$' . number_format(abs($txn->amount), 2);
                    $status_class = 'status-pending';
                    $status_label = __('Unmatched', 'freelance-studio');
                    if ($txn->status === 'matched') { $status_class = 'status-completed'; $status_label = __('Matched', 'freelance-studio'); }
                    elseif ($txn->status === 'ignored') { $status_class = 'status-draft'; $status_label = __('Ignored', 'freelance-studio'); }
                ?>
                <tr class="fs-txn-row <?php echo $txn->status === 'ignored' ? 'fs-row-ignored' : ''; ?>" 
                    data-id="<?php echo intval($txn->id); ?>" 
                    data-status="<?php echo esc_attr($txn->status); ?>"
                    data-type="<?php echo esc_attr($txn->type); ?>">
                    <td><?php echo esc_html(gmdate('M j, Y', strtotime($txn->transaction_date))); ?></td>
                    <td class="fs-txn-desc"><?php echo esc_html(mb_substr($txn->description, 0, 80)); ?></td>
                    <td class="text-right <?php echo esc_attr($amt_class); ?>"><?php echo esc_html($amt_str); ?></td>
                    <td>
                        <?php if ($txn->category): ?>
                            <span class="fs-category-badge"><?php echo esc_html($txn->category); ?></span>
                        <?php else: ?>
                            <span class="fs-muted">—</span>
                        <?php endif; ?>
                    </td>
                    <td><span class="fs-status-badge <?php echo esc_attr($status_class); ?>"><?php echo esc_html($status_label); ?></span></td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
</div>

<!-- Sidebar Panel Overlay -->
<div class="fs-txn-panel-overlay" id="fs-txn-panel-overlay"></div>

<!-- Sidebar Panel -->
<div class="fs-txn-panel" id="fs-txn-panel">
    <div class="fs-txn-panel-header">
        <h3><?php esc_html_e('Transaction Details', 'freelance-studio'); ?></h3>
        <button type="button" class="fs-txn-panel-close" id="fs-txn-panel-close">&times;</button>
    </div>
    <div class="fs-txn-panel-body" id="fs-txn-panel-body">
        <!-- Populated by JS -->
    </div>
</div>

<!-- Expense Creation Modal -->
<div class="fs-modal" id="fs-txn-expense-modal">
    <div class="fs-modal-content" style="max-width:500px;">
        <div class="fs-modal-header">
            <h3><?php esc_html_e('Create Expense', 'freelance-studio'); ?></h3>
            <button type="button" class="fs-modal-close">&times;</button>
        </div>
        <div class="fs-modal-body">
            <input type="hidden" id="fs-txn-expense-txn-id">
            <div class="fs-form-group" style="margin-bottom:16px;">
                <label for="fs-txn-expense-vendor"><?php esc_html_e('Vendor / Description', 'freelance-studio'); ?></label>
                <input type="text" id="fs-txn-expense-vendor" class="regular-text" style="width:100%;">
            </div>
            <div class="fs-form-group" style="margin-bottom:16px;">
                <label for="fs-txn-expense-category"><?php esc_html_e('Category', 'freelance-studio'); ?></label>
                <select id="fs-txn-expense-category" style="width:100%;">
                    <option value=""><?php esc_html_e('Select category...', 'freelance-studio'); ?></option>
                    <?php foreach ($categories as $key => $label): ?>
                        <option value="<?php echo esc_attr($key); ?>"><?php echo esc_html($label); ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div class="fs-form-group" style="margin-bottom:16px;">
                <label for="fs-txn-expense-project"><?php esc_html_e('Project (optional)', 'freelance-studio'); ?></label>
                <select id="fs-txn-expense-project" style="width:100%;">
                    <option value="0"><?php esc_html_e('None', 'freelance-studio'); ?></option>
                    <?php foreach ($projects as $proj): ?>
                        <option value="<?php echo intval($proj->id); ?>"><?php echo esc_html($proj->name); ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div class="fs-form-group">
                <label><?php esc_html_e('Amount', 'freelance-studio'); ?></label>
                <p class="fs-txn-expense-amount-display" style="font-size:18px; font-weight:600; color:var(--fs-gray-800);"></p>
                <p class="fs-txn-expense-date-display description"></p>
            </div>
        </div>
        <div class="fs-modal-footer">
            <button type="button" class="fs-btn fs-btn-secondary fs-modal-close"><?php esc_html_e('Cancel', 'freelance-studio'); ?></button>
            <button type="button" class="fs-btn fs-btn-primary" id="fs-txn-expense-save"><?php esc_html_e('Create Expense & Link', 'freelance-studio'); ?></button>
        </div>
    </div>
</div>

<!-- Personal Rules Modal -->
<div class="fs-modal" id="fs-txn-rules-modal">
    <div class="fs-modal-content" style="max-width:550px;">
        <div class="fs-modal-header">
            <h3><?php esc_html_e('Personal Transaction Rules', 'freelance-studio'); ?></h3>
            <button type="button" class="fs-modal-close">&times;</button>
        </div>
        <div class="fs-modal-body">
            <p class="description" style="margin-bottom:16px;"><?php esc_html_e('Transactions with descriptions matching any of these keywords will be automatically marked as personal (ignored). Matching is case-insensitive.', 'freelance-studio'); ?></p>
            
            <div class="fs-txn-rules-add" style="display:flex; gap:8px; margin-bottom:16px;">
                <input type="text" id="fs-txn-rule-input" class="regular-text" style="flex:1;" placeholder="<?php esc_attr_e('e.g., Netflix, Kroger, Starbucks...', 'freelance-studio'); ?>">
                <button type="button" class="fs-btn fs-btn-primary fs-btn-small" id="fs-txn-rule-add"><?php esc_html_e('Add', 'freelance-studio'); ?></button>
            </div>

            <div id="fs-txn-rules-list" class="fs-txn-rules-list">
                <!-- Populated by JS -->
            </div>
            
            <div id="fs-txn-rules-empty" class="fs-empty-state" style="display:none; padding:20px;">
                <p><?php esc_html_e('No personal rules yet. Add keywords above to auto-ignore matching transactions.', 'freelance-studio'); ?></p>
            </div>
        </div>
        <div class="fs-modal-footer">
            <button type="button" class="fs-btn fs-btn-secondary fs-modal-close"><?php esc_html_e('Close', 'freelance-studio'); ?></button>
        </div>
    </div>
</div>
<?php endif; ?>

<script>
jQuery(document).ready(function($) {
    var txnData = { rows: [], headers: [], mapping: {}, file: null, parsedTransactions: [] };

    var bankMaps = {
        'chase': { 'transaction date': 'date', 'post date': 'skip', 'description': 'description', 'category': 'skip', 'type': 'skip', 'amount': 'amount', 'memo': 'reference' },
        'bofa': { 'date': 'date', 'description': 'description', 'amount': 'amount', 'running bal.': 'skip' },
        'wells_fargo': { 'date': 'date', 'amount': 'amount', 'star': 'skip', 'check number': 'reference', 'description': 'description' },
        'capital_one': { 'account number': 'skip', 'transaction date': 'date', 'posted date': 'skip', 'card no.': 'skip', 'transaction description': 'description', 'description': 'description', 'transaction type': 'type', 'category': 'skip', 'transaction amount': 'amount', 'debit': 'debit', 'credit': 'credit', 'balance': 'skip' },
        'citi': { 'status': 'skip', 'date': 'date', 'description': 'description', 'debit': 'debit', 'credit': 'credit' },
        'amex': { 'date': 'date', 'description': 'description', 'amount': 'amount', 'extended details': 'skip', 'appears on your statement as': 'skip', 'address': 'skip', 'city/state': 'skip', 'zip code': 'skip', 'country': 'skip', 'reference': 'reference', 'category': 'skip' },
        'paypal': { 'date': 'date', 'name': 'description', 'type': 'skip', 'status': 'skip', 'currency': 'skip', 'gross': 'amount', 'fee': 'skip', 'net': 'skip', 'from email address': 'skip', 'to email address': 'skip', 'transaction id': 'reference', 'item title': 'skip' }
    };

    var genericAutoMap = {
        'date': 'date', 'transaction date': 'date', 'post date': 'date', 'posted date': 'date', 'trans date': 'date', 'posting date': 'date',
        'description': 'description', 'transaction description': 'description', 'memo': 'description', 'name': 'description', 'payee': 'description', 'merchant': 'description', 'details': 'description',
        'amount': 'amount', 'transaction amount': 'amount', 'total': 'amount', 'gross': 'amount', 'net': 'amount',
        'type': 'type', 'transaction type': 'type',
        'debit': 'debit', 'withdrawal': 'debit', 'withdrawals': 'debit', 'payment': 'debit',
        'credit': 'credit', 'deposit': 'credit', 'deposits': 'credit',
        'check': 'reference', 'check number': 'reference', 'check no': 'reference', 'reference': 'reference', 'reference number': 'reference', 'ref': 'reference', 'transaction id': 'reference', 'confirmation': 'reference',
        'account number': 'skip', 'account': 'skip', 'balance': 'skip', 'running bal.': 'skip', 'running balance': 'skip', 'category': 'skip', 'card no.': 'skip', 'card number': 'skip', 'currency': 'skip', 'status': 'skip'
    };

    var txnFields = {
        'date': '<?php esc_html_e("Transaction Date", "freelance-studio"); ?>',
        'description': '<?php esc_html_e("Description", "freelance-studio"); ?>',
        'amount': '<?php esc_html_e("Amount (single column)", "freelance-studio"); ?>',
        'type': '<?php esc_html_e("Type (Credit/Debit indicator)", "freelance-studio"); ?>',
        'debit': '<?php esc_html_e("Debit / Withdrawal", "freelance-studio"); ?>',
        'credit': '<?php esc_html_e("Credit / Deposit", "freelance-studio"); ?>',
        'reference': '<?php esc_html_e("Reference / Check #", "freelance-studio"); ?>',
        'skip': '<?php esc_html_e("— Skip —", "freelance-studio"); ?>'
    };

    function parseCSV(text) {
        var lines = [], currentLine = [], currentField = '', inQuotes = false;
        for (var i = 0; i < text.length; i++) {
            var c = text[i], next = text[i + 1];
            if (inQuotes) {
                if (c === '"' && next === '"') { currentField += '"'; i++; }
                else if (c === '"') { inQuotes = false; }
                else { currentField += c; }
            } else {
                if (c === '"') { inQuotes = true; }
                else if (c === ',') { currentLine.push(currentField.trim()); currentField = ''; }
                else if (c === '\n' || (c === '\r' && next === '\n')) {
                    currentLine.push(currentField.trim()); currentField = '';
                    if (currentLine.length > 1 || currentLine[0] !== '') lines.push(currentLine);
                    currentLine = []; if (c === '\r') i++;
                } else { currentField += c; }
            }
        }
        currentLine.push(currentField.trim());
        if (currentLine.length > 1 || currentLine[0] !== '') lines.push(currentLine);
        return lines;
    }

    function parseAmount(val) {
        if (!val) return 0;
        val = val.toString().replace(/[$,\s]/g, '').replace(/\((.+)\)/, '-$1');
        var num = parseFloat(val);
        return isNaN(num) ? 0 : num;
    }

    function parseDate(val) {
        if (!val) return null;
        val = val.trim();
        var m = val.match(/^(\d{4})-(\d{2})-(\d{2})$/);
        if (m) return val;
        m = val.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})$/);
        if (m) return m[3] + '-' + String(parseInt(m[1])).padStart(2, '0') + '-' + String(parseInt(m[2])).padStart(2, '0');
        m = val.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})$/);
        if (m) {
            var yr = parseInt(m[3]); yr = yr > 50 ? 1900 + yr : 2000 + yr;
            return yr + '-' + String(parseInt(m[1])).padStart(2, '0') + '-' + String(parseInt(m[2])).padStart(2, '0');
        }
        var d = new Date(val);
        if (!isNaN(d.getTime())) return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0');
        return null;
    }

    function getAutoMap() {
        var preset = $('#fs-txn-bank-preset').val();
        return (preset && bankMaps[preset]) ? bankMaps[preset] : genericAutoMap;
    }

    function applyAutoMap() {
        var autoMap = getAutoMap();
        txnData.mapping = {};
        txnData.headers.forEach(function(h, i) {
            txnData.mapping[i] = autoMap[h.toLowerCase().trim()] || 'skip';
        });
    }

    // Toggle import
    $('#fs-txn-toggle-import').on('click', function() {
        var $flow = $('#fs-txn-import-flow');
        $flow.is(':visible') ? $flow.slideUp() : $flow.slideDown();
    });

    $('#fs-txn-bank-preset').on('change', function() {
        if (txnData.headers.length > 0) { applyAutoMap(); if ($('#fs-txn-step-mapping').is(':visible')) showMappingStep(); }
    });

    // File handling
    function handleFile(file) {
        if (!file || !file.name.toLowerCase().endsWith('.csv')) { alert('Please select a CSV file.'); return; }
        txnData.file = file;
        $('#fs-txn-dropzone .fs-import-dropzone-content').hide();
        $('#fs-txn-dropzone .fs-import-dropzone-selected').show().find('.fs-import-filename').text(file.name);
        var reader = new FileReader();
        reader.onload = function(e) {
            var parsed = parseCSV(e.target.result);
            if (parsed.length < 2) { alert('CSV appears empty.'); return; }
            txnData.headers = parsed[0]; txnData.rows = parsed.slice(1);
            applyAutoMap(); showMappingStep();
        };
        reader.readAsText(file);
    }

    $('#fs-txn-file').on('change', function() { if (this.files.length) handleFile(this.files[0]); });
    var $dz = $('#fs-txn-dropzone');
    $dz.on('dragover dragenter', function(e) { e.preventDefault(); $(this).addClass('fs-import-dropzone-active'); })
       .on('dragleave drop', function(e) { e.preventDefault(); $(this).removeClass('fs-import-dropzone-active'); })
       .on('drop', function(e) { if (e.originalEvent.dataTransfer.files.length) handleFile(e.originalEvent.dataTransfer.files[0]); });
    $dz.find('.fs-import-remove-file').on('click', function() {
        txnData.file = null; txnData.rows = []; txnData.headers = [];
        $('#fs-txn-file').val('');
        $dz.find('.fs-import-dropzone-content').show(); $dz.find('.fs-import-dropzone-selected').hide();
        $('#fs-txn-step-mapping').hide(); $('#fs-txn-step-upload').show();
    });

    // Mapping
    function showMappingStep() {
        $('#fs-txn-step-upload').hide(); $('#fs-txn-step-mapping').show();
        var $tbody = $('#fs-txn-mapping-table tbody').empty();
        txnData.headers.forEach(function(header, i) {
            var $select = $('<select class="fs-txn-map-select" data-col="' + i + '">');
            Object.keys(txnFields).forEach(function(key) {
                var $opt = $('<option>').val(key).text(txnFields[key]);
                if (txnData.mapping[i] === key) $opt.prop('selected', true);
                $select.append($opt);
            });
            var sample = txnData.rows.length > 0 ? (txnData.rows[0][i] || '') : '';
            if (sample.length > 60) sample = sample.substring(0, 60) + '...';
            $tbody.append($('<tr>').append($('<td>').text(header), $('<td>').append($select), $('<td>').html('<code>' + $('<span>').text(sample).html() + '</code>')));
        });
    }
    $(document).on('change', '.fs-txn-map-select', function() { txnData.mapping[$(this).data('col')] = $(this).val(); });
    $('#fs-txn-back-to-upload').on('click', function() { $('#fs-txn-step-mapping').hide(); $('#fs-txn-step-upload').show(); });

    // Build transactions from rows
    function buildTransactions() {
        var colMap = {};
        Object.keys(txnData.mapping).forEach(function(ci) { var f = txnData.mapping[ci]; if (f !== 'skip') colMap[f] = parseInt(ci); });
        if (colMap.date === undefined || colMap.description === undefined) { alert('Date and Description columns are required.'); return null; }
        if (colMap.amount === undefined && colMap.debit === undefined && colMap.credit === undefined) { alert('Amount (or Debit/Credit) column is required.'); return null; }

        var transactions = [];
        txnData.rows.forEach(function(row) {
            var date = row[colMap.date] || '', desc = row[colMap.description] || '';
            if (!date || !desc) return;
            var parsedDate = parseDate(date);
            if (!parsedDate) return;
            var amount = 0;
            if (colMap.amount !== undefined) {
                amount = parseAmount(row[colMap.amount] || '0');
                // If there's a type indicator column, use it to determine sign
                if (colMap.type !== undefined) {
                    var typeVal = (row[colMap.type] || '').toString().toLowerCase().trim();
                    // Make amount positive first, then apply sign based on type
                    var absAmount = Math.abs(amount);
                    if (typeVal === 'debit' || typeVal === 'withdrawal' || typeVal === 'payment' || typeVal === 'sale' || typeVal === 'purchase') {
                        amount = -absAmount;
                    } else {
                        // credit, deposit, refund, etc. = positive
                        amount = absAmount;
                    }
                }
            } else {
                var deb = colMap.debit !== undefined ? parseAmount(row[colMap.debit] || '0') : 0;
                var cred = colMap.credit !== undefined ? parseAmount(row[colMap.credit] || '0') : 0;
                if (cred > 0) amount = cred;
                else if (deb > 0) amount = -deb;
                else if (deb < 0) amount = deb;
            }
            if (amount === 0) return;
            var ref = colMap.reference !== undefined ? (row[colMap.reference] || '') : '';
            transactions.push({ transaction_date: parsedDate, description: desc, amount: amount, bank_reference: ref, raw_data: JSON.stringify(row) });
        });
        return transactions;
    }

    // Preview
    $('#fs-txn-preview-btn').on('click', function() {
        var transactions = buildTransactions();
        if (!transactions || transactions.length === 0) { alert('No valid transactions found.'); return; }
        txnData.parsedTransactions = transactions;

        $.post(ajaxurl, {
            action: 'fs_check_transaction_duplicates',
            nonce: '<?php echo wp_create_nonce("fs_import_nonce"); ?>',
            transactions: JSON.stringify(transactions.map(function(t) { return { date: t.transaction_date, amount: t.amount, description: t.description }; }))
        }, function(response) {
            var dupes = new Set();
            if (response.success && response.data.duplicates) response.data.duplicates.forEach(function(k) { dupes.add(k); });

            var credits = 0, debits = 0, duplicates = 0;
            var minDate = transactions[0].transaction_date, maxDate = minDate;
            var $tbody = $('#fs-txn-preview-table tbody').empty();

            transactions.forEach(function(t) {
                var key = t.transaction_date + '|' + t.amount + '|' + t.description;
                var isDupe = dupes.has(key);
                if (isDupe) duplicates++;
                if (t.amount >= 0) credits++; else debits++;
                if (t.transaction_date < minDate) minDate = t.transaction_date;
                if (t.transaction_date > maxDate) maxDate = t.transaction_date;

                var amtCls = t.amount >= 0 ? 'fs-amount-positive' : 'fs-amount-negative';
                var amtStr = (t.amount >= 0 ? '+' : '-') + '$' + Math.abs(t.amount).toFixed(2);
                $tbody.append('<tr class="' + (isDupe ? 'fs-row-muted' : '') + '">' +
                    '<td>' + $('<span>').text(t.transaction_date).html() + '</td>' +
                    '<td>' + $('<span>').text(t.description.substring(0, 80)).html() + '</td>' +
                    '<td class="text-right ' + amtCls + '">' + amtStr + '</td>' +
                    '<td>' + $('<span>').text(t.bank_reference).html() + '</td>' +
                    '<td>' + (isDupe ? '<span class="fs-status-badge status-draft">Duplicate</span>' : '<span class="fs-status-badge status-active">New</span>') + '</td></tr>');
            });

            $('#fs-txn-stat-total').text(transactions.length - duplicates);
            $('#fs-txn-stat-credits').text(credits);
            $('#fs-txn-stat-debits').text(debits);
            $('#fs-txn-stat-duplicates').text(duplicates);
            var range = minDate; if (minDate !== maxDate) range += ' to ' + maxDate;
            $('#fs-txn-stat-date-range').text(range);

            $('#fs-txn-step-mapping').hide(); $('#fs-txn-step-preview').show();
        });
    });
    $('#fs-txn-back-to-mapping').on('click', function() { $('#fs-txn-step-preview').hide(); $('#fs-txn-step-mapping').show(); });

    // Import
    $('#fs-txn-run-import').on('click', function() {
        var transactions = txnData.parsedTransactions;
        if (!transactions || !transactions.length) return;
        $('#fs-txn-step-preview').hide(); $('#fs-txn-step-progress').show();

        var bankName = $('#fs-txn-bank-preset option:selected').text();
        if ($('#fs-txn-bank-preset').val() === '' || $('#fs-txn-bank-preset').val() === 'other') {
            bankName = txnData.file ? txnData.file.name.replace(/\.csv$/i, '') : '';
        }

        var batchSize = 50, total = transactions.length, offset = 0, imported = 0, skipped = 0;
        var batchId = 'import_' + Date.now();

        function runBatch() {
            var batch = transactions.slice(offset, offset + batchSize);
            if (!batch.length) { showResults(imported, skipped); return; }
            var pct = Math.round((offset / total) * 100);
            $('#fs-txn-progress-fill').css('width', pct + '%');
            $('#fs-txn-progress-text').text('Processing ' + offset + ' / ' + total + '...');

            $.post(ajaxurl, {
                action: 'fs_import_transactions_batch',
                nonce: '<?php echo wp_create_nonce("fs_import_nonce"); ?>',
                transactions: JSON.stringify(batch),
                import_batch: batchId,
                source_bank: bankName
            }, function(r) {
                if (r.success) { imported += r.data.imported; skipped += r.data.skipped; offset += batchSize; runBatch(); }
                else { alert('Import error: ' + (r.data || '')); }
            }).fail(function() { alert('Network error.'); });
        }
        runBatch();
    });

    function showResults(imported, skipped) {
        $('#fs-txn-progress-fill').css('width', '100%');
        setTimeout(function() {
            $('#fs-txn-step-progress').hide(); $('#fs-txn-step-results').show();
            $('#fs-txn-results-summary').html(
                '<div class="fs-import-preview-stats">' +
                '<div class="fs-import-stat-card"><span class="fs-import-stat-number">' + imported + '</span><span class="fs-import-stat-label"><?php esc_html_e("Imported", "freelance-studio"); ?></span></div>' +
                '<div class="fs-import-stat-card"><span class="fs-import-stat-number">' + skipped + '</span><span class="fs-import-stat-label"><?php esc_html_e("Skipped", "freelance-studio"); ?></span></div></div>'
            );
        }, 500);
    }
    $('#fs-txn-import-another').on('click', function() { location.reload(); });

    // ==============================
    // TRANSACTION REVIEW UI
    // ==============================
    var currentTxnId = null;

    // Filter tabs
    $('.fs-txn-filter-tabs .fs-tab').on('click', function(e) {
        e.preventDefault();
        $('.fs-txn-filter-tabs .fs-tab').removeClass('active');
        $(this).addClass('active');
        var filter = $(this).data('filter');
        $('#fs-txn-review-table tbody tr').each(function() {
            if (filter === 'all') { $(this).show(); }
            else { $(this).toggle($(this).data('status') === filter); }
        });
    });

    // Click row to open sidebar panel
    $(document).on('click', '.fs-txn-row', function() {
        var id = $(this).data('id');
        currentTxnId = id;
        $('.fs-txn-row').removeClass('fs-txn-row-active');
        $(this).addClass('fs-txn-row-active');
        loadPanel(id);
    });

    // Close panel
    $('#fs-txn-panel-close, #fs-txn-panel-overlay').on('click', closePanel);
    function closePanel() {
        $('#fs-txn-panel').removeClass('open');
        $('#fs-txn-panel-overlay').removeClass('open');
        $('.fs-txn-row').removeClass('fs-txn-row-active');
        currentTxnId = null;
    }

    function loadPanel(id) {
        var $body = $('#fs-txn-panel-body').html('<div style="text-align:center;padding:40px;"><span class="spinner is-active" style="float:none;"></span></div>');
        $('#fs-txn-panel, #fs-txn-panel-overlay').addClass('open');

        $.post(ajaxurl, {
            action: 'fs_get_transaction_details',
            nonce: fs_ajax.nonce,
            id: id
        }, function(r) {
            if (!r.success) { $body.html('<p>Error loading details.</p>'); return; }
            renderPanel(r.data);
        });
    }

    function renderPanel(data) {
        var t = data.transaction;
        var isDebit = t.type === 'debit';
        var amtClass = isDebit ? 'fs-amount-negative' : 'fs-amount-positive';
        var amtStr = (isDebit ? '-' : '+') + '$' + Math.abs(parseFloat(t.amount)).toFixed(2);

        var html = '<div class="fs-txn-panel-details">';
        html += '<div class="fs-txn-panel-amount ' + amtClass + '">' + amtStr + '</div>';
        html += '<div class="fs-txn-panel-field"><span class="fs-txn-panel-label"><?php esc_html_e("Date", "freelance-studio"); ?></span><span>' + t.transaction_date + '</span></div>';
        html += '<div class="fs-txn-panel-field"><span class="fs-txn-panel-label"><?php esc_html_e("Description", "freelance-studio"); ?></span><span>' + $('<span>').text(t.description).html() + '</span></div>';
        if (t.bank_reference) {
            html += '<div class="fs-txn-panel-field"><span class="fs-txn-panel-label"><?php esc_html_e("Reference", "freelance-studio"); ?></span><span>' + $('<span>').text(t.bank_reference).html() + '</span></div>';
        }
        html += '</div>';

        // Status-specific content
        if (t.status === 'matched' && data.linked) {
            html += renderMatchedSection(data.linked, t);
        } else if (t.status === 'ignored') {
            html += '<div class="fs-txn-panel-section">';
            html += '<p class="fs-muted"><?php esc_html_e("Marked as personal — not a business transaction.", "freelance-studio"); ?></p>';
            html += '<button class="fs-btn fs-btn-secondary fs-btn-small fs-txn-unignore" data-id="' + t.id + '"><?php esc_html_e("Restore", "freelance-studio"); ?></button>';
            html += '</div>';
        } else {
            // Unmatched - show suggestions + actions
            if (data.category_suggestion) {
                html += '<div class="fs-txn-panel-suggestion"><span class="dashicons dashicons-lightbulb"></span> <?php esc_html_e("Suggested category:", "freelance-studio"); ?> <strong>' + $('<span>').text(data.category_suggestion).html() + '</strong></div>';
            }

            if (data.suggestions && data.suggestions.length > 0) {
                html += '<div class="fs-txn-panel-section"><h4>' + (isDebit ? '<?php esc_html_e("Matching Expenses", "freelance-studio"); ?>' : '<?php esc_html_e("Matching Invoices", "freelance-studio"); ?>') + '</h4>';
                html += '<div class="fs-txn-match-list">';
                data.suggestions.forEach(function(s) {
                    if (isDebit) {
                        html += '<div class="fs-txn-match-item" data-match-type="expense" data-match-id="' + s.id + '">';
                        html += '<div class="fs-txn-match-info"><strong>' + $('<span>').text(s.expense_name || s.category).html() + '</strong>';
                        html += '<span class="fs-muted">' + s.expense_date + ' · $' + parseFloat(s.amount).toFixed(2) + '</span></div>';
                        html += '<button class="fs-btn fs-btn-primary fs-btn-small fs-txn-link-btn"><?php esc_html_e("Link", "freelance-studio"); ?></button></div>';
                    } else {
                        var clientName = s.client_name || '';
                        var projectName = s.project_name || '';
                        var isPaid = s.status === 'paid';
                        html += '<div class="fs-txn-match-item" data-match-type="invoice" data-match-id="' + s.id + '">';
                        html += '<div class="fs-txn-match-info"><strong>' + $('<span>').text(s.invoice_number || '#' + s.id).html() + '</strong>';
                        html += '<span class="fs-muted">' + $('<span>').text(clientName).html();
                        if (projectName) html += ' · ' + $('<span>').text(projectName).html();
                        html += ' · $' + parseFloat(s.total).toFixed(2);
                        if (isPaid) html += ' · <em><?php esc_html_e("Already Paid", "freelance-studio"); ?></em>';
                        html += '</span></div>';
                        if (!isPaid) {
                            html += '<label style="margin-right:8px;font-size:12px;"><input type="checkbox" class="fs-txn-mark-paid" checked> <?php esc_html_e("Mark Paid", "freelance-studio"); ?></label>';
                        }
                        html += '<button class="fs-btn fs-btn-primary fs-btn-small fs-txn-link-btn"><?php esc_html_e("Link", "freelance-studio"); ?></button></div>';
                    }
                });
                html += '</div></div>';
            } else {
                html += '<div class="fs-txn-panel-section"><p class="fs-muted"><?php esc_html_e("No matching records found.", "freelance-studio"); ?></p></div>';
            }

            // Actions
            html += '<div class="fs-txn-panel-actions">';
            if (isDebit) {
                html += '<button class="fs-btn fs-btn-primary fs-btn-small fs-txn-create-expense" data-id="' + t.id + '"><?php esc_html_e("Create Expense", "freelance-studio"); ?></button> ';
            }
            html += '<button class="fs-btn fs-btn-secondary fs-btn-small fs-txn-ignore" data-id="' + t.id + '"><?php esc_html_e("Mark Personal", "freelance-studio"); ?></button>';
            html += '</div>';
        }

        $('#fs-txn-panel-body').html(html);
    }

    function renderMatchedSection(linked, t) {
        var html = '<div class="fs-txn-panel-section">';
        html += '<h4><?php esc_html_e("Linked To", "freelance-studio"); ?></h4>';
        if (linked.type === 'expense' && linked.record) {
            html += '<div class="fs-txn-linked-record">';
            html += '<span class="dashicons dashicons-cart"></span> ';
            html += '<strong>' + $('<span>').text(linked.record.expense_name || linked.record.category).html() + '</strong>';
            html += '<br><span class="fs-muted">' + linked.record.expense_date + ' · $' + parseFloat(linked.record.amount).toFixed(2) + '</span>';
            html += '</div>';
        } else if (linked.type === 'invoice' && linked.record) {
            html += '<div class="fs-txn-linked-record">';
            html += '<span class="dashicons dashicons-media-text"></span> ';
            html += '<strong>' + $('<span>').text(linked.record.invoice_number || '#' + linked.record.id).html() + '</strong>';
            if (linked.record.client_name) html += ' — ' + $('<span>').text(linked.record.client_name).html();
            if (linked.record.project_name) html += '<br><span class="fs-muted">' + $('<span>').text(linked.record.project_name).html() + '</span>';
            html += '<br><span class="fs-muted">$' + parseFloat(linked.record.total).toFixed(2) + '</span>';
            html += '</div>';
        }
        html += '<button class="fs-btn fs-btn-secondary fs-btn-small fs-txn-unmatch" data-id="' + t.id + '" style="margin-top:12px;"><?php esc_html_e("Unlink", "freelance-studio"); ?></button>';
        html += '</div>';
        return html;
    }

    // Link transaction to expense/invoice
    $(document).on('click', '.fs-txn-link-btn', function() {
        var $item = $(this).closest('.fs-txn-match-item');
        var matchType = $item.data('match-type');
        var matchId = $item.data('match-id');
        var markPaid = $item.find('.fs-txn-mark-paid').is(':checked') ? '1' : '0';

        $.post(ajaxurl, {
            action: 'fs_match_transaction',
            nonce: fs_ajax.nonce,
            transaction_id: currentTxnId,
            match_type: matchType,
            match_id: matchId,
            mark_paid: markPaid
        }, function(r) {
            if (r.success) { updateRowStatus(currentTxnId, 'matched'); loadPanel(currentTxnId); }
        });
    });

    // Unmatch
    $(document).on('click', '.fs-txn-unmatch', function() {
        var id = $(this).data('id');
        $.post(ajaxurl, { action: 'fs_unmatch_transaction', nonce: fs_ajax.nonce, transaction_id: id }, function(r) {
            if (r.success) { updateRowStatus(id, 'unmatched'); loadPanel(id); }
        });
    });

    // Ignore (mark personal)
    $(document).on('click', '.fs-txn-ignore', function() {
        var id = $(this).data('id');
        $.post(ajaxurl, { action: 'fs_toggle_transaction_ignore', nonce: fs_ajax.nonce, transaction_id: id, action_type: 'ignore' }, function(r) {
            if (r.success) { updateRowStatus(id, 'ignored'); loadPanel(id); }
        });
    });

    // Unignore (restore)
    $(document).on('click', '.fs-txn-unignore', function() {
        var id = $(this).data('id');
        $.post(ajaxurl, { action: 'fs_toggle_transaction_ignore', nonce: fs_ajax.nonce, transaction_id: id, action_type: 'unignore' }, function(r) {
            if (r.success) { updateRowStatus(id, 'unmatched'); loadPanel(id); }
        });
    });

    // Create expense modal
    $(document).on('click', '.fs-txn-create-expense', function() {
        var id = $(this).data('id');
        var $row = $('.fs-txn-row[data-id="' + id + '"]');
        var desc = $row.find('.fs-txn-desc').text();
        var amt = $row.find('.fs-amount-negative, .fs-amount-positive').text().replace(/[+\-$,]/g, '');
        var date = $row.find('td:first').text();

        $('#fs-txn-expense-txn-id').val(id);
        $('#fs-txn-expense-vendor').val(desc);
        $('.fs-txn-expense-amount-display').text('$' + amt);
        $('.fs-txn-expense-date-display').text(date);

        // Pre-select suggested category
        var suggestion = $('#fs-txn-panel-body .fs-txn-panel-suggestion strong').text();
        if (suggestion) {
            $('#fs-txn-expense-category').val(suggestion);
        }

        $('#fs-txn-expense-modal').addClass('active');
    });

    // Save expense
    $('#fs-txn-expense-save').on('click', function() {
        var txnId = $('#fs-txn-expense-txn-id').val();
        var category = $('#fs-txn-expense-category').val();
        if (!category) { alert('<?php esc_html_e("Please select a category.", "freelance-studio"); ?>'); return; }

        var $btn = $(this).prop('disabled', true).text('<?php esc_html_e("Creating...", "freelance-studio"); ?>');

        $.post(ajaxurl, {
            action: 'fs_create_expense_from_transaction',
            nonce: fs_ajax.nonce,
            transaction_id: txnId,
            category: category,
            vendor: $('#fs-txn-expense-vendor').val(),
            project_id: $('#fs-txn-expense-project').val()
        }, function(r) {
            $btn.prop('disabled', false).text('<?php esc_html_e("Create Expense & Link", "freelance-studio"); ?>');
            if (r.success) {
                $('#fs-txn-expense-modal').removeClass('active');
                updateRowStatus(txnId, 'matched');
                loadPanel(txnId);
            } else {
                alert(r.data || 'Error');
            }
        });
    });

    // Close expense modal
    $('#fs-txn-expense-modal .fs-modal-close').on('click', function() {
        $('#fs-txn-expense-modal').removeClass('active');
    });

    // Update row visuals after status change
    function updateRowStatus(id, newStatus) {
        var $row = $('.fs-txn-row[data-id="' + id + '"]');
        $row.data('status', newStatus).attr('data-status', newStatus);
        $row.toggleClass('fs-row-ignored', newStatus === 'ignored');

        var badgeClass = 'status-pending', label = '<?php esc_html_e("Unmatched", "freelance-studio"); ?>';
        if (newStatus === 'matched') { badgeClass = 'status-completed'; label = '<?php esc_html_e("Matched", "freelance-studio"); ?>'; }
        else if (newStatus === 'ignored') { badgeClass = 'status-draft'; label = '<?php esc_html_e("Ignored", "freelance-studio"); ?>'; }

        $row.find('.fs-status-badge').attr('class', 'fs-status-badge ' + badgeClass).text(label);

        // Update tab counts
        updateFilterCounts();
    }

    function updateFilterCounts() {
        var counts = { all: 0, unmatched: 0, matched: 0, ignored: 0 };
        $('#fs-txn-review-table tbody tr').each(function() {
            counts.all++;
            var s = $(this).data('status');
            if (counts[s] !== undefined) counts[s]++;
        });
        $('.fs-txn-filter-tabs .fs-tab').each(function() {
            var f = $(this).data('filter');
            $(this).find('.fs-tab-count').text(counts[f]);
        });
    }

    // ==============================
    // PERSONAL RULES
    // ==============================
    var personalRules = [];

    // Open rules modal
    $('#fs-txn-open-rules').on('click', function() {
        loadRules();
        $('#fs-txn-rules-modal').addClass('active');
    });

    // Close rules modal
    $('#fs-txn-rules-modal .fs-modal-close').on('click', function() {
        $('#fs-txn-rules-modal').removeClass('active');
    });

    // Load rules from server
    function loadRules() {
        $.post(ajaxurl, {
            action: 'fs_get_personal_rules',
            nonce: fs_ajax.nonce
        }, function(r) {
            if (r.success) {
                personalRules = r.data.rules || [];
                renderRulesList();
            }
        });
    }

    // Render rules list
    function renderRulesList() {
        var $list = $('#fs-txn-rules-list').empty();
        var $empty = $('#fs-txn-rules-empty');

        if (personalRules.length === 0) {
            $empty.show();
            return;
        }
        $empty.hide();

        personalRules.forEach(function(rule, i) {
            $list.append(
                '<div class="fs-txn-rule-item" data-index="' + i + '">' +
                '<span class="fs-txn-rule-keyword">' + $('<span>').text(rule).html() + '</span>' +
                '<button type="button" class="fs-btn-link fs-txn-rule-remove" data-index="' + i + '"><?php esc_html_e("Remove", "freelance-studio"); ?></button>' +
                '</div>'
            );
        });
    }

    // Add rule
    $('#fs-txn-rule-add').on('click', addRule);
    $('#fs-txn-rule-input').on('keypress', function(e) { if (e.which === 13) { e.preventDefault(); addRule(); } });

    function addRule() {
        var keyword = $('#fs-txn-rule-input').val().trim();
        if (!keyword) return;

        // Check for duplicates (case-insensitive)
        var lower = keyword.toLowerCase();
        for (var i = 0; i < personalRules.length; i++) {
            if (personalRules[i].toLowerCase() === lower) {
                $('#fs-txn-rule-input').val('').focus();
                return;
            }
        }

        personalRules.push(keyword);
        saveRules();
        $('#fs-txn-rule-input').val('').focus();
        renderRulesList();
    }

    // Remove rule
    $(document).on('click', '.fs-txn-rule-remove', function() {
        var idx = parseInt($(this).data('index'));
        personalRules.splice(idx, 1);
        saveRules();
        renderRulesList();
    });

    // Save rules to server
    function saveRules() {
        $.post(ajaxurl, {
            action: 'fs_save_personal_rules',
            nonce: fs_ajax.nonce,
            rules: JSON.stringify(personalRules)
        });
    }

    // Run rules on existing transactions
    $('#fs-txn-run-rules').on('click', function() {
        var $btn = $(this);
        $btn.prop('disabled', true).find('.dashicons').addClass('spin');

        $.post(ajaxurl, {
            action: 'fs_run_personal_rules',
            nonce: fs_ajax.nonce
        }, function(r) {
            $btn.prop('disabled', false).find('.dashicons').removeClass('spin');
            if (r.success) {
                var count = r.data.ignored_count || 0;
                if (count > 0) {
                    // Update affected rows in the table
                    if (r.data.ignored_ids) {
                        r.data.ignored_ids.forEach(function(id) {
                            updateRowStatus(id, 'ignored');
                        });
                    }
                    alert(count + ' <?php esc_html_e("transactions marked as personal.", "freelance-studio"); ?>');
                } else {
                    alert('<?php esc_html_e("No unmatched transactions matched your rules.", "freelance-studio"); ?>');
                }
            }
        });
    });
});
</script>
