// taxes_az/public/js/xml_mapping/xml_generator.js

frappe.provide("taxes_az.xml_mapping");

taxes_az.xml_mapping.XMLGenerator = class XMLGenerator {
    constructor(frm) {
        this.frm = frm;
    }
    
    // Генерация XML на основе данных DocType и правил маппинга
    async generateXML(doctypeName, docname) {
        try {
            // Загружаем данные DocType
            const docData = await this._loadDocTypeData(doctypeName, docname);
            
            // Загружаем правила маппинга
            const mappingRules = JSON.parse(this.frm.doc.mapping_data || '{}');
            
            // Загружаем шаблон XML
            const xmlTemplate = this.frm.doc.xml_sample_file;
            
            // Создаем DOM из шаблона XML
            const parser = new DOMParser();
            const xmlDoc = parser.parseFromString(xmlTemplate, "text/xml");
            
            // Применяем правила маппинга
            for (const xmlPath in mappingRules) {
                const doctypeField = mappingRules[xmlPath];
                const value = docData[doctypeField];
                
                if (value !== undefined) {
                    this._setXMLValueByPath(xmlDoc, xmlPath, value);
                }
            }
            
            // Преобразуем DOM обратно в строку XML
            const serializer = new XMLSerializer();
            const xmlString = serializer.serializeToString(xmlDoc);
            
            return xmlString;
        } catch (error) {
            frappe.throw(`Error generating XML: ${error.message}`);
            return null;
        }
    }
    
    // Загрузка данных DocType
    async _loadDocTypeData(doctypeName, docname) {
        return new Promise((resolve, reject) => {
            frappe.call({
                method: 'frappe.client.get',
                args: {
                    doctype: doctypeName,
                    name: docname
                },
                callback: (response) => {
                    if (response.message) {
                        resolve(response.message);
                    } else {
                        reject(new Error('Failed to load document data'));
                    }
                }
            });
        });
    }
    
    // Установка значения в XML по пути
    _setXMLValueByPath(xmlDoc, path, value) {
        try {
            // Проверяем, является ли путь атрибутом
            if (path.includes('@')) {
                const [elementPath, attrName] = path.split('@');
                const elementPathParts = elementPath.split('/').filter(p => p);
                
                // Получаем элемент
                let element = xmlDoc.documentElement;
                for (const part of elementPathParts) {
                    if (part !== element.nodeName) {
                        const elements = element.getElementsByTagName(part);
                        if (elements.length === 0) {
                            throw new Error(`Element ${part} not found in path ${path}`);
                        }
                        element = elements[0];
                    }
                }
                
                // Устанавливаем атрибут
                element.setAttribute(attrName, value);
            } else {
                // Путь к элементу
                const pathParts = path.split('/').filter(p => p);
                
                // Получаем элемент
                let element = xmlDoc.documentElement;
                for (let i = 0; i < pathParts.length; i++) {
                    const part = pathParts[i];
                    
                    if (i === pathParts.length - 1) {
                        // Последний элемент в пути - целевой элемент
                        const elements = element.getElementsByTagName(part);
                        if (elements.length) {
                            elements[0].textContent = value;
                        }
                    } else if (part !== element.nodeName) {
                        const elements = element.getElementsByTagName(part);
                        if (elements.length === 0) {
                            throw new Error(`Element ${part} not found in path ${path}`);
                        }
                        element = elements[0];
                    }
                }
            }
        } catch (error) {
            console.error(`Error setting value for path ${path}:`, error);
        }
    }
};