import { INodeType, INodeTypeDescription, INodeExecutionData, NodeConnectionType, IExecuteFunctions, IDataObject } from 'n8n-workflow';
import { XMLParser } from 'fast-xml-parser';

interface XmlData {
    body?: string;
    [key: string]: any;
}

export class _Xml2json implements INodeType {
    description: INodeTypeDescription = {
        displayName: 'Xml2json',
        name: 'xml2json',
        group: ['transform'],
        version: 1,
        description: 'Convert XML string in DATA.body to JSON',
        defaults: { name: 'Xml2json' },
        inputs: [NodeConnectionType.Main],
        outputs: [NodeConnectionType.Main],
        properties: [],
    };

    async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
        const items = this.getInputData();
        if (!items || items.length === 0) return [[]];

        const item = items[0];
        const data = (item.json.DATA as XmlData) || {};

        const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '' });

        try {
            let xmlStr = '';
            if (data.body && typeof data.body === 'string') {
                xmlStr = data.body;
                data.body = undefined;
            } else if (typeof data === 'string') {
                xmlStr = data;
            } else if (data) {
                xmlStr = JSON.stringify(data);
            }

            const xmlStart = xmlStr.indexOf('<?xml');
            if (xmlStart === -1) throw new Error('XML Document is not found');

            const xmlEnd = xmlStr.lastIndexOf('>') + 1;
            let xmlContent = xmlStr.substring(xmlStart, xmlEnd).replace(/\r/g, '').replace(/\n/g, '');

            const jsonObj = parser.parse(xmlContent);

            // Перезаписываем DATA
            item.json.DATA = { ...data, ...jsonObj };

            // Полная перезапись METADATA в стиле BaseNodeTransform
            const workflowName = this.getWorkflow().name;
            const nodeInfo = this.getNode();
            const fromNodeFull = nodeInfo.type;
            const fromNode = fromNodeFull.includes('.') ? fromNodeFull.split('.').pop()! : fromNodeFull;
            const idField = nodeInfo.name;

            item.json.METADATA = {
                chain: workflowName,
                from: fromNode,
                id: idField,
                time: Date.now(),
            };

        } catch (e) {
            throw new Error('Xml2json error: ' + (e as Error).message);
        }

        return this.prepareOutputData([item]);
    }
}
