import Dataset from '#models/dataset';
import { Client } from '@opensearch-project/opensearch';
import { create } from 'xmlbuilder2';
import SaxonJS from 'saxon-js';
import XmlModel from '#app/Library/XmlModel';
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces.js';
import logger from '@adonisjs/core/services/logger';
import { readFileSync } from 'fs';
import { DateTime } from 'luxon';
// import Config from '@ioc:Adonis/Core/Config';
import { getDomain } from '#app/utils/utility-functions';

// const opensearchNode = process.env.OPENSEARCH_HOST || 'localhost';
// const client = new Client({ node: `http://${opensearchNode}` }); // replace with your OpenSearch endpoint
interface XslTParameter {
    [key: string]: any;
}
export default {
    // opensearchNode: process.env.OPENSEARCH_HOST || 'localhost',
    client: new Client({ node: `http://${process.env.OPENSEARCH_HOST || 'localhost'}` }), // replace with your OpenSearch endpoint

    async getDoiRegisterString(dataset: Dataset): Promise<string | undefined> {
        try {
            const proc = readFileSync('public/assets2/doi_datacite.sef.json');
            const xsltParameter: XslTParameter = {};
            let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
            const datasetNode = xml.root().ele('Dataset');
            await createXmlRecord(dataset, datasetNode);
            const xmlString = xml.end({ prettyPrint: false });

            // set timestamp
            const date = DateTime.now();
            const unixTimestamp = date.toUnixInteger();
            xsltParameter['unixTimestamp'] = unixTimestamp;

            // set prefix
            let prefix = '';
            // let base_domain = '';
            // const datacite_environment = process.env.DATACITE_ENVIRONMENT || 'debug';
            // if (datacite_environment === 'debug') {
            //     prefix = process.env.DATACITE_TEST_PREFIX || '';
            //     base_domain = process.env.TEST_BASE_DOMAIN || '';
            // } else if (datacite_environment === 'production') {
            //     prefix = process.env.DATACITE_PREFIX || '';
            //     base_domain = process.env.BASE_DOMAIN || '';
            // }
            prefix = process.env.DATACITE_PREFIX || '';
            xsltParameter['prefix'] = prefix;

            const repIdentifier = 'tethys';
            xsltParameter['repIdentifier'] = repIdentifier;

            let xmlOutput; // = xmlString;
            try {
                const result = await SaxonJS.transform({
                    // stylesheetFileName: `${config.TMP_BASE_DIR}/data-quality/rules/iati.sef.json`,
                    stylesheetText: proc,
                    destination: 'serialized',
                    // sourceFileName: sourceFile,
                    sourceText: xmlString,
                    stylesheetParams: xsltParameter,
                    // logLevel: 10,
                });
                xmlOutput = result.principalResult;
            } catch (error) {
                logger.error('An error occurred while creating the user', error.message);
            }

            return xmlOutput;
        } catch (error) {
            logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
        }
    },

    async indexDocument(dataset: Dataset, index_name: string): Promise<void> {
        try {
            const proc = readFileSync('public/assets2/solr.sef.json');
            const doc: string = await this.getTransformedString(dataset, proc);

            let document = JSON.parse(doc);
            await this.client.index({
                id: dataset.publish_id?.toString(),
                index: index_name,
                body: document,
                refresh: true,
            });
            logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
        } catch (error) {
            logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
        }
    },

    async getTransformedString(dataset: Dataset, proc: Buffer): Promise<string> {
        let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
        const datasetNode = xml.root().ele('Dataset');
        await createXmlRecord(dataset, datasetNode);
        const xmlString = xml.end({ prettyPrint: false });

        try {
            const result = await SaxonJS.transform({
                stylesheetText: proc,
                destination: 'serialized',
                sourceText: xmlString,
            });
            return result.principalResult;
        } catch (error) {
            logger.error(`An error occurred while creating the user, error: ${error.message},`);
            return '';
        }
    },
};
/**
 * Return the default global focus trap stack
 *
 * @return {import('focus-trap').FocusTrap[]}
 */

// export const indexDocument = async (dataset: Dataset, index_name: string, proc: Buffer): Promise<void> => {
//     try {
//         const doc = await getJsonString(dataset, proc);

//         let document = JSON.parse(doc);
//         await client.index({
//             id: dataset.publish_id?.toString(),
//             index: index_name,
//             body: document,
//             refresh: true,
//         });
//         Logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
//     } catch (error) {
//         Logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
//     }
// };

// const getJsonString = async (dataset, proc): Promise<string> => {
//     let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
//     const datasetNode = xml.root().ele('Dataset');
//     await createXmlRecord(dataset, datasetNode);
//     const xmlString = xml.end({ prettyPrint: false });

//     try {
//         const result = await transform({
//             stylesheetText: proc,
//             destination: 'serialized',
//             sourceText: xmlString,
//         });
//         return result.principalResult;
//     } catch (error) {
//         Logger.error(`An error occurred while creating the user, error: ${error.message},`);
//         return '';
//     }
// };

const createXmlRecord = async (dataset: Dataset, datasetNode: XMLBuilder): Promise<void> => {
    const domNode = await getDatasetXmlDomNode(dataset);
    if (domNode) {
         // add frontdoor url and data-type
        dataset.publish_id && addLandingPageAttribute(domNode, dataset.publish_id.toString());
        addSpecInformation(domNode, 'data-type:' + dataset.type);
        if (dataset.collections) {
            for (const coll of dataset.collections) {
                const collRole = coll.collectionRole;
                addSpecInformation(domNode, collRole.oai_name + ':' + coll.number);
            }
        }

        datasetNode.import(domNode);
    }
};

const getDatasetXmlDomNode = async (dataset: Dataset): Promise<XMLBuilder | null> => {
    const xmlModel = new XmlModel(dataset);
    // xmlModel.setModel(dataset);
    xmlModel.excludeEmptyFields();
    xmlModel.caching = true;
    // const cache = dataset.xmlCache ? dataset.xmlCache : null;
    // dataset.load('xmlCache');
    await dataset.load('xmlCache');
    if (dataset.xmlCache) {
        xmlModel.xmlCache = dataset.xmlCache;
    }

    // return cache.getDomDocument();
    const domDocument: XMLBuilder | null = await xmlModel.getDomDocument();
    return domDocument;
};

const addLandingPageAttribute = (domNode: XMLBuilder, dataid: string) => {
    const baseDomain = process.env.OAI_BASE_DOMAIN || 'localhost';
    const url = 'https://' + getDomain(baseDomain) + '/dataset/' + dataid;
    // add attribute du dataset xml element
    domNode.att('landingpage', url);
};

const addSpecInformation= (domNode: XMLBuilder, information: string) => {
    domNode.ele('SetSpec').att('Value', information);
};