import frappe
import json
import re
import difflib
from frappe.utils import now, cstr, cint, flt, get_datetime
from frappe.model.document import Document

class ETaxesSettings(Document):
    def validate(self):
        self.validate_vat_account_mappings()

    def on_update(self):
        self._sync_registry_statuses()

    def _sync_registry_statuses(self):
        """Reset registry record statuses when their rows are removed from mapping tables."""
        self._reset_orphaned(
            mapped_names={row.etaxes_customer_name for row in self.customer_mappings if row.etaxes_customer_name},
            doctype="E-Taxes Customers",
            name_field="etaxes_party_name",
            reset_fields={"status": "New", "mapped_customer": None,
                          "customer_group": None, "territory": None, "payment_terms": None},
        )
        self._reset_orphaned(
            mapped_names={row.etaxes_supplier_name for row in self.supplier_mappings if row.etaxes_supplier_name},
            doctype="E-Taxes Suppliers",
            name_field="etaxes_party_name",
            reset_fields={"status": "New", "mapped_supplier": None,
                          "supplier_group": None, "payment_terms": None},
        )
        self._reset_orphaned(
            mapped_names={row.etaxes_item_name for row in self.item_mappings if row.etaxes_item_name},
            doctype="E-Taxes Item",
            name_field="etaxes_item_name",
            reset_fields={"status": "New", "mapped_item": None,
                          "item_group": None, "uom": None, "item_tax_template": None},
        )
        self._reset_orphaned(
            mapped_names={row.etaxes_unit_name for row in self.unit_mappings if row.etaxes_unit_name},
            doctype="E-Taxes Unit",
            name_field="etaxes_unit_name",
            reset_fields={"status": "New", "mapped_unit": None},
        )

    def _reset_orphaned(self, mapped_names, doctype, name_field, reset_fields):
        orphaned = frappe.get_all(doctype, filters={"status": "Mapped"}, fields=["name", name_field])
        for record in orphaned:
            if record.get(name_field) not in mapped_names:
                frappe.db.set_value(doctype, record.name, reset_fields, update_modified=False)

    def validate_vat_account_mappings(self):
        """
        Проверка уникальности комбинаций operation_type + expense_income + classification_code
        в таблице VAT Account Mappings
        """
        if not self.vat_account_mappings:
            return

        seen_combinations = set()

        for idx, mapping in enumerate(self.vat_account_mappings, start=1):
            # Нормализуем classification_code (None и пустая строка считаются одинаковыми)
            operation_type = mapping.operation_type
            expense_income = mapping.expense_income
            classification_code = mapping.classification_code or None

            # Создаем ключ для проверки уникальности (operation_type + expense_income + classification_code)
            combination_key = (operation_type, expense_income, classification_code)

            if combination_key in seen_combinations:
                # Формируем понятное сообщение об ошибке
                if classification_code:
                    frappe.throw(
                        f'Row #{idx}: Duplicate mapping found. '
                        f'Operation Type "{operation_type}", Expense/Income "{expense_income}", '
                        f'Classification Code "{classification_code}" '
                        f'already exists in this settings. Each combination must be unique.'
                    )
                else:
                    frappe.throw(
                        f'Row #{idx}: Duplicate mapping found. '
                        f'Operation Type "{operation_type}", Expense/Income "{expense_income}" '
                        f'with empty Classification Code '
                        f'already exists in this settings. Each combination must be unique.'
                    )

            seen_combinations.add(combination_key)