import frappe
from frappe.model.document import Document


class KapitalBankSettings(Document):
	def on_update(self):
		# Keep the registry records in sync with the mapping child tables, both ways:
		#   * a row with a linked target (Bank Account / ERP party) -> registry
		#     record becomes Mapped (and inherits its attributes);
		#   * removing a row OR clearing that link flips the record back to New.
		self._sync_account_statuses()
		self._sync_customer_statuses()
		self._sync_supplier_statuses()
		self._sync_card_statuses()

	def _sync_account_statuses(self):
		"""Kapital Bank Account becomes Mapped when its mapping row links a Bank
		Account, and reverts to New when the row is removed or the link cleared."""
		mapped_ibans = set()
		for row in self.account_mappings:
			if not (row.iban and row.bank_account):
				continue
			mapped_ibans.add(row.iban)
			current = frappe.db.get_value(
				"Kapital Bank Account", row.iban, ["status", "bank_account"], as_dict=True
			)
			if not current:
				continue
			desired = {"status": "Mapped", "bank_account": row.bank_account}
			if any(current.get(k) != v for k, v in desired.items()):
				frappe.db.set_value("Kapital Bank Account", row.iban, desired, update_modified=False)

		orphaned = frappe.get_all(
			"Kapital Bank Account",
			filters={"status": "Mapped"},
			fields=["name"],
		)
		for account in orphaned:
			if account.name not in mapped_ibans:
				frappe.db.set_value(
					"Kapital Bank Account",
					account.name,
					{
						"status": "New",
						"bank_account": None,
					},
					update_modified=False,
				)

	def _sync_customer_statuses(self):
		"""Kapital Bank Customer becomes Mapped when its mapping row links an ERP
		Customer, and reverts to New when the row is removed or the link cleared."""
		mapped_names = set()
		for row in self.customer_mappings:
			if not (row.kb_customer_name and row.erp_customer):
				continue
			mapped_names.add(row.kb_customer_name)
			current = frappe.db.get_value(
				"Kapital Bank Customer", row.kb_customer_name,
				["status", "mapped_customer", "customer_group", "territory", "payment_terms"],
				as_dict=True,
			)
			if not current:
				continue
			desired = {
				"status": "Mapped",
				"mapped_customer": row.erp_customer,
				"customer_group": row.customer_group or None,
				"territory": row.territory or None,
				"payment_terms": row.payment_terms or None,
			}
			if any(current.get(k) != v for k, v in desired.items()):
				frappe.db.set_value(
					"Kapital Bank Customer", row.kb_customer_name, desired, update_modified=False
				)

		orphaned = frappe.get_all(
			"Kapital Bank Customer",
			filters={"status": "Mapped"},
			fields=["name", "customer_name"],
		)
		for customer in orphaned:
			if customer.name not in mapped_names:
				frappe.db.set_value(
					"Kapital Bank Customer",
					customer.name,
					{
						"status": "New",
						"mapped_customer": None,
						"customer_group": None,
						"territory": None,
						"payment_terms": None,
					},
					update_modified=False,
				)

	def _sync_supplier_statuses(self):
		"""Kapital Bank Supplier becomes Mapped when its mapping row links an ERP
		Supplier, and reverts to New when the row is removed or the link cleared."""
		mapped_names = set()
		for row in self.supplier_mappings:
			if not (row.kb_supplier_name and row.erp_supplier):
				continue
			mapped_names.add(row.kb_supplier_name)
			current = frappe.db.get_value(
				"Kapital Bank Supplier", row.kb_supplier_name,
				["status", "mapped_supplier", "supplier_group", "payment_terms"],
				as_dict=True,
			)
			if not current:
				continue
			desired = {
				"status": "Mapped",
				"mapped_supplier": row.erp_supplier,
				"supplier_group": row.supplier_group or None,
				"payment_terms": row.payment_terms or None,
			}
			if any(current.get(k) != v for k, v in desired.items()):
				frappe.db.set_value(
					"Kapital Bank Supplier", row.kb_supplier_name, desired, update_modified=False
				)

		orphaned = frappe.get_all(
			"Kapital Bank Supplier",
			filters={"status": "Mapped"},
			fields=["name", "supplier_name"],
		)
		for supplier in orphaned:
			if supplier.name not in mapped_names:
				frappe.db.set_value(
					"Kapital Bank Supplier",
					supplier.name,
					{
						"status": "New",
						"mapped_supplier": None,
						"supplier_group": None,
						"payment_terms": None,
					},
					update_modified=False,
				)

	def _sync_card_statuses(self):
		"""Kapital Bank Card becomes Mapped when its mapping row links a Bank
		Account, and reverts to New when the row is removed or the link cleared."""
		mapped_accounts = set()
		for row in self.card_mappings:
			if not (row.account_number and row.bank_account):
				continue
			mapped_accounts.add(row.account_number)
			current = frappe.db.get_value(
				"Kapital Bank Card", row.account_number, ["status", "bank_account"], as_dict=True
			)
			if not current:
				continue
			desired = {"status": "Mapped", "bank_account": row.bank_account}
			if any(current.get(k) != v for k, v in desired.items()):
				frappe.db.set_value(
					"Kapital Bank Card", row.account_number, desired, update_modified=False
				)

		orphaned = frappe.get_all(
			"Kapital Bank Card",
			filters={"status": "Mapped"},
			fields=["name", "account_number"],
		)
		for card in orphaned:
			if card.name not in mapped_accounts:
				frappe.db.set_value(
					"Kapital Bank Card",
					card.name,
					{
						"status": "New",
						"bank_account": None,
					},
					update_modified=False,
				)
