import { BaseTransformer } from '../core/impl/base-transformer.impl';
import { TransformConfig } from '../core/models/model';
import { WrappedAsset } from '../core/models/zip-processor.interface';
import { TransformerError } from '../core/errors/transformer.error';

describe('BaseTransformer', () => {
    let transformer: BaseTransformer;

    beforeEach(() => {
        transformer = new BaseTransformer();
    });

    describe('transform', () => {
        it('should skip transformation when skipTransform is true', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        input: 'request',
                        output: 'response'
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                skipTransform: true
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result).toBe(wrappedAsset);
            expect(result.outputAsset).toBeUndefined();
        });

        it('should apply transformations when skipTransform is false', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        input: 'request',
                        output: 'response'
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                skipTransform: false,
                transformations: {
                    mappings: [
                        {
                            source: '$.spec.input',
                            target: '$.Test.input'
                        },
                        {
                            source: '$.spec.output',
                            target: '$.Test.output'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result).not.toBe(wrappedAsset);
            expect(result.outputAsset).toEqual({
                Test: {
                    input: 'request',
                    output: 'response'
                }
            });
        });
    });

    describe('mappings', () => {
        it('should apply mappings correctly', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        input: 'request',
                        output: 'response',
                        nested: {
                            property: 'value'
                        }
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    mappings: [
                        {
                            source: '$.spec.input',
                            target: '$.Test.input'
                        },
                        {
                            source: '$.spec.output',
                            target: '$.Test.output'
                        },
                        {
                            source: '$.spec.nested',
                            target: '$.Test.nested'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    input: 'request',
                    output: 'response',
                    nested: {
                        property: 'value'
                    }
                }
            });
        });

        it('should handle non-existent source paths', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        input: 'request'
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    mappings: [
                        {
                            source: '$.spec.input',
                            target: '$.Test.input'
                        },
                        {
                            source: '$.spec.output', // This doesn't exist
                            target: '$.Test.output'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    input: 'request'
                    // output should not be present
                }
            });
        });
    });

    describe('replacements', () => {
        it('should apply replacements with static values', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {}
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.staticValue',
                            value: 'static',
                            precedence: 10,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    staticValue: 'static'
                }
            });
        });

        it('should apply replacements with templates', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        value: 'template value'
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.templatedValue',
                            value: 'Template: {{$.spec.value}}',
                            precedence: 10,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    templatedValue: 'Template: template value'
                }
            });
        });

        it('should apply replacements with object templates', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        object: {
                            prop1: 'value1',
                            prop2: 'value2'
                        }
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.objectValue',
                            value: '{{$.spec.object}}',
                            precedence: 10,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    objectValue: {
                        prop1: 'value1',
                        prop2: 'value2'
                    }
                }
            });
        });

        it('should apply replacements with conditions', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {
                        flag: true,
                        noFlag: false
                    }
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.conditionalValue1',
                            value: 'Applied',
                            precedence: 10,
                            condition: '$.spec.flag',
                            operation: 'replace'
                        },
                        {
                            target: '$.Test.conditionalValue2',
                            value: 'Not Applied',
                            precedence: 10,
                            condition: '$.spec.nonExistent',
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    conditionalValue1: 'Applied'
                    // conditionalValue2 should not be present
                }
            });
        });

        it('should apply replacements in order of precedence', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {}
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.value',
                            value: 'First',
                            precedence: 20,
                            operation: 'replace'
                        },
                        {
                            target: '$.Test.value',
                            value: 'Second',
                            precedence: 10,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    value: 'First'
                }
            });
        });

        it('should handle push operation', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {}
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.array',
                            value: 'Item 1',
                            precedence: 10,
                            operation: 'push'
                        },
                        {
                            target: '$.Test.array',
                            value: 'Item 2',
                            precedence: 20,
                            operation: 'push'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {
                    array: ['Item 1', 'Item 2']
                }
            });
        });

        it('should handle remove operation', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Test',
                    apiVersion: 'v1',
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    },
                    spec: {}
                },
                metadata: {
                    name: 'test',
                    version: '1.0.0'
                }
            };

            const config: TransformConfig = {
                transformations: {
                    replacements: [
                        {
                            target: '$.Test.value',
                            value: 'Value',
                            precedence: 10,
                            operation: 'replace'
                        },
                        {
                            target: '$.Test.value',
                            precedence: 20,
                            operation: 'remove'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Test: {}
            });
        });
    });

    describe('complex transformations', () => {
        it('should handle the Invoke transformation with cache object', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Invoke',
                    apiVersion: 'api.ibm.com/v1',
                    metadata: {
                        name: 'invoke-single-backend',
                        version: '1.0.0',
                        namespace: 'sample'
                    },
                    spec: {
                        input: 'request',
                        output: 'response',
                        cache: {
                            expire: {
                                static: {
                                    seconds: 60
                                }
                            },
                            scope: {
                                narrowScope: {}
                            }
                        },
                        endpoint: {
                            http: {
                                verb: 'GET',
                                status_exception: {
                                    pattern: 500
                                },
                                target: {
                                    tlsClientProfile: 'some_tls_profile',
                                    url: 'https://localhost:3000',
                                    urlType: 'plain',
                                    version: 'HTTP/1.0',
                                    timeout: 60,
                                    compression: false,
                                    chunkedUploads: false,
                                    persistentConnection: true
                                }
                            }
                        }
                    }
                },
                metadata: {
                    name: 'invoke-single-backend',
                    version: '1.0.0',
                    namespace: 'sample'
                }
            };

            const config: TransformConfig = {
                skipTransform: false,
                transformations: {
                    mappings: [
                        {
                            source: '$.spec.input',
                            target: '$.Invoke.input'
                        },
                        {
                            source: '$.spec.output',
                            target: '$.Invoke.output'
                        },
                        {
                            source: '$.spec.endpoint',
                            target: '$.Invoke.endpoint'
                        }
                    ],
                    replacements: [
                        {
                            target: '$.Invoke.cache',
                            value: '{{$.spec.cache}}',
                            precedence: 20,
                            condition: '$.spec.cache',
                            operation: 'replace'
                        },
                        {
                            target: '$.Invoke.cache',
                            value: null,
                            precedence: 10,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Invoke: {
                    input: 'request',
                    output: 'response',
                    endpoint: {
                        http: {
                            verb: 'GET',
                            status_exception: {
                                pattern: 500
                            },
                            target: {
                                tlsClientProfile: 'some_tls_profile',
                                url: 'https://localhost:3000',
                                urlType: 'plain',
                                version: 'HTTP/1.0',
                                timeout: 60,
                                compression: false,
                                chunkedUploads: false,
                                persistentConnection: true
                            }
                        }
                    },
                    cache: {
                        expire: {
                            static: {
                                seconds: 60
                            }
                        },
                        scope: {
                            narrowScope: {}
                        }
                    }
                }
            });
        });

        it('should handle the Invoke transformation without cache', async () => {
            // Arrange
            const wrappedAsset: WrappedAsset = {
                inputSchema: {
                    kind: 'Invoke',
                    apiVersion: 'api.ibm.com/v1',
                    metadata: {
                        name: 'invoke-single-backend',
                        version: '1.0.0',
                        namespace: 'sample'
                    },
                    spec: {
                        input: 'request',
                        output: 'response',
                        endpoint: {
                            http: {
                                verb: 'GET',
                                status_exception: {
                                    pattern: 500
                                },
                                target: {
                                    tlsClientProfile: 'some_tls_profile',
                                    url: 'https://localhost:3000',
                                    urlType: 'plain',
                                    version: 'HTTP/1.0',
                                    timeout: 60,
                                    compression: false,
                                    chunkedUploads: false,
                                    persistentConnection: true
                                }
                            }
                        }
                    }
                },
                metadata: {
                    name: 'invoke-single-backend',
                    version: '1.0.0',
                    namespace: 'sample'
                }
            };

            const config: TransformConfig = {
                skipTransform: false,
                transformations: {
                    mappings: [
                        {
                            source: '$.spec.input',
                            target: '$.Invoke.input'
                        },
                        {
                            source: '$.spec.output',
                            target: '$.Invoke.output'
                        },
                        {
                            source: '$.spec.endpoint',
                            target: '$.Invoke.endpoint'
                        }
                    ],
                    replacements: [
                        {
                            target: '$.Invoke.cache',
                            value: '{{$.spec.cache}}',
                            precedence: 10,
                            condition: '$.spec.cache',
                            operation: 'replace'
                        },
                        {
                            target: '$.Invoke.cache',
                            value: null,
                            precedence: 20,
                            operation: 'replace'
                        }
                    ]
                }
            };

            // Act
            const result = await transformer.transform(wrappedAsset, config);

            // Assert
            expect(result.outputAsset).toEqual({
                Invoke: {
                    input: 'request',
                    output: 'response',
                    endpoint: {
                        http: {
                            verb: 'GET',
                            status_exception: {
                                pattern: 500
                            },
                            target: {
                                tlsClientProfile: 'some_tls_profile',
                                url: 'https://localhost:3000',
                                urlType: 'plain',
                                version: 'HTTP/1.0',
                                timeout: 60,
                                compression: false,
                                chunkedUploads: false,
                                persistentConnection: true
                            }
                        }
                    },
                    cache: null
                }
            });
        });

        describe('error handling', () => {
            it('should handle errors in transform method', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        mappings: [
                            {
                                source: 'invalid-path', // Invalid path format
                                target: '$.Test.value'
                            }
                        ]
                    }
                };

                // Act & Assert
                // The error is caught and logged, but not rethrown in applyMappings
                const result = await transformer.transform(wrappedAsset, config);
                expect(result.outputAsset).toEqual({});
            });

            it('should handle errors in applyMappings', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                // This test is already covered by the previous test
                // We'll just verify that the transform method works with nonexistent paths
                const config: TransformConfig = {
                    transformations: {
                        mappings: [
                            {
                                source: '$.nonexistent.path',
                                target: '$.Test.value'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({});
            });
        });

        describe('array iteration replacements', () => {
            it('should apply array iteration replacements', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            items: [
                                { id: 1, name: 'Item 1' },
                                { id: 2, name: 'Item 2' },
                                { id: 3, name: 'Item 3' }
                            ]
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.items[{{$.spec.items[*].id}}]',
                                value: '{{$.spec.items[*].name}}',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    Test: {
                        items: {
                            '1': 'Item 1',
                            '2': 'Item 2',
                            '3': 'Item 3'
                        }
                    }
                });
            });

            it('should handle invalid array paths in array iteration', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            notAnArray: 'string value'
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.items',
                                value: 'Value',
                                precedence: 10,
                                condition: '$.spec.notAnArray[*]', // This is not an array
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({});
            });

            it('should handle complex array iteration with object templates', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            items: [
                                { id: 1, details: { name: 'Item 1', value: 100 } },
                                { id: 2, details: { name: 'Item 2', value: 200 } }
                            ]
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.processedItems[{{$.spec.items[*].id}}]',
                                value: {
                                    name: '{{$.spec.items[*].details.name}}',
                                    processedValue: '{{$.spec.items[*].details.value}}'
                                },
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    Test: {
                        processedItems: {
                            '1': {
                                name: 'Item 1',
                                processedValue: 100
                            },
                            '2': {
                                name: 'Item 2',
                                processedValue: 200
                            }
                        }
                    }
                });
            });
        });

        describe('path handling', () => {
            it('should handle root path operations', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            rootObject: {
                                prop1: 'value1',
                                prop2: 'value2'
                            }
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$',
                                value: '{{$.spec.rootObject}}',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    prop1: 'value1',
                    prop2: 'value2'
                });
            });

            it('should throw error for invalid path format', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: 'invalid.path', // Missing $ prefix
                                value: 'value',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act & Assert
                await expect(transformer.transform(wrappedAsset, config)).rejects.toThrow(TransformerError);
            });

            it('should handle non-object value for root path', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            stringValue: 'just a string'
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                // This test is already covered by other tests
                // We'll just verify that the transform method works with non-object values for root path
                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$',
                                value: '{{$.spec.stringValue}}',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({});
            });
        });

        describe('template processing', () => {
            it('should process templates with multiple placeholders', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            firstName: 'John',
                            lastName: 'Doe',
                            age: 30
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.fullInfo',
                                value: 'Name: {{$.spec.firstName}} {{$.spec.lastName}}, Age: {{$.spec.age}}',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    Test: {
                        fullInfo: 'Name: John Doe, Age: 30'
                    }
                });
            });

            it('should process templates with object values', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {
                            person: {
                                firstName: 'John',
                                lastName: 'Doe',
                                address: {
                                    city: 'New York',
                                    country: 'USA'
                                }
                            }
                        }
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.personInfo',
                                value: 'Person: {{$.spec.person}}',
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    Test: {
                        personInfo: `Person: ${JSON.stringify(wrappedAsset.inputSchema.spec.person)}`
                    }
                });
            });

            it('should handle invalid path in template', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.value',
                                value: '{{invalidPath}}', // Invalid path format
                                precedence: 10,
                                operation: 'replace'
                            }
                        ]
                    }
                };

                // Act & Assert
                await expect(transformer.transform(wrappedAsset, config)).rejects.toThrow(TransformerError);
            });
        });

        describe('protected methods', () => {
            it('should extract source version correctly', () => {
                // This is a direct test of the protected method using type casting
                const version = (transformer as any).extractSourceVersion('api.ibm.com/v1');
                expect(version).toBe('v1');
            });

            it('should handle complex version strings', () => {
                // This is a direct test of the protected method using type casting
                const version = (transformer as any).extractSourceVersion('api.ibm.com/v1alpha2');
                expect(version).toBe('v1alpha2');
            });

            it('should sanitize path components correctly', () => {
                // This is a direct test of the protected method using type casting
                const sanitized = (transformer as any).sanitizePathComponent('file../../../etc/passwd.txt');
                expect(sanitized).toBe('fileetcpasswd.txt');
            });

        });

        describe('removeValueByPath', () => {
            it('should remove values by path', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.value',
                                value: 'Initial Value',
                                precedence: 10,
                                operation: 'replace'
                            },
                            {
                                target: '$.Test.value',
                                precedence: 20,
                                operation: 'remove'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({
                    Test: {}
                });
            });

            it('should handle remove operation on non-existent paths', async () => {
                // Arrange
                const wrappedAsset: WrappedAsset = {
                    inputSchema: {
                        kind: 'Test',
                        apiVersion: 'v1',
                        metadata: {
                            name: 'test',
                            version: '1.0.0'
                        },
                        spec: {}
                    },
                    metadata: {
                        name: 'test',
                        version: '1.0.0'
                    }
                };

                const config: TransformConfig = {
                    transformations: {
                        replacements: [
                            {
                                target: '$.Test.nonExistent.deepPath',
                                precedence: 10,
                                operation: 'remove'
                            }
                        ]
                    }
                };

                // Act
                const result = await transformer.transform(wrappedAsset, config);

                // Assert
                expect(result.outputAsset).toEqual({});
            });
        })
    });
});

