// Bank Transaction list view: "Import From..." dropdown with "Load from Excel"
// Other apps (e.g. kapital_bank) add their own items into the same group.

(function () {
	const existing = frappe.listview_settings['Bank Transaction'] || {};
	const prevOnload = existing.onload;

	frappe.listview_settings['Bank Transaction'] = Object.assign({}, existing, {
		onload(listview) {
			if (typeof prevOnload === 'function') {
				try { prevOnload(listview); } catch (e) { console.error(e); }
			}

			listview.page.add_inner_button(__('Load from Excel'), function () {
				BIExcelImport.showDialog(listview);
			}, __('Import From...'));
		}
	});
})();

const BIExcelImport = {
	showDialog(listview) {
		frappe.db.get_list('Bank Statement Importer', {
			fields: ['name', 'bank_name'],
			limit: 100,
		}).then((integrations) => {
			if (!integrations || !integrations.length) {
				frappe.msgprint({
					title: __('No Bank Statement Importer'),
					indicator: 'orange',
					message: __('Create at least one Bank Statement Importer record first.'),
				});
				return;
			}
			BIExcelImport._showSetupDialog(integrations, listview);
		});
	},

	_showSetupDialog(integrations, listview) {
		const d = new frappe.ui.Dialog({
			title: __('Load Bank Transactions from Excel'),
			fields: [
				{
					fieldname: 'bank_integration',
					fieldtype: 'Link',
					label: __('Bank Statement Importer'),
					options: 'Bank Statement Importer',
					reqd: 1,
					description: __('Format and column mappings come from the chosen Bank Statement Importer.'),
				},
				{
					fieldname: 'bank_account',
					fieldtype: 'Link',
					label: __('Bank Account'),
					options: 'Bank Account',
					reqd: 1,
					description: __('The Bank Account these transactions will be assigned to.'),
				},
				{
					fieldname: 'file_url',
					fieldtype: 'Attach',
					label: __('Excel File'),
					reqd: 1,
				},
			],
			primary_action_label: __('Parse'),
			primary_action(values) {
				d.hide();
				BIExcelImport._parseAndPreview(values, listview);
			},
		});
		d.show();
	},

	_parseAndPreview(values, listview) {
		frappe.show_alert({ message: __('Parsing file...'), indicator: 'blue' });
		frappe.call({
			method: 'jey_erp.bank_integration.import_api.parse_excel_for_preview',
			args: {
				file_url: values.file_url,
				bank_integration: values.bank_integration,
				bank_account: values.bank_account,
			},
			callback(r) {
				if (!r.message || !r.message.success) {
					frappe.msgprint({
						title: __('Parse Error'),
						indicator: 'red',
						message: (r.message && r.message.message) || __('Unknown error'),
					});
					return;
				}
				const txns = r.message.transactions || [];
				const skipped = r.message.skipped_duplicates || 0;
				const droppedDate = r.message.dropped_date || 0;
				const droppedAmount = r.message.dropped_amount || 0;
				const droppedDirection = r.message.dropped_direction || 0;
				const unknownDirections = r.message.unknown_directions || [];
				const emptyRefCount = r.message.empty_ref_count || 0;

				if (droppedDate > 0 && !txns.length) {
					BIExcelImport._showDateParseHelp(droppedDate, values.bank_integration);
					return;
				}
				if (droppedDirection > 0 && !txns.length) {
					BIExcelImport._showDirectionHelp(droppedDirection, unknownDirections, values.bank_integration);
					return;
				}
				if (droppedAmount > 0 && !txns.length) {
					BIExcelImport._showAmountHelp(droppedAmount, values.bank_integration);
					return;
				}
				if (!txns.length) {
					frappe.msgprint({
						title: __('Nothing to Import'),
						indicator: 'blue',
						message: skipped > 0
							? __('All {0} parsed rows are duplicates.', [skipped])
							: __('No transactions found in the file. Check that the Header Row in the File Format tab points at the actual header line.'),
					});
					return;
				}
				BIExcelImport._showPreview(txns, skipped, values, listview,
					droppedDate, droppedAmount, droppedDirection, unknownDirections, emptyRefCount);
			},
		});
	},

	_showPreview(txns, skipped, values, listview, droppedDate, droppedAmount, droppedDirection, unknownDirections, emptyRefCount) {
		let table = '<div style="max-height: 500px; overflow-y: auto;">';
		if (skipped > 0) {
			table += '<div class="alert alert-info">' +
				__('Skipped {0} duplicates already imported. {1} new transactions ready.', [skipped, txns.length]) +
				'</div>';
		}
		if (droppedDate > 0) {
			table += '<div class="alert alert-warning">' +
				__('Dropped {0} row(s) — the date could not be parsed.', [droppedDate]) + ' ' +
				__("Open the Bank Statement Importer's File Format tab, enable 'Use Custom Date Format', and set the exact format your bank uses.") +
				'</div>';
		}
		if (droppedDirection > 0) {
			const sample = (unknownDirections || []).map(frappe.utils.escape_html).join(', ');
			table += '<div class="alert alert-warning">' +
				__('Dropped {0} row(s) — unknown direction value(s):', [droppedDirection]) +
				' <code>' + (sample || '?') + '</code>. ' +
				__('Open the File Format tab and add these to Debit Values or Credit Values.') +
				'</div>';
		}
		if (droppedAmount > 0) {
			table += '<div class="alert alert-warning">' +
				__('Dropped {0} row(s) — missing or zero amount.', [droppedAmount]) +
				'</div>';
		}
		if (emptyRefCount > 0) {
			table += '<div class="alert alert-warning">' +
				__('{0} of {1} row(s) have no Reference Number — re-importing the same file will create duplicates because deduplication uses the Reference Number.',
					[emptyRefCount, txns.length]) +
				'</div>';
		}
		table += '<table class="table table-bordered" style="width:100%; table-layout:fixed;">';
		table += '<thead style="position:sticky; top:0; z-index:1; background:var(--bg-color);"><tr>';
		table += '<th style="width:4%;"><input type="checkbox" class="bi-select-all-txns"></th>';
		table += '<th style="width:14%;">' + __('Ref No') + '</th>';
		table += '<th style="width:10%;">' + __('Date') + '</th>';
		table += '<th style="width:24%;">' + __('Counterparty') + '</th>';
		table += '<th style="width:12%; text-align:right;">' + __('Amount') + '</th>';
		table += '<th style="width:8%; text-align:center;">' + __('Type') + '</th>';
		table += '<th style="width:28%;">' + __('Purpose / Description') + '</th>';
		table += '</tr></thead><tbody>';

		const esc = frappe.utils.escape_html;
		txns.forEach((t, i) => {
			const dateStr = t.date ? moment(t.date).format('DD.MM.YYYY') : '';
			const amountStr = parseFloat(t.amount || 0).toFixed(2);
			const drcrLabel = t.drcr === 'D'
				? '<span class="label label-danger">' + __('Pay') + '</span>'
				: '<span class="label label-success">' + __('Receive') + '</span>';
			const text = t.purpose || t.description || '';
			table += '<tr>' +
				'<td><input type="checkbox" class="bi-select-txn" data-idx="' + i + '"></td>' +
				'<td style="word-break:break-word;">' + esc(t.ref_no || '') + '</td>' +
				'<td>' + dateStr + '</td>' +
				'<td style="word-break:break-word;">' + esc(t.counterparty || '') + '</td>' +
				'<td style="text-align:right;">' + amountStr + '</td>' +
				'<td style="text-align:center;">' + drcrLabel + '</td>' +
				'<td style="word-break:break-word; font-size:0.9em;">' + esc(text) + '</td>' +
				'</tr>';
		});
		table += '</tbody></table></div>';

		const d = new frappe.ui.Dialog({
			title: __('Select Transactions to Import') + ' (' + txns.length + ')',
			size: 'large',
			fields: [{ fieldname: 'preview_html', fieldtype: 'HTML', options: table }],
			primary_action_label: __('Import Selected'),
			primary_action() {
				const selected = [];
				d.$wrapper.find('.bi-select-txn:checked').each(function () {
					const i = parseInt($(this).data('idx'), 10);
					selected.push(txns[i]);
				});
				if (!selected.length) {
					frappe.msgprint({
						title: __('No Selection'), indicator: 'orange',
						message: __('Please select at least one transaction.'),
					});
					return;
				}
				d.hide();
				BIExcelImport._runImport(selected, values, listview);
			},
		});
		d.$wrapper.find('.modal-dialog').css({ 'max-width': '90%', 'width': '90%' });
		d.show();

		d.$wrapper.find('.bi-select-all-txns').on('change', function () {
			d.$wrapper.find('.bi-select-txn').prop('checked', $(this).prop('checked'));
		});
	},

	_runImport(selected, values, listview) {
		const total = selected.length;
		// Freeze the page instead of using show_progress. show_progress relies
		// on a Bootstrap modal whose backdrop reliably gets stuck when we then
		// open a msgprint on completion; freeze is a simple full-page overlay
		// that unfreeze() always cleans up.
		frappe.dom.freeze(__('Starting import…'));

		frappe.realtime.off('bi_bt_import_progress');
		frappe.realtime.on('bi_bt_import_progress', function (d) {
			BIExcelImport._setFreezeMessage(__('Importing {0} of {1}…', [d.current, d.total]));
		});

		frappe.realtime.off('bi_bt_import_complete');
		frappe.realtime.on('bi_bt_import_complete', function (d) {
			frappe.realtime.off('bi_bt_import_progress');
			frappe.realtime.off('bi_bt_import_complete');
			frappe.dom.unfreeze();

			const ok = d.imported || 0;
			const errCount = (d.errors || []).length;

			let msg = '<div>' + __('Imported: <b>{0}</b>', [ok]) + '</div>';
			msg += '<div>' + __('Errors: <b>{0}</b>', [errCount]) + '</div>';

			const indicator = errCount === 0 ? 'green' : (ok > 0 ? 'orange' : 'red');
			const title = errCount === 0
				? __('Import Successful')
				: (ok === 0 ? __('Import Failed') : __('Import Completed with Errors'));

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

			if (errCount > 0 && d.errors) {
				BIExcelImport._lastErrors = d.errors;
				setTimeout(() => {
					if (!dlg) return;
					dlg.body.append(
						'<div style="text-align:center; margin-top:12px;">' +
						'<button class="btn btn-default btn-sm" id="bi-show-errors-btn">' +
						__('View Errors') + '</button></div>'
					);
					$('#bi-show-errors-btn').on('click', () => BIExcelImport._showErrorDetails());
				}, 200);
			}

			if (listview) listview.refresh();
		});

		frappe.call({
			method: 'jey_erp.bank_integration.import_api.import_bulk_bt',
			args: {
				txn_list: JSON.stringify(selected),
				bank_integration: values.bank_integration,
				bank_account: values.bank_account,
			},
			error() {
				frappe.realtime.off('bi_bt_import_progress');
				frappe.realtime.off('bi_bt_import_complete');
				frappe.dom.unfreeze();
				frappe.msgprint({
					title: __('Error'), indicator: 'red',
					message: __('Network error starting import'),
				});
			},
		});
	},

	// Replace the message on the active freeze overlay without re-freezing
	// (re-freezing stacks counter and breaks unfreeze pairing).
	_setFreezeMessage(msg) {
		const $msg = $('#freeze .freeze-message');
		if ($msg.length) {
			$msg.text(msg);
		}
	},

	_showDateParseHelp(droppedCount, bankIntegrationName) {
		const openForm = function () {
			frappe.set_route('Form', 'Bank Statement Importer', bankIntegrationName);
		};
		const d = new frappe.ui.Dialog({
			title: __('Date Format Not Recognized'),
			fields: [{
				fieldtype: 'HTML',
				options:
					'<div class="alert alert-danger">' +
					__('All {0} row(s) were dropped because the date column could not be parsed.', [droppedCount]) +
					'</div>' +
					'<p>' + __("The parser tries common formats like <code>2026-01-31</code>, <code>31.01.2026</code>, <code>01/31/2026</code> automatically.") + '</p>' +
					'<p>' + __("If your bank uses a different format, open the Bank Statement Importer's File Format tab and enable <b>Use Custom Date Format</b>, then enter the exact Python strftime format (e.g. <code>%d-%b-%Y</code> for <code>31-Jan-2026</code>).") + '</p>',
			}],
			primary_action_label: __('Open Bank Statement Importer'),
			primary_action() { d.hide(); openForm(); },
			secondary_action_label: __('Close'),
			secondary_action() { d.hide(); },
		});
		d.show();
	},

	_showAmountHelp(droppedCount, bankIntegrationName) {
		const openForm = function () {
			frappe.set_route('Form', 'Bank Statement Importer', bankIntegrationName);
		};
		const d = new frappe.ui.Dialog({
			title: __('Amount Column Missing or Empty'),
			fields: [{
				fieldtype: 'HTML',
				options:
					'<div class="alert alert-danger">' +
					__('All {0} row(s) were dropped because the amount could not be read.', [droppedCount]) +
					'</div>' +
					'<p>' + __('Most likely the <b>Amount</b> column (or <b>Debit</b>/<b>Credit</b>, depending on Amount Mode) is not mapped to an Excel header in the File Format tab.') + '</p>' +
					'<p>' + __('Open the Bank Statement Importer and check the Column Mappings table — Standard Field values must include all columns required by the chosen Amount Mode.') + '</p>',
			}],
			primary_action_label: __('Open Bank Statement Importer'),
			primary_action() { d.hide(); openForm(); },
			secondary_action_label: __('Close'),
			secondary_action() { d.hide(); },
		});
		d.show();
	},

	_showDirectionHelp(droppedCount, unknownDirections, bankIntegrationName) {
		const openForm = function () {
			frappe.set_route('Form', 'Bank Statement Importer', bankIntegrationName);
		};
		const sample = (unknownDirections || []).map(frappe.utils.escape_html).join(', ') || '?';
		const d = new frappe.ui.Dialog({
			title: __('Unknown Direction Values'),
			fields: [{
				fieldtype: 'HTML',
				options:
					'<div class="alert alert-danger">' +
					__('All {0} row(s) were dropped because the Direction column contained values not configured in the File Format tab.', [droppedCount]) +
					'</div>' +
					'<p>' + __('Unrecognised values:') + ' <code>' + sample + '</code></p>' +
					'<p>' + __('Open the Bank Statement Importer and add these to <b>Debit Values</b> (for outflows) or <b>Credit Values</b> (for inflows), comma-separated.') + '</p>',
			}],
			primary_action_label: __('Open Bank Statement Importer'),
			primary_action() { d.hide(); openForm(); },
			secondary_action_label: __('Close'),
			secondary_action() { d.hide(); },
		});
		d.show();
	},

	_showErrorDetails() {
		const errs = BIExcelImport._lastErrors || [];
		if (!errs.length) {
			frappe.msgprint(__('No error details'));
			return;
		}
		const esc = frappe.utils.escape_html;
		let html = '<div style="max-height:500px; overflow-y:auto;">';
		errs.forEach(e => {
			html += '<div style="margin-bottom:12px; padding:10px; border:1px solid var(--border-color); border-radius:6px;">';
			html += '<strong>' + esc(e.ref_no || 'No ref') + '</strong>';
			html += ' <span class="label label-danger" style="margin-left:8px;">' + esc(e.error_type || 'error') + '</span>';
			html += '<div style="margin-top:6px; color:var(--text-muted);">' +
				esc(e.counterparty || '') + ' — ' + parseFloat(e.amount || 0).toFixed(2) + '</div>';
			html += '<div style="margin-top:6px;"><code>' + esc(e.message || '') + '</code></div>';
			html += '</div>';
		});
		html += '</div>';
		const d = new frappe.ui.Dialog({
			title: __('Error Details') + ' (' + errs.length + ')',
			size: 'large',
			fields: [{ fieldname: 'errors_html', fieldtype: 'HTML', options: html }],
		});
		d.show();
	},
};

window.BIExcelImport = BIExcelImport;
