#!/usr/bin/env node
// (C) 2021-2023 GoodData Corporation
const fs = require('fs');

const basePath = '../../fixtures/ComplexModel';
const filename = `${basePath}/upload_info.json`;

async function generateMainDate(dataset) {
    const datasetString = dataset.toString().padStart(2, '0');
    const columnName = `m${datasetString}.date01`;
    const populates = [`m${datasetString}date01.date.day.us.mm_dd_yyyy`];
    return {
        columnName,
        constraints: {
            date: 'MM/dd/yyyy'
        },
        mode: 'FULL',
        populates,
        referenceKey: 1
    };
}

async function generateSubDate(dataset, subDataset) {
    const datasetString = dataset.toString().padStart(2, '0');

    const subDatasetString = subDataset.toString().padStart(2, '0');
    const columnName = `m${datasetString}s${subDatasetString}.date01`;
    const populates = [
        `m${datasetString}s${subDatasetString}date01.date.day.us.mm_dd_yyyy`
    ];
    return {
        columnName,
        constraints: {
            date: 'MM/dd/yyyy'
        },
        mode: 'FULL',
        populates,
        referenceKey: 1
    };
}

async function generateMainFacts(dataset, factCount) {
    const part = [];
    const datasetString = dataset.toString().padStart(2, '0');
    for (let i = 1; i <= factCount; i += 1) {
        const j = i.toString().padStart(2, '0');
        const columnName = `m${datasetString}.fact${j}`;
        const populates = [`fact.m${datasetString}.m${datasetString}fact${j}`];
        part.push({
            columnName,
            mode: 'FULL',
            populates
        });
    }
    return part;
}

async function generateSubFacts(dataset, subDataset, factCount) {
    const part = [];
    const datasetString = dataset.toString().padStart(2, '0');

    const subDatasetString = subDataset.toString().padStart(2, '0');
    for (let i = 1; i <= factCount; i += 1) {
        const factString = i.toString().padStart(2, '0');
        const columnName = `m${datasetString}s${subDatasetString}.fact${factString}`;
        const populates = [
            `fact.m${datasetString}s${subDatasetString}.m${datasetString}s${subDatasetString}fact${factString}`
        ];
        part.push({
            columnName,
            mode: 'FULL',
            populates
        });
    }

    return part;
}

async function generateMainAttributesForLastDataset(
    dataset,
    subDatasetCount,
    attributeCount
) {
    const part = [];
    const datasetString = dataset.toString().padStart(2, '0');
    for (let i = 1; i <= attributeCount; i += 1) {
        if (i <= subDatasetCount + 1 && i !== 1) {
            // eslint-disable-next-line no-continue
            continue;
        } else {
            const attributeString = i.toString().padStart(2, '0');
            const columnName = `m${datasetString}.attr${attributeString}`;
            const populates = [
                `label.m${datasetString}.m${datasetString}attr${attributeString}`
            ];
            part.push({
                columnName,
                mode: 'FULL',
                populates,
                referenceKey: 1
            });
        }
    }
    for (let j = 1; j <= subDatasetCount; j += 1) {
        const subDatasetString = j.toString().padStart(2, '0');
        const columnName = `m${datasetString}s${subDatasetString}.attr01`;
        const populates = [
            `label.m${datasetString}s${subDatasetString}.m${datasetString}s${subDatasetString}attr01`
        ];
        part.push({
            columnName,
            mode: 'FULL',
            populates,
            referenceKey: 1
        });
    }
    return part;
}

async function generateMainAttributesForOtherDatasets(
    dataset,
    subDatasetCount,
    attributeCount
) {
    const part = [];
    let columnName;
    let populates;

    const datasetString = dataset.toString().padStart(2, '0');
    for (let i = 1; i <= attributeCount; i += 1) {
        const j = i.toString().padStart(2, '0');
        if (i === 1) {
            columnName = `m${datasetString}.attr${j}`;
            populates = [`label.m${datasetString}.m${datasetString}attr${j}`];
            part.push({
                columnName,
                mode: 'FULL',
                populates,
                referenceKey: 1
            });

            const nextDatasetString = (dataset + 1).toString().padStart(2, '0');
            columnName = `m${nextDatasetString}.attr${j}`;
            populates = [
                `label.m${nextDatasetString}.m${nextDatasetString}attr${j}`
            ];
            part.push({
                columnName,
                mode: 'FULL',
                populates,
                referenceKey: 1
            });
        } else if (i <= subDatasetCount + 2) {
            // eslint-disable-next-line no-continue
            continue;
        } else {
            columnName = `m${datasetString}.attr${j}`;
            populates = [`label.m${datasetString}.m${datasetString}attr${j}`];
            part.push({
                columnName,
                mode: 'FULL',
                populates,
                referenceKey: 1
            });
        }
    }
    for (let j = 1; j <= subDatasetCount; j += 1) {
        const subDatasetString = j.toString().padStart(2, '0');
        // eslint-disable-next-line no-shadow
        const columnName = `m${datasetString}s${subDatasetString}.attr01`;
        // eslint-disable-next-line no-shadow
        const populates = [
            `label.m${datasetString}s${subDatasetString}.m${datasetString}s${subDatasetString}attr01`
        ];
        part.push({
            columnName,
            mode: 'FULL',
            populates,
            referenceKey: 1
        });
    }
    return part;
}

async function generateSubAttributes(dataset, subDataset, attributeCount) {
    const part = [];
    let columnName;
    let populates;

    const datasetString = dataset.toString().padStart(2, '0');

    const subDatasetString = subDataset.toString().padStart(2, '0');
    for (let i = 1; i <= attributeCount; i += 1) {
        const attributeString = i.toString().padStart(2, '0');
        columnName = `m${datasetString}s${subDatasetString}.attr${attributeString}`;
        populates = [
            `label.m${datasetString}s${subDatasetString}.m${datasetString}s${subDatasetString}attr${attributeString}`
        ];
        part.push({
            columnName,
            mode: 'FULL',
            populates,
            referenceKey: 1
        });
    }
    return part;
}
// Create a helper function to generate the parts array for each dataSetSLIManifest
async function generatePartsArray(
    dataset,
    datasetCount,
    subDatasetCount,
    attributeCount,
    factCount
) {
    const parts = [];
    parts.push(await generateMainDate(dataset));
    parts.push(...(await generateMainFacts(dataset, factCount)));

    if (dataset === datasetCount) {
        parts.push(
            ...(await generateMainAttributesForLastDataset(
                datasetCount,
                subDatasetCount,
                attributeCount
            ))
        );
    } else {
        parts.push(
            ...(await generateMainAttributesForOtherDatasets(
                dataset,
                subDatasetCount,
                attributeCount
            ))
        );
    }
    return parts;
}

async function generateSubPartsArray(
    dataset,
    subDataset,
    attributeCount,
    factCount
) {
    const parts = [];
    parts.push(await generateSubDate(dataset, subDataset));
    parts.push(...(await generateSubFacts(dataset, subDataset, factCount)));
    parts.push(
        ...(await generateSubAttributes(dataset, subDataset, attributeCount))
    );

    return parts;
}

async function createUploadInfoFile(
    datasetCount,
    subDatasetCount,
    mainAttributeCount,
    subAttributeCount,
    mainFactCount,
    subFactCount
) {
    const dataSetSLIManifestList = [];
    // Generate dataSetSLIManifest for each dataset
    for (let i = 1; i <= datasetCount; i += 1) {
        const datasetString = i.toString().padStart(2, '0');
        const dataSetSLIManifest = {
            dataSet: `dataset.m${datasetString}`,
            file: `m${datasetString}.csv`,
            // eslint-disable-next-line no-await-in-loop
            parts: await generatePartsArray(
                i,
                datasetCount,
                subDatasetCount,
                mainAttributeCount,
                mainFactCount
            )
        };

        const manifestItem = {
            dataSetSLIManifest
        };

        dataSetSLIManifestList.push(manifestItem);

        for (let j = 1; j <= subDatasetCount; j += 1) {
            const subDatasetString = j.toString().padStart(2, '0');
            // eslint-disable-next-line no-shadow
            const dataSetSLIManifest = {
                dataSet: `dataset.m${datasetString}s${subDatasetString}`,
                file: `m${datasetString}s${subDatasetString}.csv`,
                // eslint-disable-next-line no-await-in-loop
                parts: await generateSubPartsArray(
                    i,
                    j,
                    subAttributeCount,
                    subFactCount
                )
            };

            const subManifestItem = {
                dataSetSLIManifest
            };

            dataSetSLIManifestList.push(subManifestItem);
        }
    }

    const json = {
        dataSetSLIManifestList
    };

    fs.writeFile(filename, JSON.stringify(json, null, 2), (err) => {
        if (err) {
            // eslint-disable-next-line no-console
            console.error('Error writing JSON file:', err);
        } else {
            // eslint-disable-next-line no-console
            console.log('JSON file has been successfully generated:', filename);
        }
    });
}

module.exports = {
    createUploadInfoFile
};
