// src/transformers/mappingTransformer.ts
import { ITransformer, PipelineContext } from '../core/interfaces';
import { get, set } from 'lodash'; // Use lodash for safe nested access, install: npm i lodash @types/lodash

// Define rule structure (can be more sophisticated)
export interface MappingRule {
    sourcePath: string; // Dot notation path in input object (e.g., 'user.profile.firstName')
    targetPath: string; // Dot notation path in output object
    // Optional: transformation function, default value, type casting etc.
    transform?: (value: any, input: any, context: PipelineContext) => any;
    defaultValue?: any;
}

export class MappingTransformer<TInput, TOutput> implements ITransformer<TInput, TOutput> {
    private rules: MappingRule[];

    constructor(rules: MappingRule[]) {
        this.rules = rules;
    }

    async transform(data: TInput, context: PipelineContext): Promise<TOutput> {
        const output: Partial<TOutput> = {}; // Start with an empty object

        for (const rule of this.rules) {
            let value = get(data, rule.sourcePath, rule.defaultValue); // Get value using lodash

            if (rule.transform) {
                try {
                     value = await Promise.resolve(rule.transform(value, data, context)); // Allow async transforms
                } catch (err: any) {
                    context.logger.error({ err, rule, input: data }, `Error during custom mapping transformation for ${rule.sourcePath}`);
                    // Decide how to handle: skip field, throw, set default?
                    value = rule.defaultValue; // Default on error?
                }
            }

            if (value !== undefined) { // Only set if value is not undefined (allows defaults)
               set(output as object, rule.targetPath, value); // Set value using lodash
            }
        }

        return output as TOutput; // Assume the output matches TOutput structure
    }
}