import { ExpressionParser, PathExpression } from '../core/services/expression-parser.service';
import { BaseTransformer } from '../core/impl/base-transformer.impl';

class TestTransformer extends BaseTransformer {
    public testGetValueByPath(obj: any, path: string): any {
        return this.getValueByPath(obj, path);
    }

    public testSetValueByPath(obj: any, path: string, value: any): void {
        return this.setValueByPath(obj, path, value);
    }

    transform(input: any): any {
        return input;
    }
}

describe('Special key handling tests', () => {
    let transformer: TestTransformer;
    let pathExpression: PathExpression;

    beforeEach(() => {
        transformer = new TestTransformer();
        pathExpression = new PathExpression('$.test');
    });

    describe('Object keys with special characters', () => {
        it('should handle keys with hyphens', () => {
            const obj = { 'key-with-hyphens': 'value' };

            // Test BaseTransformer getValueByPath
            expect(transformer.testGetValueByPath(obj, '$.key-with-hyphens')).toBe('value');

            // Test PathExpression getValueByPath
            expect(pathExpression.getValueByPath(obj, '$.key-with-hyphens')).toBe('value');
        });

        it('should handle keys with dots by treating them as path separators', () => {
            const obj = { 'key.with.dots': 'value' };

            // The system treats dots as path separators, so this will return undefined
            expect(transformer.testGetValueByPath(obj, '$.key.with.dots')).toBeUndefined();
            expect(pathExpression.getValueByPath(obj, '$.key.with.dots')).toBeUndefined();

            // We need bracket notation or escaping for keys with dots
            // But this is not supported in the current implementation
        });

        it('should handle keys with spaces', () => {
            const obj = { 'key with spaces': 'value' };

            // Check if spaces are handled (they seem to be)
            const result = transformer.testGetValueByPath(obj, '$.key with spaces');
            expect(result).toBe('value');

            const pathResult = pathExpression.getValueByPath(obj, '$.key with spaces');
            expect(pathResult).toBe('value');
        });

        it('should handle nested objects with special characters', () => {
            const obj = {
                'dp-nano-gateway': {
                    'rate-limit': 100
                }
            };

            // Test BaseTransformer getValueByPath
            expect(transformer.testGetValueByPath(obj, '$.dp-nano-gateway.rate-limit')).toBe(100);

            // Test PathExpression getValueByPath
            expect(pathExpression.getValueByPath(obj, '$.dp-nano-gateway.rate-limit')).toBe(100);
        });
    });

    describe('Setting values with special keys', () => {
        it('should set values for keys with hyphens', () => {
            const obj = {};

            transformer.testSetValueByPath(obj, '$.dp-nano-gateway.rate-limit', 100);

            expect(obj).toEqual({
                'dp-nano-gateway': {
                    'rate-limit': 100
                }
            });
        });
    });

    describe('ExpressionParser with special keys', () => {
        it('should parse expressions with hyphens in keys', () => {
            // The regex in ExpressionParser.parse now handles hyphens
            const expression = ExpressionParser.parse('$.dp-nano-gateway.rate-limit');
            expect(expression).toBeInstanceOf(PathExpression);

            const context = {
                'dp-nano-gateway': {
                    'rate-limit': 100
                }
            };

            expect(expression.evaluate(context)).toBe(true); // Now correctly evaluates to true
        });

        it('should parse comparison expressions with hyphens in keys', () => {
            const expression = ExpressionParser.parse('$.dp-nano-gateway.rate-limit === limit');

            const context = {
                'dp-nano-gateway': {
                    'rate-limit': 'limit'
                }
            };

            expect(expression.evaluate(context)).toBe(true); // Now correctly evaluates to true
        });
    });

    describe('Bracket notation for accessing object properties', () => {
        it('should support bracket notation for accessing properties with special characters', () => {
            const obj = {
                'dp-nano-gateway': {
                    'rate-limit': 100
                }
            };

            // Now bracket notation should be supported
            expect(pathExpression.getValueByPath(obj, "$['dp-nano-gateway']['rate-limit']")).toBe(100);
        });

        it('should support bracket notation for keys with dots', () => {
            const obj = { 'key.with.dots': 'value' };

            // Current dot notation doesn't work for keys with dots
            expect(transformer.testGetValueByPath(obj, '$.key.with.dots')).toBeUndefined();

            // But bracket notation should now work
            expect(pathExpression.getValueByPath(obj, "$['key.with.dots']")).toBe('value');
        });

        it('should support mixed dot and bracket notation', () => {
            const obj = {
                'normal': {
                    'key.with.dots': 'nested value'
                }
            };

            // Mixed notation
            expect(pathExpression.getValueByPath(obj, "$.normal['key.with.dots']")).toBe('nested value');
        });
    });
});

// Made with Bob
