// Kapital Bank — Bank Reconciliation Tool integration
// Adds checkbox column + "Create & Reconcile" toolbar

frappe.ui.form.on("Bank Reconciliation Tool", {
	render: function (frm) {
		// Only activate if at least one Kapital Bank Login exists
		frappe.db.count("Kapital Bank Login").then(function (count) {
			if (!count) return;

			if (frm._kb_check_interval) clearInterval(frm._kb_check_interval);

			frm._kb_check_interval = setInterval(function () {
				const dtm = frm.bank_reconciliation_data_table_manager;
				if (dtm && dtm.datatable && !dtm._kb_enhanced) {
					clearInterval(frm._kb_check_interval);
					KBBRTMapping.enhance(frm, dtm);
				}
			}, 200);

			setTimeout(function () { clearInterval(frm._kb_check_interval); }, 15000);
		});
	},
});

const KBBRTMapping = {
	enhance: function (frm, dtm) {
		dtm._kb_enhanced = true;
		dtm._kb_frm = frm;

		// Rebuild DataTable with checkboxColumn: true
		dtm.datatable.destroy();
		dtm.datatable = new frappe.DataTable(dtm.$reconciliation_tool_dt.get(0), {
			columns: dtm.columns,
			data: dtm.transactions,
			dynamicRowHeight: true,
			checkboxColumn: true,
			inlineFilters: true,
		});
		$(`.${dtm.datatable.style.scopeClass} .dt-scrollable`).css("max-height", "calc(100vh - 400px)");

		// Restore ERPNext's Action-button listeners for the new datatable
		dtm.set_listeners();

		dtm._kb_scopeClass = dtm.datatable.style.scopeClass;

		KBBRTMapping.injectToolbar(dtm);
	},

	injectToolbar: function (dtm) {
		$("#kb-brt-mapping-toolbar").remove();

		const $toolbar = $(`
			<div id="kb-brt-mapping-toolbar"
				style="display:none; align-items:center; gap:10px; margin-bottom:8px;
				       padding:8px 12px; background:var(--fg-color);
				       border:1px solid var(--border-color); border-radius:6px;">
				<span class="kb-brt-selected-count text-muted"></span>
				<button class="btn btn-primary btn-sm kb-brt-create-mapping-btn">
					${__("Create & Reconcile")}
				</button>
			</div>
		`);

		dtm.$reconciliation_tool_dt.before($toolbar);

		const scopeClass = dtm.datatable.style.scopeClass;
		$(document).off("click.kb_brt_mapping").on(
			"click.kb_brt_mapping",
			`.${scopeClass} input[type="checkbox"]`,
			function () {
				setTimeout(() => KBBRTMapping.updateToolbar(dtm, $toolbar), 30);
			}
		);

		$toolbar.find(".kb-brt-create-mapping-btn").on("click", function () {
			KBBRTMapping.showMappingDialog(dtm);
		});
	},

	updateToolbar: function (dtm, $toolbar) {
		const checked = dtm.datatable.rowmanager.getCheckedRows();
		if (checked && checked.length > 0) {
			$toolbar.css("display", "flex");
			$toolbar.find(".kb-brt-selected-count").text(__("{0} row(s) selected", [checked.length]));
		} else {
			$toolbar.hide();
		}
	},

	showMappingDialog: function (dtm) {
		const checkedIndices = dtm.datatable.rowmanager.getCheckedRows();
		if (!checkedIndices || checkedIndices.length === 0) {
			frappe.msgprint({ title: __("Warning"), indicator: "orange", message: __("No rows selected.") });
			return;
		}

		// dtm.transactions row: [date, party_type, party(HTML), description, deposit, withdrawal, ..., reference_number, bank_transaction]
		const txns = [];
		let skippedCount = 0;
		checkedIndices.forEach(function (rowIndex) {
			const row = dtm.transactions[parseInt(rowIndex, 10)];
			if (!row) return;
			const description = (row[3] || "").trim();
			if (!description) { skippedCount++; return; }
			const partyType = (row[1] || "").trim();
			const partyName = $("<div>").html(row[2] || "").text().trim();
			const deposit = parseFloat(row[4]) || 0;
			const withdrawal = parseFloat(row[5]) || 0;
			const bankTransactionName = $(row[8] || "").data("name") || "";
			txns.push({
				purpose: description,
				drcr: withdrawal > 0 ? "D" : "C",
				party_type: partyType,
				party: partyName,
				amount: deposit || withdrawal,
				date: (row[0] || "").trim(),
				reference_number: (row[7] || "").trim(),
				bank_transaction_name: bankTransactionName,
			});
		});

		// Deduplicate for preview only
		const purposeMap = new Map();
		txns.forEach(function (txn) {
			const key = txn.purpose + "|" + txn.drcr;
			if (purposeMap.has(key)) {
				purposeMap.get(key).count++;
			} else {
				purposeMap.set(key, {
					purpose: txn.purpose,
					payment_type: txn.drcr === "D" ? "Pay" : "Receive",
					party: txn.party,
					count: 1,
				});
			}
		});

		if (purposeMap.size === 0) {
			frappe.msgprint({ title: __("No Purposes"), indicator: "orange",
				message: __("All selected rows have no description text.") });
			return;
		}

		// Preview table
		let previewHtml = '<div style="max-height:260px; overflow-y:auto; margin-bottom:12px;">' +
			'<table class="table table-bordered" style="width:100%;">' +
			"<thead><tr>" +
			"<th>" + __("Description") + "</th>" +
			'<th style="width:90px;">' + __("Type") + "</th>" +
			'<th style="width:140px;">' + __("Party") + "</th>" +
			'<th style="width:60px; text-align:center;">' + __("Rows") + "</th>" +
			"</tr></thead><tbody>";
		purposeMap.forEach(function (e) {
			const badge = e.payment_type === "Pay"
				? '<span class="label label-danger">Pay</span>'
				: '<span class="label label-success">Receive</span>';
			previewHtml += "<tr>" +
				'<td style="word-break:break-word;font-size:0.9em;">' + frappe.utils.escape_html(e.purpose) + "</td>" +
				"<td>" + badge + "</td>" +
				"<td>" + (e.party ? frappe.utils.escape_html(e.party) : '<span class="text-muted">—</span>') + "</td>" +
				'<td style="text-align:center;">' + e.count + "</td></tr>";
		});
		previewHtml += "</tbody></table></div>";
		if (skippedCount > 0) {
			previewHtml += '<div class="alert alert-warning">' +
				__("{0} row(s) skipped — no description text.", [skippedCount]) + "</div>";
		}

		const d = new frappe.ui.Dialog({
			title: __("Create & Reconcile") + " (" + purposeMap.size + ")",
			size: "large",
			fields: [
				{
					fieldname: "mode",
					fieldtype: "Select",
					label: __("Action"),
					options: "Both\nMappings Only\nDocuments & Reconcile",
					default: "Both",
					reqd: 1,
				},
				{ fieldname: "preview_html", fieldtype: "HTML", options: previewHtml },
				{ fieldname: "sec_options", fieldtype: "Section Break", label: __("Options") },
				{
					fieldname: "document_type",
					fieldtype: "Select",
					label: __("Document Type"),
					options: "Payment Entry\nJournal Entry",
					default: "Payment Entry",
					reqd: 1,
				},
				{
					fieldname: "use_custom_purpose",
					fieldtype: "Check",
					label: __("Use custom purpose keyword"),
					onchange: function () {
						const on = d.get_value("use_custom_purpose");
						d.set_df_property("custom_purpose", "hidden", on ? 0 : 1);
						d.set_df_property("custom_purpose", "reqd", on ? 1 : 0);
						d.get_field("custom_purpose").refresh();
					},
				},
				{
					fieldname: "custom_purpose",
					fieldtype: "Data",
					label: __("Custom Purpose Keyword"),
					hidden: 1,
					description: __("All selected rows will be mapped with this purpose instead of their own description"),
				},
				{ fieldname: "sec_accounts", fieldtype: "Section Break", label: __("GL Accounts") },
				{
					fieldname: "paid_from", fieldtype: "Link", options: "Account",
					label: __("Paid From (Account)"), reqd: 1,
				},
				{ fieldname: "col_break", fieldtype: "Column Break" },
				{
					fieldname: "paid_to", fieldtype: "Link", options: "Account",
					label: __("Paid To (Account)"), reqd: 1,
				},
			],
			primary_action_label: __("Create & Reconcile"),
			primary_action: function () {
				const values = d.get_values();
				if (!values) return;

				let finalTxns = txns.slice();
				if (values.use_custom_purpose && (values.custom_purpose || "").trim()) {
					const cp = values.custom_purpose.trim();
					finalTxns = txns.map(t => Object.assign({}, t, { purpose: cp }));
				}

				KBBRTMapping.submitMappings(d, finalTxns, values.paid_from, values.paid_to, values.document_type, values.mode);
			},
		});

		d._kb_frm = dtm._kb_frm;
		d.show();

		// Pre-fill custom purpose from the Description inline filter if active
		const $fi = $(`.${dtm._kb_scopeClass} .dt-row-filter input.dt-filter[data-name="Description"]`);
		const filterVal = ($fi.val() || "").trim();
		if (filterVal) {
			d.set_df_property("custom_purpose", "hidden", 0);
			d.set_df_property("custom_purpose", "reqd", 1);
			d.set_value("use_custom_purpose", 1);
			d.set_value("custom_purpose", filterVal);
			d.get_field("custom_purpose").refresh();
		}
	},

	submitMappings: function (dialog, txns, paid_from, paid_to, document_type, mode) {
		dialog.disable_primary_action();
		frappe.call({
			method: "kapital_bank.mapping.create_purpose_mappings",
			args: {
				transactions: JSON.stringify(txns),
				paid_from: paid_from,
				paid_to: paid_to,
				document_type: document_type || "Payment Entry",
				mode: mode || "Both",
			},
			callback: function (r) {
				dialog.enable_primary_action();
				if (!r.message || !r.message.success) {
					frappe.msgprint({ title: __("Error"), indicator: "red",
						message: r.message ? r.message.message : __("Unknown error") });
					return;
				}
				dialog.hide();
				const res = r.message;
				const parts = [];
				if (res.created_mappings) parts.push(__("Mappings created: {0}", [res.created_mappings]));
				if (res.already_mapped) parts.push(__("Already mapped: {0}", [res.already_mapped]));
				if (res.skipped_no_data) parts.push(__("Skipped (no purpose): {0}", [res.skipped_no_data]));
				if (res.created_docs) parts.push(__("Documents created: {0}", [res.created_docs]));
				if (res.reconciled) parts.push(__("Reconciled: {0}", [res.reconciled]));
				if (res.errors && res.errors.length) parts.push(__("Errors: {0}", [res.errors.length]));
				frappe.show_alert({
					message: parts.join(" &bull; ") || __("No changes"),
					indicator: (res.created_mappings > 0 || res.created_docs > 0) ? "green" : "blue",
				}, 5);
				if (dialog._kb_frm) dialog._kb_frm.refresh();
				if (res.errors && res.errors.length) {
					KBBRTMapping.showErrors(res.errors);
				}
			},
			error: function () {
				dialog.enable_primary_action();
				frappe.msgprint({ title: __("Error"), indicator: "red",
					message: __("Network error creating mappings") });
			},
		});
	},

	showErrors: function (errors) {
		let html = '<div style="max-height:500px; overflow-y:auto;">';
		errors.forEach(function (err) {
			const ref = err.reference_number || __("Unknown");
			html += '<div style="margin-bottom:14px; padding:12px; border:1px solid var(--border-color); border-radius:6px; background:var(--bg-color);">';
			html += '<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:6px; padding-bottom:6px; border-bottom:1px solid var(--border-color);">';
			html += '<strong>' + frappe.utils.escape_html(ref) + '</strong>';
			html += '<span class="label label-danger">' + __("Error") + '</span>';
			html += '</div>';
			html += '<div style="color:var(--text-color);">' + frappe.utils.escape_html(err.message || __("Unknown error")) + '</div>';
			html += '</div>';
		});
		html += '</div>';

		const d = new frappe.ui.Dialog({
			title: __("Errors ({0})", [errors.length]),
			size: "large",
			fields: [{ fieldname: "errors_html", fieldtype: "HTML", options: html }],
			primary_action_label: __("Close"),
			primary_action: function () { d.hide(); },
		});
		d.show();
	},
};
