frappe.ui.form.on('Kapital Bank Settings', {
	setup(frm) {
		// Customer/Supplier Group and Territory must be leaf (non-group) nodes.
		const leaf = () => ({ filters: { is_group: 0 } });
		frm.set_query('default_customer_group', leaf);
		frm.set_query('default_supplier_group', leaf);
		frm.set_query('default_territory', leaf);
		frm.set_query('customer_group', 'customer_mappings', leaf);
		frm.set_query('territory', 'customer_mappings', leaf);
		frm.set_query('supplier_group', 'supplier_mappings', leaf);
		frm.set_query('cost_center', 'transaction_mappings', leaf);
	},

	refresh(frm) {
		// ── Main: Load Data from Kapital Bank ────────────────────────────────
		frm.add_custom_button(__('Load Data'), () => {
			show_load_data_dialog(frm);
		}, __('Kapital Bank'));

		frm.add_custom_button(__('Sync Bank Codes'), () => {
			frappe.show_alert({ message: __('Syncing bank codes...'), indicator: 'blue' });
			frappe.call({
				method: 'kapital_bank.payment_api.sync_bank_codes',
				callback(r) {
					const res = r.message;
					if (!res) return;
					frappe.show_alert({
						message: __('Bank codes synced: {0} added, {1} updated (total {2})', [res.added, res.updated, res.total]),
						indicator: 'green',
					}, 6);
				},
			});
		}, __('Kapital Bank'));

		// ── Accounts buttons ──────────────────────────────────────────────────
		frm.add_custom_button(__('Match accounts to Bank Accounts'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => _match_accounts(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				_match_accounts(frm);
			}
		}, __('Accounts'));

		frm.add_custom_button(__('Create Bank Accounts'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => create_unmapped_bank_accounts(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				create_unmapped_bank_accounts(frm);
			}
		}, __('Accounts'));

		frm.add_custom_button(__('Add unmapped accounts'), () => {
			if (frm.is_dirty()) {
				frm.save().then(() => add_unmapped_accounts(frm));
			} else {
				add_unmapped_accounts(frm);
			}
		}, __('Accounts'));

		// ── Cards buttons ────────────────────────────────────────────────────
		frm.add_custom_button(__('Match cards to Bank Accounts'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => _match_cards(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				_match_cards(frm);
			}
		}, __('Cards'));

		frm.add_custom_button(__('Create Bank Accounts for cards'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => create_unmapped_bank_accounts_for_cards(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				create_unmapped_bank_accounts_for_cards(frm);
			}
		}, __('Cards'));

		frm.add_custom_button(__('Add unmapped cards'), () => {
			if (frm.is_dirty()) {
				frm.save().then(() => add_unmapped_cards(frm));
			} else {
				add_unmapped_cards(frm);
			}
		}, __('Cards'));

		// ── Customers buttons ─────────────────────────────────────────────────
		frm.add_custom_button(__('Match customers by similar name'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => _match_customers(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				_match_customers(frm);
			}
		}, __('Customers'));

		frm.add_custom_button(__('Create matching customers'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => create_unmapped_customers(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				create_unmapped_customers(frm);
			}
		}, __('Customers'));

		frm.add_custom_button(__('Add unmapped customers'), () => {
			if (frm.is_dirty()) {
				frm.save().then(() => add_unmapped_customers(frm));
			} else {
				add_unmapped_customers(frm);
			}
		}, __('Customers'));

		// ── Suppliers buttons ─────────────────────────────────────────────────
		frm.add_custom_button(__('Match suppliers by similar name'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => _match_suppliers(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				_match_suppliers(frm);
			}
		}, __('Suppliers'));

		frm.add_custom_button(__('Create matching suppliers'), () => {
			if (frm.is_dirty()) {
				frappe.confirm(
					__('Document contains unsaved changes. Save before performing the operation?'),
					() => frm.save().then(() => create_unmapped_suppliers(frm)),
					() => frappe.show_alert({ message: __('Operation canceled. Please save the document first.'), indicator: 'red' }, 5)
				);
			} else {
				create_unmapped_suppliers(frm);
			}
		}, __('Suppliers'));

		frm.add_custom_button(__('Add unmapped suppliers'), () => {
			if (frm.is_dirty()) {
				frm.save().then(() => add_unmapped_suppliers(frm));
			} else {
				add_unmapped_suppliers(frm);
			}
		}, __('Suppliers'));

		// ── Purpose buttons ───────────────────────────────────────────────────
		frm.add_custom_button(__('Add unmapped purposes'), () => {
			if (frm.is_dirty()) {
				frm.save().then(() => add_unmapped_purposes(frm));
			} else {
				add_unmapped_purposes(frm);
			}
		}, __('Purpose'));

		// ── Bulk Edit buttons for mapping tables ─────────────────────────────
		const mapping_tables = [
			'account_mappings', 'card_mappings', 'customer_mappings',
			'supplier_mappings', 'transaction_mappings'
		];
		mapping_tables.forEach(table => {
			frm.fields_dict[table]?.grid.add_custom_button(__('Bulk Edit'), () => {
				bulk_edit_table(frm, table);
			});
		});

		// ── Workflow wizard (current step + expandable step list) ─────────────
		_kb_render_form_wizard(frm);

		// ── Populate data tabs ────────────────────────────────────────────────
		load_data_tabs(frm);
	}
});

// ═══════════════════════════════════════════════════════════════════════════════
// MATCH HELPERS
// ═══════════════════════════════════════════════════════════════════════════════

function _match_customers(frm) {
	frappe.confirm(
		__('This will automatically match unmapped customers with similar Customer names. Continue?'),
		() => {
			frappe.show_alert({ message: __('Matching customers...'), indicator: 'blue' });
			frappe.call({
				method: 'kapital_bank.bank_api.match_similar_customers',
				callback(r) {
					if (r.message && r.message.success) {
						frappe.show_alert({
							message: __('Matched {0} of {1} customers', [r.message.matched_count, r.message.total_processed]),
							indicator: 'green'
						}, 5);
						frm.reload_doc();
					} else {
						frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error matching customers') });
					}
				}
			});
		}
	);
}

function _match_suppliers(frm) {
	frappe.confirm(
		__('This will automatically match unmapped suppliers with similar Supplier names. Continue?'),
		() => {
			frappe.show_alert({ message: __('Matching suppliers...'), indicator: 'blue' });
			frappe.call({
				method: 'kapital_bank.bank_api.match_similar_suppliers',
				callback(r) {
					if (r.message && r.message.success) {
						frappe.show_alert({
							message: __('Matched {0} of {1} suppliers', [r.message.matched_count, r.message.total_processed]),
							indicator: 'green'
						}, 5);
						frm.reload_doc();
					} else {
						frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error matching suppliers') });
					}
				}
			});
		}
	);
}

// ═══════════════════════════════════════════════════════════════════════════════
// MATCH / CREATE ACCOUNTS & CARDS
// ═══════════════════════════════════════════════════════════════════════════════

function _match_accounts(frm) {
	frappe.confirm(
		__('This will automatically match unmapped accounts with existing Bank Accounts by IBAN. Continue?'),
		() => {
			frappe.show_alert({ message: __('Matching accounts...'), indicator: 'blue' });
			frappe.call({
				method: 'kapital_bank.bank_api.match_similar_accounts',
				callback(r) {
					if (r.message && r.message.success) {
						frappe.show_alert({
							message: __('Matched {0} of {1} accounts', [r.message.matched_count, r.message.total_processed]),
							indicator: 'green'
						}, 5);
						frm.reload_doc();
					} else {
						frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error matching accounts') });
					}
				}
			});
		}
	);
}

function create_unmapped_bank_accounts(frm) {
	frappe.confirm(
		__('<div style="color:red;font-weight:bold;">WARNING! This will create new Bank Account records for all unmapped accounts!</div><p>This action is irreversible. Are you sure?</p>'),
		function() {
			frappe.confirm(
				__('Are you really sure? This cannot be undone.'),
				function() {
					frappe.call({
						method: 'kapital_bank.bank_api.create_unmapped_accounts',
						args: { 'settings_name': frm.doc.name },
						callback: function(r) {
							if (r.message && r.message.success) {
								frappe.show_alert({
									message: __('Created {0} new Bank Accounts', [r.message.created_count]),
									indicator: 'green'
								}, 6);
								frm.reload_doc();
							} else {
								frappe.msgprint({
									title: __('Error'),
									indicator: 'red',
									message: r.message ? r.message.message : __('Error creating Bank Accounts')
								});
							}
						}
					});
				}
			);
		}
	);
}

function _match_cards(frm) {
	frappe.confirm(
		__('This will automatically match unmapped cards with existing Bank Accounts by account number. Continue?'),
		() => {
			frappe.show_alert({ message: __('Matching cards...'), indicator: 'blue' });
			frappe.call({
				method: 'kapital_bank.bank_api.match_similar_cards',
				callback(r) {
					if (r.message && r.message.success) {
						frappe.show_alert({
							message: __('Matched {0} of {1} cards', [r.message.matched_count, r.message.total_processed]),
							indicator: 'green'
						}, 5);
						frm.reload_doc();
					} else {
						frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error matching cards') });
					}
				}
			});
		}
	);
}

function create_unmapped_bank_accounts_for_cards(frm) {
	frappe.confirm(
		__('<div style="color:red;font-weight:bold;">WARNING! This will create new Bank Account records for all unmapped cards!</div><p>This action is irreversible. Are you sure?</p>'),
		function() {
			frappe.confirm(
				__('Are you really sure? This cannot be undone.'),
				function() {
					frappe.call({
						method: 'kapital_bank.bank_api.create_unmapped_cards',
						args: { 'settings_name': frm.doc.name },
						callback: function(r) {
							if (r.message && r.message.success) {
								frappe.show_alert({
									message: __('Created {0} new Bank Accounts for cards', [r.message.created_count]),
									indicator: 'green'
								}, 6);
								frm.reload_doc();
							} else {
								frappe.msgprint({
									title: __('Error'),
									indicator: 'red',
									message: r.message ? r.message.message : __('Error creating Bank Accounts for cards')
								});
							}
						}
					});
				}
			);
		}
	);
}

// ═══════════════════════════════════════════════════════════════════════════════
// LOAD DATA DIALOG
// ═══════════════════════════════════════════════════════════════════════════════

function show_load_data_dialog(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_summary',
		callback(r) {
			const summary = (r.message && r.message.success) ? r.message.summary : {};
			open_load_dialog(frm, summary);
		}
	});
}

function open_load_dialog(frm, summary) {
	let summary_html = `<div style="background:#f8f9fa;padding:15px;border-radius:6px;margin-bottom:15px;">
		<h5 style="margin-bottom:15px;">${__('Current Registry Data')}</h5>
		<div style="display:flex;gap:10px;">`;

	const types = [
		{ key: 'accounts',  label: __('Accounts') },
		{ key: 'cards',     label: __('Cards') },
		{ key: 'customers', label: __('Customers') },
		{ key: 'suppliers', label: __('Suppliers') },
		{ key: 'purposes',  label: __('Purposes') }
	];
	types.forEach(t => {
		const d = summary[t.key] || { total: 0, mapped: 0 };
		const unmapped = d.total - d.mapped;
		const pct = d.total > 0 ? Math.round(d.mapped / d.total * 100) : 0;
		summary_html += `<div style="flex:1;text-align:center;border:1px solid #ddd;padding:10px;border-radius:4px;background:#fff;">
				<h6 style="margin-bottom:8px;">${t.label}</h6>
				<div><strong>${d.total}</strong> ${__('total')}</div>
				<div style="color:#28a745;"><strong>${d.mapped}</strong> ${__('mapped')}</div>
				<div style="color:#dc3545;"><strong>${unmapped}</strong> ${__('unmapped')}</div>
				<div style="font-size:11px;color:#666;margin-top:4px;">${pct}% ${__('mapped')}</div>
			</div>`;
	});
	summary_html += '</div></div>';

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

	const d = new frappe.ui.Dialog({
		size: 'large',
		title: __('Load Data from Kapital Bank'),
		fields: [
			{ fieldname: 'summary_html', fieldtype: 'HTML', options: summary_html },
			{ fieldname: 'sec_period', fieldtype: 'Section Break', label: __('Period (for counterparties and purposes from statements)') },
			{ fieldname: 'date_from', fieldtype: 'Date', label: __('Date From'), default: first_day, reqd: 0 },
			{ fieldname: 'col_break', fieldtype: 'Column Break' },
			{ fieldname: 'date_to',   fieldtype: 'Date', label: __('Date To'),   default: last_day,  reqd: 0 },
			{ fieldname: 'sec_what', fieldtype: 'Section Break', label: __('What to load') },
			{ fieldname: 'load_accounts', fieldtype: 'Check', label: __('Load Accounts'), default: 1,
			  description: __('Fetch current accounts') },
			{ fieldname: 'load_cards', fieldtype: 'Check', label: __('Load Cards'), default: 1,
			  description: __('Fetch current business cards') },
			{ fieldname: 'load_counterparties', fieldtype: 'Check', label: __('Load Counterparties from statements'), default: 1,
			  description: __('Extract counterparties from account statement transactions for the selected period') },
			{ fieldname: 'load_purposes', fieldtype: 'Check', label: __('Load Purposes from statements'), default: 1,
			  description: __('Extract unique purposes from account statement transactions for the selected period') }
		],
		primary_action_label: __('Load'),
		primary_action(values) {
			if ((values.load_counterparties || values.load_purposes) && (!values.date_from || !values.date_to)) {
				frappe.msgprint(__('Please set Date From and Date To to load counterparties/purposes from statements.'));
				return;
			}
			d.hide();
			start_loading(frm, values);
		}
	});
	d.show();
}

function start_loading(frm, values) {
	const operations = [];
	if (values.load_accounts) {
		operations.push({
			method: 'kapital_bank.bank_api.load_accounts_to_registry',
			label: __('Accounts'),
			args: {},
			format_result(r) {
				if (r.message && r.message.success) {
					return __('Accounts: {0} created, {1} updated', [r.message.created, r.message.updated]);
				}
				return __('Accounts error: {0}', [r.message ? r.message.message : 'unknown']);
			}
		});
	}
	if (values.load_cards) {
		operations.push({
			method: 'kapital_bank.bank_api.load_cards_to_registry',
			label: __('Cards'),
			args: {},
			format_result(r) {
				if (r.message && r.message.success) {
					return __('Cards: {0} created, {1} updated', [r.message.created, r.message.updated]);
				}
				return __('Cards error: {0}', [r.message ? r.message.message : 'unknown']);
			}
		});
	}
	if (values.load_counterparties) {
		operations.push({
			method: 'kapital_bank.bank_api.load_counterparties_from_statements',
			label: __('Counterparties'),
			args: { from_date: values.date_from, to_date: values.date_to },
			format_result(r) {
				if (r.message && r.message.success) {
					return __('Counterparties: {0} customers, {1} suppliers, {2} skipped',
						[r.message.customers_created, r.message.suppliers_created, r.message.skipped]);
				}
				return __('Counterparties error: {0}', [r.message ? r.message.message : 'unknown']);
			}
		});
	}
	if (values.load_purposes) {
		operations.push({
			method: 'kapital_bank.bank_api.load_purposes_from_statements',
			label: __('Purposes'),
			args: { from_date: values.date_from, to_date: values.date_to },
			format_result(r) {
				if (r.message && r.message.success) {
					return __('Purposes: {0} created, {1} updated ({2} found)',
					[r.message.created, r.message.updated, r.message.total_found]);
				}
				return __('Purposes error: {0}', [r.message ? r.message.message : 'unknown']);
			}
		});
	}

	
	if (operations.length === 0) {
		frappe.show_alert({ message: __('Nothing selected'), indicator: 'orange' }, 3);
		return;
	}

	let current = 0;
	const results = [];
	let has_errors = false;

	function run_next() {
		if (current >= operations.length) {
			frappe.hide_progress();
			frappe.show_alert({
				message: results.join(' | '),
				indicator: has_errors ? 'red' : 'green'
			}, 6);
			frm.reload_doc();
			return;
		}

		const op = operations[current];
		frappe.show_progress(
			__('Loading Data'),
			current,
			operations.length,
			__('Loading {0}...', [op.label])
		);

		frappe.call({
			method: op.method,
			args: op.args,
			callback(r) {
				const result_text = op.format_result(r);
				if (!r.message || !r.message.success) has_errors = true;
				results.push(result_text);
				current++;
				frappe.show_progress(
					__('Loading Data'),
					current,
					operations.length,
					current < operations.length
						? __('Loading {0}...', [operations[current].label])
						: __('Done')
				);
				setTimeout(run_next, 100);
			},
			error() {
				has_errors = true;
				results.push(op.label + ': error');
				current++;
				setTimeout(run_next, 100);
			}
		});
	}

	run_next();
}

// ═══════════════════════════════════════════════════════════════════════════════
// ADD UNMAPPED TO MAPPING TABLES
// ═══════════════════════════════════════════════════════════════════════════════

function add_unmapped_accounts(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_unmapped_accounts',
		callback(r) {
			if (!r.message || !r.message.success) {
				frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error') });
				return;
			}
			const accounts = r.message.accounts;
			if (!accounts || accounts.length === 0) {
				frappe.show_alert({ message: __('No unmapped accounts found'), indicator: 'blue' }, 5);
				return;
			}
			accounts.forEach(a => {
				const row = frm.add_child('account_mappings');
				row.iban = a.iban;
				row.account_label = a.account_desc || a.iban;
				row.currency = a.currency || '';
			});
			frm.refresh_field('account_mappings');
			frm.save().then(() => {
				frappe.show_alert({ message: __('Added {0} accounts to mapping', [accounts.length]), indicator: 'green' }, 5);
				load_accounts_tab();
			});
		}
	});
}

function add_unmapped_cards(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_unmapped_cards',
		callback(r) {
			if (!r.message || !r.message.success) {
				frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error') });
				return;
			}
			const cards = r.message.cards;
			if (!cards || cards.length === 0) {
				frappe.show_alert({ message: __('No unmapped cards found'), indicator: 'blue' }, 5);
				return;
			}
			cards.forEach(c => {
				const row = frm.add_child('card_mappings');
				row.account_number = c.account_number;
				row.card_label = c.pan ? (c.pan + ' (' + (c.card_type || '') + ')') : c.account_number;
				row.currency = c.currency || '';
			});
			frm.refresh_field('card_mappings');
			frm.save().then(() => {
				frappe.show_alert({ message: __('Added {0} cards to mapping', [cards.length]), indicator: 'green' }, 5);
				load_cards_tab();
			});
		}
	});
}

function add_unmapped_customers(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_unmapped_customers',
		callback(r) {
			if (!r.message || !r.message.success) {
				frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error') });
				return;
			}
			const customers = r.message.customers;
			if (!customers || customers.length === 0) {
				frappe.show_alert({ message: __('No unmapped customers found'), indicator: 'blue' }, 5);
				return;
			}
			customers.forEach(c => {
				const row = frm.add_child('customer_mappings');
				row.kb_customer_name = c.name;
				row.tax_id = c.tax_id || '';
				row.mapping_type = 'Manual';
			});
			frm.refresh_field('customer_mappings');
			frm.save().then(() => {
				frappe.show_alert({ message: __('Added {0} customers to mapping', [customers.length]), indicator: 'green' }, 5);
				load_customers_tab();
			});
		}
	});
}

function add_unmapped_suppliers(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_unmapped_suppliers',
		callback(r) {
			if (!r.message || !r.message.success) {
				frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error') });
				return;
			}
			const suppliers = r.message.suppliers;
			if (!suppliers || suppliers.length === 0) {
				frappe.show_alert({ message: __('No unmapped suppliers found'), indicator: 'blue' }, 5);
				return;
			}
			suppliers.forEach(s => {
				const row = frm.add_child('supplier_mappings');
				row.kb_supplier_name = s.name;
				row.tax_id = s.tax_id || '';
				row.mapping_type = 'Manual';
			});
			frm.refresh_field('supplier_mappings');
			frm.save().then(() => {
				frappe.show_alert({ message: __('Added {0} suppliers to mapping', [suppliers.length]), indicator: 'green' }, 5);
				load_suppliers_tab();
			});
		}
	});
}

function add_unmapped_purposes(frm) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_unmapped_purposes',
		callback(r) {
			if (!r.message || !r.message.success) {
				frappe.msgprint({ title: __('Error'), indicator: 'red', message: r.message ? r.message.message : __('Error') });
				return;
			}
			const purposes = r.message.purposes;
			if (!purposes || purposes.length === 0) {
				frappe.show_alert({ message: __('No unmapped purposes found'), indicator: 'blue' }, 5);
				return;
			}
			let added = 0;
			purposes.forEach(p => {
				if (p.direction === 'Both') {
					const row_pay = frm.add_child('transaction_mappings');
					row_pay.purpose_keyword = p.name;
					row_pay.payment_type = 'Pay';
					const row_recv = frm.add_child('transaction_mappings');
					row_recv.purpose_keyword = p.name;
					row_recv.payment_type = 'Receive';
					added += 2;
				} else {
					const row = frm.add_child('transaction_mappings');
					row.purpose_keyword = p.name;
					row.payment_type = p.direction || '';
					added += 1;
				}
			});
			frm.refresh_field('transaction_mappings');
			frm.save().then(() => {
				frappe.show_alert({ message: __('Added {0} rows to mapping ({1} purposes)', [added, purposes.length]), indicator: 'green' }, 5);
				load_purposes_tab();
			});
		}
	});
}

function create_unmapped_customers(frm) {
	frappe.confirm(
		__('<div style="color:red;font-weight:bold;">WARNING! This will create new Customer records for all unmapped customers!</div><p>This action is irreversible. Are you sure?</p>'),
		function() {
			frappe.confirm(
				__('Are you really sure? This cannot be undone.'),
				function() {
					frappe.call({
						method: 'kapital_bank.bank_api.create_unmapped_customers',
						args: { 'settings_name': frm.doc.name },
						callback: function(r) {
							if (r.message && r.message.success) {
								frappe.show_alert({
									message: __('Created {0} new customers', [r.message.created_count]),
									indicator: 'green'
								}, 6);
								frm.reload_doc();
							} else {
								frappe.msgprint({
									title: __('Error'),
									indicator: 'red',
									message: r.message ? r.message.message : __('Error creating customers')
								});
							}
						}
					});
				}
			);
		}
	);
}

function create_unmapped_suppliers(frm) {
	frappe.confirm(
		__('<div style="color:red;font-weight:bold;">WARNING! This will create new Supplier records for all unmapped suppliers!</div><p>This action is irreversible. Are you sure?</p>'),
		function() {
			frappe.confirm(
				__('Are you really sure? This cannot be undone.'),
				function() {
					frappe.call({
						method: 'kapital_bank.bank_api.create_unmapped_suppliers',
						args: { 'settings_name': frm.doc.name },
						callback: function(r) {
							if (r.message && r.message.success) {
								frappe.show_alert({
									message: __('Created {0} new suppliers', [r.message.created_count]),
									indicator: 'green'
								}, 6);
								frm.reload_doc();
							} else {
								frappe.msgprint({
									title: __('Error'),
									indicator: 'red',
									message: r.message ? r.message.message : __('Error creating suppliers')
								});
							}
						}
					});
				}
			);
		}
	);
}

// ═══════════════════════════════════════════════════════════════════════════════
// DATA TABS
// ═══════════════════════════════════════════════════════════════════════════════

function load_data_tabs(frm) {
	load_accounts_tab();
	load_cards_tab();
	load_customers_tab();
	load_suppliers_tab();
	load_purposes_tab();
}

// ─── Accounts tab ────────────────────────────────────────────────────────────

function load_accounts_tab() {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_list',
		args: { data_type: 'accounts', limit: 100, offset: 0 },
		callback(r) {
			if (r.message && r.message.success) {
				render_accounts_list(r.message.data, r.message.total_count);
			} else {
				const msg = r.message ? r.message.message : __('Unknown error');
				$('#kb-accounts-container').html(error_html(msg, load_accounts_tab));
			}
		},
		error() { $('#kb-accounts-container').html(error_html(__('Network error'), load_accounts_tab)); }
	});
}

function render_accounts_list(accounts, total_count) {
	let html = list_header(__('Accounts'), total_count, 'kb-refresh-accounts');

	if (accounts && accounts.length > 0) {
		html += `<table class="table table-bordered" style="font-size:13px;">
			<thead class="grid-heading-row"><tr>
				<th>${__('IBAN')}</th>
				<th>${__('Currency')}</th>
				<th>${__('Current Balance')}</th>
				<th>${__('Planned Balance')}</th>
				<th>${__('Account Status')}</th>
				<th>${__('Status')}</th>
				<th>${__('Mapped To')}</th>
			</tr></thead><tbody>`;
		accounts.forEach(a => {
			const pill = a.status === 'Mapped' ? 'green' : 'red';
			const mapped_to = a.bank_account ? `<a href="/app/bank-account/${a.bank_account}">${a.bank_account}</a>` : '-';
			html += `<tr>
				<td><a href="/app/kapital-bank-account/${a.name}">${a.iban}</a></td>
				<td>${a.currency || '-'}</td>
				<td class="text-right">${fmt_num(a.current_balance)}</td>
				<td class="text-right">${fmt_num(a.planned_balance)}</td>
				<td>${a.account_status || '-'}</td>
				<td><span class="indicator-pill ${pill}">${__(a.status)}</span></td>
				<td>${mapped_to}</td>
			</tr>`;
		});
		html += '</tbody></table>';
		if (total_count > accounts.length) {
			html += `<p class="text-muted small">${__('Showing {0} of {1}', [accounts.length, total_count])} — <a href="/app/kapital-bank-account">${__('View All')}</a></p>`;
		}
	} else {
		html += empty_state(__('No accounts in registry. Use "Load Data" to fetch from Kapital Bank.'));
	}

	$('#kb-accounts-container').html(html);
	$('#kb-refresh-accounts').on('click', () => {
		$('#kb-accounts-container').html(loading_html());
		load_accounts_tab();
	});
}

// ─── Cards tab ───────────────────────────────────────────────────────────────

function load_cards_tab() {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_list',
		args: { data_type: 'cards', limit: 100, offset: 0 },
		callback(r) {
			if (r.message && r.message.success) {
				render_cards_list(r.message.data, r.message.total_count);
			} else {
				const msg = r.message ? r.message.message : __('Unknown error');
				$('#kb-cards-container').html(error_html(msg, load_cards_tab));
			}
		},
		error() { $('#kb-cards-container').html(error_html(__('Network error'), load_cards_tab)); }
	});
}

function render_cards_list(cards, total_count) {
	let html = list_header(__('Cards'), total_count, 'kb-refresh-cards');

	if (cards && cards.length > 0) {
		html += `<table class="table table-bordered" style="font-size:13px;">
			<thead class="grid-heading-row"><tr>
				<th>${__('PAN')}</th>
				<th>${__('Card Type')}</th>
				<th>${__('Account Number')}</th>
				<th>${__('Currency')}</th>
				<th>${__('Balance')}</th>
				<th>${__('Expiry')}</th>
				<th>${__('Status')}</th>
				<th>${__('Mapped To')}</th>
			</tr></thead><tbody>`;
		cards.forEach(c => {
			const pill = c.status === 'Mapped' ? 'green' : 'red';
			const mapped_to = c.bank_account ? `<a href="/app/bank-account/${c.bank_account}">${c.bank_account}</a>` : '-';
			html += `<tr>
				<td><a href="/app/kapital-bank-card/${c.name}"><strong>${c.pan || '-'}</strong></a></td>
				<td>${c.card_type || '-'}</td>
				<td>${c.account_number || '-'}</td>
				<td>${c.currency || '-'}</td>
				<td class="text-right">${fmt_num(c.balance)}</td>
				<td>${c.expiry_date || '-'}</td>
				<td><span class="indicator-pill ${pill}">${__(c.status)}</span></td>
				<td>${mapped_to}</td>
			</tr>`;
		});
		html += '</tbody></table>';
		if (total_count > cards.length) {
			html += `<p class="text-muted small">${__('Showing {0} of {1}', [cards.length, total_count])} — <a href="/app/kapital-bank-card">${__('View All')}</a></p>`;
		}
	} else {
		html += empty_state(__('No cards in registry. Use "Load Data" to fetch from Kapital Bank.'));
	}

	$('#kb-cards-container').html(html);
	$('#kb-refresh-cards').on('click', () => {
		$('#kb-cards-container').html(loading_html());
		load_cards_tab();
	});
}

// ─── Customers tab ───────────────────────────────────────────────────────────

function load_customers_tab() {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_list',
		args: { data_type: 'customers', limit: 100, offset: 0 },
		callback(r) {
			if (r.message && r.message.success) {
				render_customers_list(r.message.data, r.message.total_count);
			} else {
				const msg = r.message ? r.message.message : __('Unknown error');
				$('#kb-customers-container').html(error_html(msg, load_customers_tab));
			}
		},
		error() { $('#kb-customers-container').html(error_html(__('Network error'), load_customers_tab)); }
	});
}

function render_customers_list(customers, total_count) {
	let html = list_header(__('Customers'), total_count, 'kb-refresh-customers');

	if (customers && customers.length > 0) {
		html += `<table class="table table-bordered" style="font-size:13px;">
			<thead class="grid-heading-row"><tr>
				<th>${__('Customer Name')}</th>
				<th>${__('Tax ID (VOEN)')}</th>
				<th>${__('IBAN')}</th>
				<th>${__('Status')}</th>
				<th>${__('Mapped To')}</th>
				<th>${__('Created')}</th>
			</tr></thead><tbody>`;
		customers.forEach(c => {
			const pill = c.status === 'Mapped' ? 'green' : 'red';
			const mapped_to = c.mapped_customer ? `<a href="/app/customer/${c.mapped_customer}">${c.mapped_customer}</a>` : '-';
			const created = c.creation ? frappe.datetime.str_to_user(c.creation) : '-';
			html += `<tr>
				<td><a href="/app/kapital-bank-customer/${c.name}">${c.customer_name}</a></td>
				<td>${c.tax_id || '-'}</td>
				<td>${c.iban || '-'}</td>
				<td><span class="indicator-pill ${pill}">${__(c.status)}</span></td>
				<td>${mapped_to}</td>
				<td>${created}</td>
			</tr>`;
		});
		html += '</tbody></table>';
		if (total_count > customers.length) {
			html += `<p class="text-muted small">${__('Showing {0} of {1}', [customers.length, total_count])} — <a href="/app/kapital-bank-customer">${__('View All')}</a></p>`;
		}
	} else {
		html += empty_state(__('No customers registered yet.'));
	}

	$('#kb-customers-container').html(html);
	$('#kb-refresh-customers').on('click', () => {
		$('#kb-customers-container').html(loading_html());
		load_customers_tab();
	});
}

// ─── Suppliers tab ───────────────────────────────────────────────────────────

function load_suppliers_tab() {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_list',
		args: { data_type: 'suppliers', limit: 100, offset: 0 },
		callback(r) {
			if (r.message && r.message.success) {
				render_suppliers_list(r.message.data, r.message.total_count);
			} else {
				const msg = r.message ? r.message.message : __('Unknown error');
				$('#kb-suppliers-container').html(error_html(msg, load_suppliers_tab));
			}
		},
		error() { $('#kb-suppliers-container').html(error_html(__('Network error'), load_suppliers_tab)); }
	});
}

function render_suppliers_list(suppliers, total_count) {
	let html = list_header(__('Suppliers'), total_count, 'kb-refresh-suppliers');

	if (suppliers && suppliers.length > 0) {
		html += `<table class="table table-bordered" style="font-size:13px;">
			<thead class="grid-heading-row"><tr>
				<th>${__('Supplier Name')}</th>
				<th>${__('Tax ID (VOEN)')}</th>
				<th>${__('IBAN')}</th>
				<th>${__('Status')}</th>
				<th>${__('Mapped To')}</th>
				<th>${__('Created')}</th>
			</tr></thead><tbody>`;
		suppliers.forEach(s => {
			const pill = s.status === 'Mapped' ? 'green' : 'red';
			const mapped_to = s.mapped_supplier ? `<a href="/app/supplier/${s.mapped_supplier}">${s.mapped_supplier}</a>` : '-';
			const created = s.creation ? frappe.datetime.str_to_user(s.creation) : '-';
			html += `<tr>
				<td><a href="/app/kapital-bank-supplier/${s.name}">${s.supplier_name}</a></td>
				<td>${s.tax_id || '-'}</td>
				<td>${s.iban || '-'}</td>
				<td><span class="indicator-pill ${pill}">${__(s.status)}</span></td>
				<td>${mapped_to}</td>
				<td>${created}</td>
			</tr>`;
		});
		html += '</tbody></table>';
		if (total_count > suppliers.length) {
			html += `<p class="text-muted small">${__('Showing {0} of {1}', [suppliers.length, total_count])} — <a href="/app/kapital-bank-supplier">${__('View All')}</a></p>`;
		}
	} else {
		html += empty_state(__('No suppliers registered yet.'));
	}

	$('#kb-suppliers-container').html(html);
	$('#kb-refresh-suppliers').on('click', () => {
		$('#kb-suppliers-container').html(loading_html());
		load_suppliers_tab();
	});
}

// ─── Purposes tab ────────────────────────────────────────────────────────────

function load_purposes_tab() {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_list',
		args: { data_type: 'purposes', limit: 100, offset: 0 },
		callback(r) {
			if (r.message && r.message.success) {
				render_purposes_list(r.message.data, r.message.total_count);
			} else {
				const msg = r.message ? r.message.message : __('Unknown error');
				$('#kb-purposes-container').html(error_html(msg, load_purposes_tab));
			}
		},
		error() { $('#kb-purposes-container').html(error_html(__('Network error'), load_purposes_tab)); }
	});
}

function render_purposes_list(purposes, total_count) {
	let html = list_header(__('Purposes'), total_count, 'kb-refresh-purposes');

	if (purposes && purposes.length > 0) {
		html += `<table class="table table-bordered" style="font-size:13px;">
			<thead class="grid-heading-row"><tr>
				<th>${__('Purpose Keyword')}</th>
				<th>${__('Direction')}</th>
				<th>${__('Status')}</th>
			</tr></thead><tbody>`;
		purposes.forEach(p => {
			const pill = p.status === 'Mapped' ? 'green' : 'red';
			html += `<tr>
				<td><a href="/app/kapital-bank-purpose/${encodeURIComponent(p.name)}">${p.purpose_keyword}</a></td>
				<td>${__(p.direction || '-')}</td>
				<td><span class="indicator-pill ${pill}">${__(p.status)}</span></td>
			</tr>`;
		});
		html += '</tbody></table>';
		if (total_count > purposes.length) {
			html += `<p class="text-muted small">${__('Showing {0} of {1}', [purposes.length, total_count])} — <a href="/app/kapital-bank-purpose">${__('View All')}</a></p>`;
		}
	} else {
		html += empty_state(__('No purposes registered yet. Use "Load Data" to extract purposes from statements.'));
	}

	$('#kb-purposes-container').html(html);
	$('#kb-refresh-purposes').on('click', () => {
		$('#kb-purposes-container').html(loading_html());
		load_purposes_tab();
	});
}

// ═══════════════════════════════════════════════════════════════════════════════
// BULK EDIT
// ═══════════════════════════════════════════════════════════════════════════════

function bulk_edit_table(frm, table_field) {
	const selected_rows = frm.fields_dict[table_field].grid.get_selected_children();

	if (selected_rows.length === 0) {
		frappe.msgprint(__("No rows selected. Please select rows to edit."));
		return;
	}

	const child_doctype = selected_rows[0].doctype;
	const meta = frappe.get_meta(child_doctype);

	const field_options = [];
	const field_map = {};

	meta.fields.forEach(df => {
		if (!['Section Break', 'Column Break', 'Tab Break', 'HTML', 'Table', 'Button'].includes(df.fieldtype)
			&& !df.read_only && !df.hidden) {
			field_options.push({
				label: __(df.label || frappe.model.unscrub(df.fieldname)),
				value: df.fieldname
			});
			field_map[df.fieldname] = df;
		}
	});

	const d = new frappe.ui.Dialog({
		title: __("Bulk Edit Selected Rows"),
		fields: [
			{
				label: __("Field to Edit"),
				fieldname: "field_to_edit",
				fieldtype: "Select",
				options: field_options,
				reqd: 1
			},
			{
				fieldname: "value_section",
				fieldtype: "Section Break",
				label: __("New Value"),
				collapsible: 0,
				hidden: 1
			},
			{
				fieldname: "value_container",
				fieldtype: "HTML",
				options: '<div id="value_field_container"></div>'
			}
		],
		primary_action_label: __("Apply"),
		primary_action() {
			const field_name = d.get_value("field_to_edit");
			const field_def = field_map[field_name];

			if (!field_name || !d.new_value_field) {
				frappe.msgprint(__("Please select a field and enter a value."));
				return;
			}

			const new_value = d.new_value_field.get_value();

			if (new_value === undefined || new_value === null || new_value === "") {
				frappe.msgprint(__("Please enter a new value."));
				return;
			}

			// For Dynamic Link, also set the type field
			const is_dynamic = field_def && field_def.fieldtype === "Dynamic Link";
			const type_field = is_dynamic ? field_def.options : null;
			const type_value = is_dynamic && d.dynamic_link_type_field
				? d.dynamic_link_type_field.get_value() : null;

			if (is_dynamic && !type_value) {
				frappe.msgprint(__("Please select a type."));
				return;
			}

			let count = 0;
			const promises = [];

			selected_rows.forEach(row => {
				if (is_dynamic && type_field) {
					promises.push(
						frappe.model.set_value(row.doctype, row.name, type_field, type_value)
					);
				}
				promises.push(
					frappe.model.set_value(row.doctype, row.name, field_name, new_value)
						.then(() => { count++; })
				);
			});

			Promise.all(promises).then(() => {
				frm.refresh_field(table_field);
				frappe.show_alert({
					message: __("Updated {0} rows", [count]),
					indicator: 'green'
				}, 5);
				d.hide();
			});
		}
	});

	function clear_value_controls() {
		if (d.new_value_field) {
			d.new_value_field.$wrapper.remove();
			delete d.new_value_field;
		}
		if (d.dynamic_link_type_field) {
			d.dynamic_link_type_field.$wrapper.remove();
			delete d.dynamic_link_type_field;
		}
	}

	function make_value_control(field_def, container) {
		d.new_value_field = frappe.ui.form.make_control({
			df: {
				label: __("New Value for {0}", [__(field_def.label || frappe.model.unscrub(field_def.fieldname))]),
				fieldname: "new_value",
				fieldtype: field_def.fieldtype === "Dynamic Link" ? "Link" : field_def.fieldtype,
				options: field_def.options || "",
				reqd: 1
			},
			parent: container,
			render_input: true
		});
		d.new_value_field.refresh();
	}

	d.fields_dict.field_to_edit.$input.on('change', function() {
		const field_name = d.get_value("field_to_edit");
		const field_def = field_map[field_name];

		if (!field_def) return;

		d.set_df_property("value_section", "hidden", 0);
		clear_value_controls();

		const value_container = d.fields_dict.value_container.$wrapper.find("#value_field_container");

		if (field_def.fieldtype === "Dynamic Link") {
			// Find the linked Select field (e.g. counterparty_type for counterparty)
			const type_df = field_map[field_def.options];
			if (type_df) {
				d.dynamic_link_type_field = frappe.ui.form.make_control({
					df: {
						label: __(type_df.label || frappe.model.unscrub(type_df.fieldname)),
						fieldname: "dynamic_link_type",
						fieldtype: type_df.fieldtype,
						options: type_df.options || "",
						reqd: 1
					},
					parent: value_container,
					render_input: true
				});
				d.dynamic_link_type_field.refresh();

				d.dynamic_link_type_field.$input.on('change', () => {
					const selected_type = d.dynamic_link_type_field.get_value();
					if (d.new_value_field) {
						d.new_value_field.$wrapper.remove();
						delete d.new_value_field;
					}
					if (selected_type) {
						d.new_value_field = frappe.ui.form.make_control({
							df: {
								label: __("New Value for {0}", [__(field_def.label || frappe.model.unscrub(field_def.fieldname))]),
								fieldname: "new_value",
								fieldtype: "Link",
								options: selected_type,
								reqd: 1
							},
							parent: value_container,
							render_input: true
						});
						d.new_value_field.refresh();
					}
				});
			} else {
				make_value_control(field_def, value_container);
			}
		} else {
			make_value_control(field_def, value_container);
		}
	});

	d.show();
}

// ═══════════════════════════════════════════════════════════════════════════════
// HELPERS
// ═══════════════════════════════════════════════════════════════════════════════

function fmt_num(val) {
	if (val === undefined || val === null || val === '') return '-';
	const n = parseFloat(val);
	if (isNaN(n)) return val;
	return format_number(n, null, 2);
}

function loading_html() {
	return `<div class="text-center text-muted" style="padding:20px;"><i class="fa fa-spinner fa-spin"></i> ${__('Loading...')}</div>`;
}

function empty_state(msg) {
	return `<div class="text-center text-muted" style="padding:30px;"><p>${msg}</p></div>`;
}

function error_html(msg, retry_fn) {
	return `<div class="alert alert-warning">
		<p>${__('Error loading data')}: ${msg}</p>
		<button class="btn btn-sm btn-default kb-retry-btn">${__('Try Again')}</button>
	</div>`;
}

function list_header(label, total_count, refresh_id) {
	return `<div class="clearfix" style="margin-bottom:10px;">
		<div class="pull-left"><h6 class="text-muted">${label} (${total_count} ${__('total')})</h6></div>
		<div class="pull-right">
			<button class="btn btn-xs btn-default" id="${refresh_id}">
				<i class="octicon octicon-sync"></i> ${__('Refresh')}
			</button>
		</div>
	</div>`;
}

// ═══════════════════════════════════════════════════════════════════════════════
// WORKFLOW WIZARD — compact bar at the top of the Kapital Bank Settings form.
// Mirrors the Bank Integration Profile wizard, adapted to KB's API-driven flow:
// connect → fetch from the bank → map accounts/cards & counterparties → rules →
// import → reconcile. Shows the CURRENT step; clicking expands the full list.
// ═══════════════════════════════════════════════════════════════════════════════

function _kb_inject_wizard_styles() {
	if (document.getElementById('kb-wizard-styles')) return;
	const css = `
		.kb-wizard { margin: 0 0 12px; border: 1px solid var(--border-color, #e2e6e9);
			border-radius: 8px; background: var(--card-bg, #fff); overflow: hidden; }
		.kb-wizard-bar { display: flex; align-items: center; gap: 9px; padding: 9px 12px;
			cursor: pointer; user-select: none; }
		.kb-wizard-bar:hover { background: var(--bg-light-gray, #f4f5f6); }
		.kb-wizard-dot { width: 9px; height: 9px; border-radius: 50%;
			background: var(--blue-500, #2490ef); flex: 0 0 auto; }
		.kb-wizard-cur { flex: 1 1 auto; }
		.kb-wizard-cur b { margin-right: 4px; }
		.kb-wizard-toggle { font-size: 12px; color: var(--text-muted); white-space: nowrap;
			display: inline-flex; align-items: center; gap: 4px; }
		.kb-wizard-chev { display: inline-block;
			transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
		.kb-wizard.open .kb-wizard-chev { transform: rotate(180deg); }
		.kb-wizard-list { max-height: 0; overflow: hidden;
			padding: 0 6px; border-top: 0 solid var(--border-color, #eef0f2);
			transition: max-height 0.45s ease-in-out, padding 0.45s ease-in-out,
				border-width 0.45s ease-in-out; }
		.kb-wizard.open .kb-wizard-list { max-height: 640px; padding: 6px;
			border-top-width: 1px; }
		.kb-wizard-step { display: flex; align-items: flex-start; gap: 10px;
			padding: 8px; border-radius: 6px; }
		.kb-wizard-step-main { display: flex; align-items: flex-start; gap: 10px;
			flex: 1 1 auto; cursor: pointer; min-width: 0; }
		.kb-wizard-step:hover { background: var(--bg-light-gray, #f4f5f6); }
		.kb-wizard-step.cur { background: var(--highlight-color, #f0f4ff); }
		.kb-wizard-step.done { opacity: 0.65; }
		.kb-wizard-step.skipped { opacity: 0.5; }
		.kb-wizard-badge { flex: 0 0 22px; width: 22px; height: 22px; border-radius: 50%;
			display: inline-flex; align-items: center; justify-content: center;
			font-weight: 600; font-size: 12px; margin-top: 1px;
			background: var(--control-bg, #f4f5f6); }
		.kb-wizard-step.done .kb-wizard-badge { background: var(--green-100, #d4f3e0);
			color: var(--green-600, #1f9d55); }
		.kb-wizard-step.cur .kb-wizard-badge { background: var(--blue-500, #2490ef);
			color: #fff; }
		.kb-wizard-step-title { font-weight: 600; }
		.kb-wizard-step-hint { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
		.kb-wizard-tag { font-size: 11px; font-weight: 600; margin-left: 6px; }
		.kb-wizard-tag.cur { color: var(--blue-600, #1373cc); }
		.kb-wizard-tag.skip { color: var(--text-muted); }
		.kb-wizard-skip { flex: 0 0 auto; font-size: 11px; color: var(--text-muted);
			cursor: pointer; white-space: nowrap; padding: 2px 4px; align-self: center; }
		.kb-wizard-skip:hover { color: var(--text-color, #1f272e); text-decoration: underline; }`;
	const style = document.createElement('style');
	style.id = 'kb-wizard-styles';
	style.textContent = css;
	document.head.appendChild(style);
}

// Skip state is per-user (localStorage). Single doctype, so a fixed key.
function _kb_skip_key() { return 'kb_wizard_skipped::Kapital Bank Settings'; }
function _kb_get_skipped() {
	try { return JSON.parse(localStorage.getItem(_kb_skip_key()) || '[]'); }
	catch (e) { return []; }
}
function _kb_set_skipped(arr) {
	try { localStorage.setItem(_kb_skip_key(), JSON.stringify(arr)); } catch (e) { /* ignore */ }
}

// Focus a field that may live inside a custom_subtabs subtab. scroll_to_field only
// activates the parent tab and leaves the subtab content hidden, so for subtab
// fields we click the subtab button (its handler reveals the content).
function _kb_focus_field(frm, fieldname) {
	const wrapper = (frm.layout && frm.layout.wrapper) || frm.$wrapper;
	const field = frm.get_field(fieldname);
	const $pane = field && field.$wrapper ? field.$wrapper.closest('.tab-pane') : $();
	const paneId = $pane.attr('id');
	if (paneId) {
		const $btn = wrapper.find(
			`.sub-tab button.nav-link[data-target-id="${paneId}"], ` +
			`.sub-tab a.nav-link[data-target-id="${paneId}"]`
		);
		if ($btn.length) {
			$btn.first().trigger('click');
			setTimeout(() => {
				if (field.$wrapper && field.$wrapper[0]) {
					field.$wrapper[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
				}
			}, 80);
			return;
		}
	}
	frm.scroll_to_field(fieldname);
}

function _kb_render_form_wizard(frm, keepOpen) {
	frappe.call({
		method: 'kapital_bank.bank_api.get_kb_reference_data_summary',
		callback(r) {
			const s = (r.message && r.message.summary) || {};
			const g = (k) => s[k] || { total: 0, mapped: 0 };
			const acc = g('accounts'), card = g('cards');
			const cust = g('customers'), sup = g('suppliers'), pur = g('purposes');

			const registryTotal = acc.total + card.total + cust.total + sup.total + pur.total;
			const acctCardTotal = acc.total + card.total;
			const acctCardMapped = acc.mapped + card.mapped;
			const partyTotal = cust.total + sup.total;
			const partyMapped = cust.mapped + sup.mapped;

			const hasLogin = !!frm.doc.default_login;
			const hasData = registryTotal > 0;
			const acctCardDone = acctCardTotal > 0 && acctCardMapped === acctCardTotal;
			const partyDone = partyTotal > 0 && partyMapped === partyTotal;
			const hasTxnRules = (frm.doc.transaction_mappings || []).length > 0;

			const skipped = _kb_get_skipped();

			// Steps 6-7 live on other doctypes — always navigation, not skippable.
			const steps = [
				{
					key: 'connect', done: hasLogin,
					title: __('Connect Kapital Bank'),
					hint: __('Set the default login and company defaults used to reach the bank API.'),
					action: () => _kb_focus_field(frm, 'default_login'),
				},
				{
					key: 'load', done: hasData,
					title: __('Load data from the bank'),
					hint: __('Fetch accounts, cards, counterparties and purposes from the Kapital Bank API.'),
					action: () => show_load_data_dialog(frm),
				},
				{
					key: 'mapacc', done: acctCardDone,
					title: __('Map accounts & cards'),
					hint: __('Link Kapital Bank accounts and cards to ERP Bank Accounts (Accounts / Cards menus above).'),
					action: () => _kb_focus_field(frm, 'account_mappings'),
				},
				{
					key: 'mapparty', done: partyDone,
					title: __('Map counterparties'),
					hint: __('Match or create customers and suppliers (Customers / Suppliers menus above).'),
					action: () => _kb_focus_field(frm, 'customer_mappings'),
				},
				{
					key: 'rules', done: hasTxnRules,
					title: __('Configure transaction rules'),
					hint: __('Define how purposes map to Payment Entries / Journal Entries.'),
					action: () => _kb_focus_field(frm, 'transaction_mappings'),
				},
				{
					key: 'import', off: true,
					title: __('Import transactions'),
					hint: __('In the Bank Transaction list: Bank Integrations → Import Bank Statement.'),
					action: () => frappe.set_route('List', 'Bank Transaction'),
				},
				{
					key: 'reconcile', off: true,
					title: __('Create documents & reconcile'),
					hint: __('In the Bank Reconciliation Tool: pick the account and Create & Reconcile.'),
					action: () => frappe.set_route('Form', 'Bank Reconciliation Tool'),
				},
			];
			steps.forEach((st) => { st.skipped = !st.off && skipped.indexOf(st.key) !== -1; });

			let currentIdx = steps.findIndex((st) => !st.off && !st.done && !st.skipped);
			if (currentIdx === -1) currentIdx = 5; // all on-form steps done/skipped → "Import"
			const cur = steps[currentIdx];

			const esc = frappe.utils.escape_html;
			const rows = steps.map((st, i) => {
				const isCur = i === currentIdx;
				let badge, cls, tag;
				if (st.skipped) {
					badge = '–'; cls = 'skipped';
					tag = ` <span class="kb-wizard-tag skip">${__('Skipped')}</span>`;
				} else if (st.done) {
					badge = '✓'; cls = 'done'; tag = '';
				} else if (isCur) {
					badge = '➜'; cls = 'cur';
					tag = ` <span class="kb-wizard-tag cur">${__('Current step')}</span>`;
				} else {
					badge = (i + 1); cls = 'todo'; tag = '';
				}

				const skipCtl = st.off ? '' :
					`<span class="kb-wizard-skip" data-kb-skip="${st.key}">${
						st.skipped ? __('Unskip') : __('Skip')}</span>`;

				return `
					<div class="kb-wizard-step ${cls}">
						<div class="kb-wizard-step-main" data-kb-step="${i}">
							<span class="kb-wizard-badge">${badge}</span>
							<div class="kb-wizard-step-body">
								<div class="kb-wizard-step-title">${esc(st.title)}${tag}</div>
								<div class="kb-wizard-step-hint">${esc(st.hint)}</div>
							</div>
						</div>
						${skipCtl}
					</div>`;
			}).join('');

			const html = `
				<div class="kb-wizard${keepOpen ? ' open' : ''}">
					<div class="kb-wizard-bar">
						<span class="kb-wizard-dot"></span>
						<span class="kb-wizard-cur"><b>${__('Kapital Bank')}</b> · ${esc(cur.title)}</span>
						<span class="kb-wizard-toggle">${__('Steps')}<span class="kb-wizard-chev">▾</span></span>
					</div>
					<div class="kb-wizard-list">${rows}</div>
				</div>`;

			_kb_inject_wizard_styles();

			const $host = frm.$wrapper.find('.form-layout').first();
			frm.$wrapper.find('.kb-wizard').remove();
			const $w = $(html);
			$host.prepend($w);

			$w.find('.kb-wizard-bar').on('click', () => $w.toggleClass('open'));
			$w.find('.kb-wizard-step-main').on('click', function () {
				steps[$(this).data('kb-step')].action();
			});
			$w.find('.kb-wizard-skip').on('click', function (e) {
				e.stopPropagation();
				const key = $(this).data('kb-skip');
				const set = _kb_get_skipped();
				const idx = set.indexOf(key);
				if (idx === -1) set.push(key); else set.splice(idx, 1);
				_kb_set_skipped(set);
				_kb_render_form_wizard(frm, /* keepOpen */ true);
			});
		},
	});
}
