import { DataTableBuilder } from '../../DataTableBuilder/DataTableBuilder.js';
import { SectionedDataHelper } from '../SectionedDataHelper/SectionedDataHelper.js';
import { TemplateBuilder } from '../TemplateBuilder.js';

class ParentChildDataBuilder extends TemplateBuilder {
    childColumns = [];
    childVariants = [];
    childData = [];
    joinFields = [];
    childFields = [];
    parentChildDatasets = [];
    dataTableBuilder;
    constructor(variant) {
        super(variant);
        this.childVariants = this.variant.childVariants || [];
    }
    getChildVariant(childId) {
        return this.childVariants.find((cv) => cv.id === childId);
    }
    /**
     * Exracts the relevant data from the child variant definition
     * to generate the child table
     *
     * @param {string} childId
     * @return { fields: components['schemas']['FieldDefinition'][], joinFields: string[], columns: string[], name: string }
     * @memberof ParentChildDataBuilder
     */
    getChildVariantDefinitionData(childId) {
        const childVariant = this.getChildVariant(childId);
        let fields = [];
        let joinFields = [];
        let columns = [];
        let name = 'Child report';
        if (childVariant && childVariant.specification) {
            fields = childVariant.specification.fields;
            joinFields = childVariant && childVariant.specification ? childVariant.joinFields : [];
            columns = fields.filter((f) => f.visible).map((f) => f.name);
            name = childVariant.name;
        }
        return {
            fields,
            joinFields,
            columns,
            name,
        };
    }
    /**
     * Maps the parent child rows.
     * Splits into sections that will become the parent table
     *
     * @return {*}  {GroupedParentChildDataset[]}
     * @memberof ParentChildDataBuilder
     */
    mergeParentChildAndGroup(parentData) {
        const groups = [];
        let pendingParents = [];
        parentData.forEach((parentRow) => {
            // Build a dataset for this parent
            const dataset = {
                parent: parentRow,
                children: [],
            };
            // Match against each child dataset
            this.childData.forEach((child) => {
                const { joinFields } = this.getChildVariantDefinitionData(child.id);
                const matchedChildren = [];
                // Compare join fields
                child.data.forEach((childRow) => {
                    const isMatch = joinFields.every((col) => {
                        return parentRow[col] === childRow[col];
                    });
                    if (isMatch)
                        matchedChildren.push(childRow);
                });
                if (matchedChildren.length) {
                    dataset.children.push({
                        id: child.id,
                        data: matchedChildren,
                    });
                }
            });
            // Always collect the parent
            pendingParents.push(dataset.parent);
            // If dataset has children → close the group
            if (dataset.children.length > 0) {
                groups.push({
                    parent: pendingParents,
                    children: dataset.children,
                });
                pendingParents = [];
            }
        });
        // If leftover parents exist, make a final group (empty children)
        if (pendingParents.length > 0) {
            groups.push({
                parent: pendingParents,
                children: [],
            });
        }
        return groups;
    }
    /**
     * Maps the parent child data to a table data
     *
     * @param {GroupedParentChildDataset[]} parentChildGroups
     * @return {*}  {ParentChildData[]}
     * @memberof ParentChildDataBuilder
     */
    mapToTableData(parentChildGroups) {
        const parentTableBuilder = new DataTableBuilder(this.fields);
        return parentChildGroups.map((group) => {
            const parentTable = parentTableBuilder.withNoHeaderOptions(this.columns).buildTable(group.parent);
            const children = this.mapChildDataToTableData(group);
            return {
                parent: parentTable,
                children,
            };
        });
    }
    /**
     * Maps the grouped child data to table data
     *
     * @param {GroupedParentChildDataset} group
     * @return {*}
     * @memberof ParentChildDataBuilder
     */
    mapChildDataToTableData(group) {
        return group.children.map((child) => {
            const { fields: childFields, columns: childColumns, name } = this.getChildVariantDefinitionData(child.id);
            const childTableBuilder = new DataTableBuilder(childFields);
            const childTable = childTableBuilder.withNoHeaderOptions(childColumns).buildTable(child.data);
            return {
                title: name,
                ...childTable,
            };
        });
    }
    withChildData(childData) {
        this.childData = childData;
        return this;
    }
    withChildColumns(childColumns) {
        this.childColumns = childColumns;
        return this;
    }
    build() {
        const sectionData = new SectionedDataHelper()
            .withSections(this.sections)
            .withData(this.data)
            .withFields(this.fields)
            .withReportQuery(this.reportQuery)
            .build();
        const { sections } = sectionData;
        const mappedSections = sections.map((section) => {
            const groups = this.mergeParentChildAndGroup(section.data);
            const table = this.mapToTableData(groups);
            return {
                ...section,
                summaries: [],
                data: table,
            };
        });
        return {
            rowCount: this.data.length,
            sections: mappedSections,
        };
    }
}

export { ParentChildDataBuilder };
//# sourceMappingURL=ParentChildDataBuilder.js.map
