const KBBTImport = {
	loadingErrors: [],
};

// ======= ERROR MANAGEMENT =======
KBBTImport.errors = {
	add: function(txnData, errorType, errorMessage) {
		const errorEntry = {
			ref_no: txnData.ref_no || 'Unknown',
			date: txnData.date || 'Unknown',
			counterparty: txnData.counterparty || 'Unknown',
			amount: txnData.amount || 0,
			source_label: txnData.source_label || '',
			error_type: errorType,
			error_message: errorMessage,
			timestamp: new Date().toISOString(),
		};

		KBBTImport.loadingErrors.push(errorEntry);
		console.error('KB BT Import Error:', errorEntry);
	},

	clear: function() {
		frappe.confirm(
			__('Are you sure you want to clear the error log?'),
			function() {
				KBBTImport.loadingErrors = [];
				frappe.show_alert({
					message: __('Error log cleared'),
					indicator: 'green'
				}, 2);
			}
		);
	},

	showDetails: function() {
		if (KBBTImport.loadingErrors.length === 0) {
			frappe.msgprint(__('No errors to display'));
			return;
		}

		let errorsHtml = '<div class="error-log-container">';

		KBBTImport.loadingErrors.forEach(function(error) {
			let documentDate = 'No date';
			if (error.date && error.date !== 'Unknown') {
				try {
					documentDate = moment(error.date).format('DD.MM.YYYY');
				} catch (e) {
					documentDate = 'Invalid date';
				}
			}

			errorsHtml += '<div class="error-item" style="margin-bottom: 20px; padding: 15px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-color);">';

			// Header
			errorsHtml += '<div class="error-header" style="margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border-color);">';
			errorsHtml += '<div style="display: flex; justify-content: space-between; align-items: center;">';
			errorsHtml += '<h5 style="margin: 0; color: var(--text-color);">' +
						  '<strong>' + error.ref_no + '</strong></h5>';
			errorsHtml += '<span class="label label-danger">' + error.error_type + '</span>';
			errorsHtml += '</div>';
			errorsHtml += '<small style="color: var(--text-muted);">' + error.counterparty + '</small>';
			if (error.source_label) {
				errorsHtml += ' <small style="color: var(--text-muted);">(' + error.source_label + ')</small>';
			}
			errorsHtml += '</div>';

			// Error message
			errorsHtml += '<div class="error-message" style="margin-bottom: 10px;">';
			errorsHtml += '<strong style="color: var(--text-color);">' + error.error_message + '</strong>';
			errorsHtml += '</div>';

			errorsHtml += '<div style="text-align: right; margin-top: 10px;">';
			errorsHtml += '<small style="color: var(--text-muted);"><em>' + documentDate + '</em></small>';
			errorsHtml += '</div>';

			errorsHtml += '</div>';
		});

		errorsHtml += '</div>';

		// Statistics
		const errorTypes = {};
		KBBTImport.loadingErrors.forEach(function(error) {
			errorTypes[error.error_type] = (errorTypes[error.error_type] || 0) + 1;
		});

		let statsHtml = '<div style="margin-bottom: 20px; padding: 15px; background: var(--bg-light); border-radius: 6px; border: 1px solid var(--border-color);">';
		statsHtml += '<div style="display: flex; justify-content: space-between; align-items: center;">';
		statsHtml += '<div>';
		statsHtml += '<strong style="color: var(--text-color);">' + __('Total Errors:') + '</strong> ' + KBBTImport.loadingErrors.length + '<br>';
		statsHtml += '<span style="color: var(--text-muted);">';
		Object.keys(errorTypes).forEach(function(type, index) {
			if (index > 0) statsHtml += ' &bull; ';
			statsHtml += type + ': ' + errorTypes[type];
		});
		statsHtml += '</span>';
		statsHtml += '</div>';
		statsHtml += '<div>';
		statsHtml += '<button class="btn btn-default btn-sm" id="kb-bt-export-csv-dialog-btn" style="margin-right: 5px;">' +
					 '<i class="fa fa-download"></i> ' + __('Export CSV') + '</button>';
		statsHtml += '<button class="btn btn-warning btn-sm" id="kb-bt-clear-log-dialog-btn">' +
					 '<i class="fa fa-trash"></i> ' + __('Clear') + '</button>';
		statsHtml += '</div></div>';

		const d = new frappe.ui.Dialog({
			title: __('Error Details') + ' (' + KBBTImport.loadingErrors.length + ')',
			size: 'large',
			fields: [
				{
					fieldname: 'stats_html',
					fieldtype: 'HTML',
					options: statsHtml
				},
				{
					fieldname: 'errors_html',
					fieldtype: 'HTML',
					options: '<div style="max-height: 500px; overflow-y: auto;">' + errorsHtml + '</div>'
				}
			],
			primary_action_label: __('Close'),
			primary_action: function() {
				d.hide();
			}
		});

		d.show();

		setTimeout(function() {
			$('#kb-bt-export-csv-dialog-btn').off('click').on('click', function() {
				KBBTImport.errors.exportCSV();
			});

			$('#kb-bt-clear-log-dialog-btn').off('click').on('click', function() {
				KBBTImport.errors.clear();
				d.hide();
			});
		}, 200);
	},

	exportCSV: function() {
		if (KBBTImport.loadingErrors.length === 0) {
			frappe.msgprint(__('No errors to export'));
			return;
		}

		try {
			let csvContent = "data:text/csv;charset=utf-8,";
			csvContent += "Ref No,Date,Counterparty,Amount,Source,Error Type,Error Message,Timestamp\n";

			KBBTImport.loadingErrors.forEach(function(error) {
				const cleanMessage = error.error_message.replace(/"/g, '""').replace(/\n/g, ' ').replace(/\r/g, ' ');
				const cleanCounterparty = (error.counterparty || '').replace(/"/g, '""');

				const row = [
					error.ref_no,
					error.date,
					cleanCounterparty,
					error.amount,
					error.source_label || '',
					error.error_type,
					cleanMessage,
					moment(error.timestamp).format('DD.MM.YYYY HH:mm:ss')
				].map(function(field) {
					return '"' + (field || '') + '"';
				}).join(',');

				csvContent += row + "\n";
			});

			const encodedUri = encodeURI(csvContent);
			const link = document.createElement("a");
			link.setAttribute("href", encodedUri);
			link.setAttribute("download", "kb_bt_import_errors_" + moment().format('YYYY-MM-DD_HH-mm-ss') + ".csv");
			document.body.appendChild(link);
			link.click();
			document.body.removeChild(link);

			frappe.show_alert({
				message: __('Error log exported successfully'),
				indicator: 'green'
			}, 3);
		} catch (e) {
			console.error('Export error:', e);
			frappe.show_alert({
				message: __('Failed to export error log'),
				indicator: 'red'
			}, 3);
		}
	},

	showSummary: function(totalTransactions, processedCount, errorsCount) {
		if (errorsCount === 0) {
			frappe.msgprint({
				title: __('Import Completed Successfully'),
				indicator: 'green',
				message: __('All ') + totalTransactions + __(' transactions were imported successfully.')
			});
		} else {
			const title = errorsCount === totalTransactions ? __('Import Failed') : __('Import Completed with Errors');
			const indicator = processedCount > 0 ? 'orange' : 'red';

			let message = '<div style="margin-bottom: 15px;">';
			if (processedCount > 0) {
				message += __('Successfully imported: ') + '<strong>' + processedCount + '</strong>' + __(' transactions') + '<br>';
			}
			message += __('Failed: ') + '<strong>' + errorsCount + '</strong>' + __(' transactions');
			message += '</div>';

			message += '<div style="text-align: center;">' +
					  '<button class="btn btn-primary btn-sm" id="kb-bt-view-error-details-btn" style="margin-right: 10px;">' +
					  '<i class="fa fa-list"></i> ' + __('View Error Details') + '</button>' +
					  '<button class="btn btn-default btn-sm" id="kb-bt-export-error-log-btn">' +
					  '<i class="fa fa-download"></i> ' + __('Export CSV') + '</button>' +
					  '</div>';

			const summaryDialog = frappe.msgprint({
				title: title,
				indicator: indicator,
				message: message
			});

			setTimeout(function() {
				$('#kb-bt-view-error-details-btn').off('click').on('click', function() {
					summaryDialog.hide();
					KBBTImport.errors.showDetails();
				});

				$('#kb-bt-export-error-log-btn').off('click').on('click', function() {
					KBBTImport.errors.exportCSV();
				});
			}, 200);
		}
	}
};

// ======= IMPORT MODULE =======
KBBTImport.import = {
	showDialog: function() {
		// Load sources: try settings mappings first, fall back to registry doctypes
		frappe.call({
			method: 'frappe.client.get',
			args: { doctype: 'Kapital Bank Settings', name: 'Kapital Bank Settings' },
			callback: function(r) {
				if (!r.message) {
					frappe.msgprint({ title: __('Error'), indicator: 'red', message: __('Could not load Kapital Bank Settings') });
					return;
				}

				const accountMappings = r.message.account_mappings || [];
				const cardMappings = r.message.card_mappings || [];

				if (accountMappings.length > 0 || cardMappings.length > 0) {
					// Use mappings as source list
					KBBTImport.import._showDialogWithSources(
						accountMappings.map(function(m) {
							return { type: 'account', id: m.iban, label: m.account_label ? (m.iban + ' — ' + m.account_label) : m.iban };
						}).filter(function(s) { return s.id; }),
						cardMappings.map(function(m) {
							return { type: 'card', id: m.account_number, label: m.card_label ? (m.account_number + ' — ' + m.card_label) : m.account_number };
						}).filter(function(s) { return s.id; })
					);
				} else {
					// Fall back to registry doctypes
					KBBTImport.import._loadRegistrySources();
				}
			}
		});
	},

	_loadRegistrySources: function() {
		let accounts = [];
		let cards = [];
		let pending = 2;

		function onDone() {
			pending--;
			if (pending > 0) return;

			if (accounts.length === 0 && cards.length === 0) {
				frappe.msgprint({
					title: __('No Sources'),
					indicator: 'orange',
					message: __('No bank accounts or cards found. Please load registry data in Kapital Bank Settings first.')
				});
				return;
			}

			KBBTImport.import._showDialogWithSources(accounts, cards);
		}

		frappe.call({
			method: 'frappe.client.get_list',
			args: {
				doctype: 'Kapital Bank Account',
				fields: ['iban', 'account_desc', 'currency'],
				filters: { status: 'Active' },
				limit_page_length: 0
			},
			callback: function(r) {
				if (r.message) {
					accounts = r.message.map(function(a) {
						const label = a.account_desc ? (a.iban + ' — ' + a.account_desc) : a.iban;
						return { type: 'account', id: a.iban, label: label };
					});
				}
				onDone();
			},
			error: function() { onDone(); }
		});

		frappe.call({
			method: 'frappe.client.get_list',
			args: {
				doctype: 'Kapital Bank Card',
				fields: ['account_number', 'card_type', 'pan', 'currency'],
				filters: { status: 'Active' },
				limit_page_length: 0
			},
			callback: function(r) {
				if (r.message) {
					cards = r.message.map(function(c) {
						const label = c.pan ? (c.account_number + ' — ' + c.pan) : c.account_number;
						return { type: 'card', id: c.account_number, label: label };
					});
				}
				onDone();
			},
			error: function() { onDone(); }
		});
	},

	_showDialogWithSources: function(accounts, cards) {
		let sourcesHtml = '<div style="max-height: 300px; overflow-y: auto;">';
		sourcesHtml += '<div style="margin-bottom: 10px;">';
		sourcesHtml += '<label><input type="checkbox" class="kb-bt-select-all-sources"> <strong>' + __('Select All') + '</strong></label>';
		sourcesHtml += '</div>';

		if (accounts.length > 0) {
			sourcesHtml += '<div style="margin-bottom: 8px; font-weight: 600; color: var(--text-color);">' + __('Accounts') + '</div>';
			accounts.forEach(function(a) {
				sourcesHtml += '<div style="margin-left: 20px; margin-bottom: 4px;">';
				sourcesHtml += '<label><input type="checkbox" class="kb-bt-source-check" data-type="' + a.type + '" data-id="' + a.id + '"> ' + a.label + '</label>';
				sourcesHtml += '</div>';
			});
		}

		if (cards.length > 0) {
			sourcesHtml += '<div style="margin-bottom: 8px; margin-top: 10px; font-weight: 600; color: var(--text-color);">' + __('Cards') + '</div>';
			cards.forEach(function(c) {
				sourcesHtml += '<div style="margin-left: 20px; margin-bottom: 4px;">';
				sourcesHtml += '<label><input type="checkbox" class="kb-bt-source-check" data-type="' + c.type + '" data-id="' + c.id + '"> ' + c.label + '</label>';
				sourcesHtml += '</div>';
			});
		}

		sourcesHtml += '</div>';

		const today = frappe.datetime.get_today();
		const first_day = frappe.datetime.month_start(today);

		const d = new frappe.ui.Dialog({
			title: __('Import Bank Transactions'),
			fields: [
				{ fieldname: 'sec_period', fieldtype: 'Section Break', label: __('Period') },
				{ fieldname: 'date_from', fieldtype: 'Date', label: __('Date From'), reqd: 1, default: first_day },
				{ fieldname: 'col_break', fieldtype: 'Column Break' },
				{ fieldname: 'date_to', fieldtype: 'Date', label: __('Date To'), reqd: 1, default: today },
				{ fieldname: 'sec_sources', fieldtype: 'Section Break', label: __('Sources') },
				{
					fieldname: 'sources_html',
					fieldtype: 'HTML',
					options: sourcesHtml
				}
			],
			primary_action_label: __('Search'),
			primary_action: function() {
				const values = d.get_values();
				const selectedSources = [];

				d.$wrapper.find('.kb-bt-source-check:checked').each(function() {
					selectedSources.push({
						type: $(this).data('type'),
						id: $(this).data('id')
					});
				});

				if (selectedSources.length === 0) {
					frappe.msgprint({
						title: __('Warning'),
						indicator: 'orange',
						message: __('Please select at least one account or card')
					});
					return;
				}

				// Card statements are limited to 90 days by the API
				const hasCards = selectedSources.some(s => s.type === 'card');
				if (hasCards) {
					const diffDays = frappe.datetime.get_diff(values.date_to, values.date_from);
					if (diffDays > 90) {
						frappe.msgprint({
							title: __('Date Range Too Large'),
							indicator: 'orange',
							message: __('Card statements are limited to 90 days. Please shorten the date range or deselect cards.')
						});
						return;
					}
				}

				d.hide();
				KBBTImport.import.loadTransactionsMulti(values.date_from, values.date_to, selectedSources);
			}
		});
		d.show();

		// Select All handler
		d.$wrapper.find('.kb-bt-select-all-sources').on('change', function() {
			const isChecked = $(this).prop('checked');
			d.$wrapper.find('.kb-bt-source-check').prop('checked', isChecked);
		});
	},

	loadTransactionsMulti: function(fromDate, toDate, sources) {
		const totalSources = sources.length;
		let currentSourceIdx = 0;
		let allTransactions = [];
		let totalSkipped = 0;
		let seenRefNos = new Set();
		let crossAccountDuplicates = 0;
		let skippedCrossCurrency = 0;

		function fetchNext() {
			if (currentSourceIdx >= totalSources) {
				frappe.hide_progress();

				if (allTransactions.length === 0) {
					let msg = __('No new transactions found for the specified period.');
					if (totalSkipped > 0) {
						msg += ' ' + __('({0} already imported)', [totalSkipped]);
					}
					frappe.msgprint({
						title: __('Information'),
						indicator: 'blue',
						message: msg
					});
					return;
				}

				if (totalSkipped > 0 || crossAccountDuplicates > 0 || skippedCrossCurrency > 0) {
					let parts = [];
					if (totalSkipped > 0) parts.push(__('already imported: {0}', [totalSkipped]));
					if (crossAccountDuplicates > 0) parts.push(__('cross-account duplicates: {0}', [crossAccountDuplicates]));
					if (skippedCrossCurrency > 0) parts.push(__('other currency account: {0}', [skippedCrossCurrency]));
					frappe.show_alert({
						message: __('Skipped: {0}', [parts.join(', ')]),
						indicator: 'blue'
					}, 5);
				}

				KBBTImport.import.showTransactionSelection(allTransactions);
				return;
			}

			const source = sources[currentSourceIdx];
			const sourceLabel = source.type === 'account'
				? source.id
				: __('Card: {0}', [source.id]);

			frappe.show_progress(
				__('Fetching Statements'),
				currentSourceIdx,
				totalSources,
				__('Fetching statement {0} of {1}: {2}', [currentSourceIdx + 1, totalSources, sourceLabel])
			);

			const method = source.type === 'account'
				? 'kapital_bank.bank_api.get_statement_transactions'
				: 'kapital_bank.bank_api.get_card_statement_transactions';

			const args = source.type === 'account'
				? { from_date: fromDate, to_date: toDate, account_iban: source.id }
				: { from_date: fromDate, to_date: toDate, card_account_number: source.id };

			frappe.call({
				method: method,
				args: args,
				callback: function(r) {
					if (r.message && r.message.success) {
						const txns = (r.message.transactions || []).map(function(txn) {
							txn.source_id = source.id;
							return txn;
						});
						// Deduplicate across multiple statements (cross-account transfers)
						txns.forEach(function(txn) {
							if (txn.ref_no && seenRefNos.has(txn.ref_no)) {
								crossAccountDuplicates++;
							} else {
								if (txn.ref_no) seenRefNos.add(txn.ref_no);
								allTransactions.push(txn);
							}
						});
						totalSkipped += (r.message.skipped_duplicates || 0);
						skippedCrossCurrency += (r.message.skipped_cross_currency || 0);
					} else {
						frappe.show_alert({
							message: __('Error fetching {0}: {1}', [sourceLabel, r.message ? r.message.message : 'unknown']),
							indicator: 'red'
						}, 5);
					}
					currentSourceIdx++;
					setTimeout(fetchNext, 100);
				},
				error: function() {
					frappe.show_alert({
						message: __('Network error fetching {0}', [sourceLabel]),
						indicator: 'red'
					}, 5);
					currentSourceIdx++;
					setTimeout(fetchNext, 100);
				}
			});
		}

		fetchNext();
	},

	showTransactionSelection: function(txns) {
		const hasCardTxns = txns.some(t => t.source_type === 'card');

		let txnTable = '';
		if (hasCardTxns) {
			txnTable += '<div style="margin-bottom: 10px; padding: 10px 12px; background: var(--red-50, #fff5f5); border: 1px solid var(--red-200, #fecaca); border-radius: var(--border-radius); font-size: var(--text-base); color: var(--red-600, #dc2626);">';
			txnTable += '⚠️ ' + __('Card transactions may already be imported from other accounts. The bank uses different reference numbers for card and account statements, so duplicates cannot be detected automatically.');
			txnTable += '</div>';
		}

		txnTable += '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered kb-bt-txn-table" style="width: 100%; table-layout: fixed;">';
		txnTable += '<thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-color, #fff);"><tr>' +
					'<th style="width: 4%;"><input type="checkbox" class="kb-bt-select-all-txns"></th>' +
					'<th style="width: 14%;">' + __('Ref No') + '</th>' +
					'<th style="width: 10%;">' + __('Date') + '</th>' +
					'<th style="width: 14%;">' + __('Account') + '</th>' +
					'<th style="width: 20%;">' + __('Counterparty') + '</th>' +
					'<th style="width: 12%; text-align: right;">' + __('Amount') + '</th>' +
					'<th style="width: 6%; text-align: center;">' + __('Type') + '</th>' +
					'<th style="width: 20%;">' + __('Purpose') + '</th>' +
					'</tr></thead><tbody>';

		txns.forEach(function(txn, idx) {
			const displayDate = txn.date ? moment(txn.date).format('DD.MM.YYYY') : '';
			const amountFmt = parseFloat(txn.amount || 0).toFixed(2);
			const drcrLabel = txn.drcr === 'D'
				? '<span class="label label-danger">' + __('Pay') + '</span>'
				: '<span class="label label-success">' + __('Receive') + '</span>';
			const sourceLabel = txn.source_label || '';

			txnTable += '<tr>' +
						'<td><input type="checkbox" class="kb-bt-select-txn" data-idx="' + idx + '"></td>' +
						'<td style="word-break: break-word;">' + (txn.ref_no || '') + '</td>' +
						'<td>' + displayDate + '</td>' +
						'<td style="word-break: break-word; font-size: 0.85em;">' + sourceLabel + '</td>' +
						'<td style="word-break: break-word;">' + (txn.counterparty || '') + '</td>' +
						'<td style="text-align: right;">' + amountFmt + ' ' + (txn.currency || '') + '</td>' +
						'<td style="text-align: center;">' + drcrLabel + '</td>' +
						'<td style="word-break: break-word; font-size: 0.9em;">' + (txn.full_description || txn.purpose || '') + '</td>' +
						'</tr>';
		});

		txnTable += '</tbody></table></div>';

		const infoMessage = '<div class="alert alert-info">' +
						   __('Transactions found: ') + txns.length +
						   '</div>';

		const d = new frappe.ui.Dialog({
			title: __('Select Transactions to Import'),
			size: 'large',
			fields: [
				{
					fieldname: 'info_html',
					fieldtype: 'HTML',
					options: infoMessage
				},
				{
					fieldname: 'txns_html',
					fieldtype: 'HTML',
					options: txnTable
				}
			],
			primary_action_label: __('Load selected'),
			primary_action: function() {
				const selectedTxns = [];
				d.$wrapper.find('.kb-bt-select-txn:checked').each(function() {
					const idx = $(this).data('idx');
					selectedTxns.push(txns[idx]);
				});

				if (selectedTxns.length === 0) {
					frappe.msgprint({
						title: __('Warning'),
						indicator: 'orange',
						message: __('No transactions selected')
					});
					return;
				}

				d.hide();
				KBBTImport.import.loadSelectedTransactions(selectedTxns);
			},
			secondary_action_label: __('Cancel'),
			secondary_action: function() {
				d.hide();
			}
		});

		d.$wrapper.find('.modal-dialog').css({
			'max-width': '90%',
			'width': '90%',
			'margin': '30px auto'
		});

		d.$wrapper.find('.modal-body').css({
			'padding': '15px'
		});

		d.show();

		d.$wrapper.find('.kb-bt-select-all-txns').on('change', function() {
			const isChecked = $(this).prop('checked');
			d.$wrapper.find('.kb-bt-select-txn').prop('checked', isChecked);
		});
	},

	loadSelectedTransactions: function(selectedTxns) {
		KBBTImport.loadingErrors = [];
		const total = selectedTxns.length;
		// Защита от гонки realtime: 'complete' закрывает прогресс. Опоздавший 'progress'
		// иначе пересоздаёт модал, который уже никто не закрывает. Флаг делает
		// обработчик прогресса no-op после завершения.
		let importFinished = false;

		frappe.show_progress(
			__('Importing Transactions'), 0, total,
			__('Starting import of {0} transactions...', [total])
		);

		// Listen for realtime progress from background job
		frappe.realtime.off('kb_bt_import_progress');
		frappe.realtime.on('kb_bt_import_progress', function(data) {
			if (importFinished) return;
			frappe.show_progress(
				__('Importing Transactions'), data.current, data.total,
				__('Importing transaction {0} of {1}', [data.current, data.total])
			);
		});

		// Listen for completion from background job
		frappe.realtime.off('kb_bt_import_complete');
		frappe.realtime.on('kb_bt_import_complete', function(data) {
			importFinished = true;
			frappe.realtime.off('kb_bt_import_progress');
			frappe.realtime.off('kb_bt_import_complete');
			KBBTImport.import._onBulkComplete(data);
			setTimeout(KBBTImport.import._closeProgress, 150);
		});

		frappe.call({
			method: 'kapital_bank.bank_api.import_bulk_bank_transactions',
			args: { txn_list: JSON.stringify(selectedTxns) },
			callback: function(r) {
				// Job enqueued — progress & completion come via realtime events
				if (!r.message || !r.message.enqueued) {
					frappe.realtime.off('kb_bt_import_progress');
					frappe.realtime.off('kb_bt_import_complete');
					KBBTImport.import._closeProgress();
					frappe.msgprint({
						title: __('Error'),
						indicator: 'red',
						message: __('Failed to start import job')
					});
				}
			},
			error: function() {
				frappe.realtime.off('kb_bt_import_progress');
				frappe.realtime.off('kb_bt_import_complete');
				KBBTImport.import._closeProgress();
				frappe.msgprint({
					title: __('Error'),
					indicator: 'red',
					message: __('Network error starting import')
				});
			}
		});
	},

	_onBulkComplete: function(data) {
		KBBTImport.import._closeProgress();

		// Collect errors for the error panel
		(data.errors || []).forEach(function(err) {
			const txnData = err.txn_data || {};
			const errorType = err.error_type === 'unmapped_bank_account' ? 'Unmapped Bank Account'
				: 'Import Error';
			KBBTImport.errors.add(txnData, errorType, err.message);
		});

		KBBTImport.errors.showSummary(data.total, data.imported, data.errors ? data.errors.length : 0);

		if (cur_list) {
			cur_list.refresh();
		}
	},

	_closeProgress: function() {
		if (frappe.cur_progress) {
			try {
				frappe.cur_progress.$wrapper.modal('hide');
				frappe.cur_progress.$wrapper.remove();
			} catch(e) {}
			frappe.cur_progress = null;
		}
		if ($('.modal:visible').length === 0) {
			$('.modal-backdrop').remove();
			$('body').removeClass('modal-open');
		}
	}
};

// ───────────────────────────────────────────────────────────────────────────────
// Register Kapital Bank as a bank-import source in jey_erp's shared "Import
// From..." menu (Bank Transaction list, Payment Entry list, Bank Reconciliation
// Tool). Loaded globally via app_include_js, so KBBTImport is available wherever
// the menu is shown — including the BRT, where the per-doctype script is not.
// ───────────────────────────────────────────────────────────────────────────────

window.KBBTImport = KBBTImport;

frappe.provide('jey_erp');
jey_erp.bank_sources = jey_erp.bank_sources || [];
if (!jey_erp.bank_sources.some((s) => s.key === 'kapital')) {
	jey_erp.bank_sources.push({
		key: 'kapital',
		label: __('Kapital Bank'),
		importLabel: __('Kapital Bank (API)'),
		settingsLabel: __('Kapital Bank Settings'),
		runImport(ctx) {
			ctx = ctx || {};
			// Let the caller (e.g. the Bank Reconciliation Tool) react when the
			// API import finishes — KBBTImport runs its own progress/list refresh,
			// but the BRT needs to reload its reconciliation table afterwards.
			if (typeof ctx.onComplete === 'function') {
				const handler = (d) => {
					frappe.realtime.off('kb_bt_import_complete', handler);
					ctx.onComplete({ imported: (d && d.imported) || 0, errors: (d && d.errors) || [], transactions: [] });
				};
				frappe.realtime.on('kb_bt_import_complete', handler);
			}
			KBBTImport.import.showDialog();
		},
		goToSettings() { frappe.set_route('Form', 'Kapital Bank Settings'); },
	});
}
