import { AppConstants } from "../../src/constants/app.constants.js";
import { TypeNotFoundException } from "../../src/exeptions/type-not-found-exception.js";
import { isBaseAsset } from "../../src/functions/asset.helper.js";
import { getDocumentBasedOnLanguage, getLanguage, getType, getContentType, isInvalidFile } from "../../src/functions/data.parser.js";
import { isJSON, parseJSON } from "../../src/functions/json.helper.js";
import { isOpenAPI } from "../../src/functions/open-api.helper.js";
import { isYAML, loadYaml } from "../../src/functions/yaml.helper.js";
import yaml from 'js-yaml';

jest.mock('../../src/functions/open-api.helper', () => ({
    isOpenAPI: jest.fn()
}));

jest.mock('../../src/functions/swagger-api.helper', () => ({
    isSwagger: jest.fn()
}));

jest.mock('../../src/functions/asset.helper', () => ({
    isBaseAsset: jest.fn()
}));

jest.mock('../../src/functions/json.helper', () => ({
    isJSON: jest.fn(),
    parseJSON: jest.fn()
}));

jest.mock('../../src/functions/yaml.helper', () => ({
    isYAML: jest.fn(),
    loadYaml: jest.fn()
}));

describe('Data Parser Utility Functions test', () => {

    describe('getDocumentBasedOnLanguage', () => {
        it('should parse YAML content correctly', () => {
            const yamlContent = 'key: value';
            const parsed = { key: 'value' };
            (loadYaml as jest.Mock).mockReturnValue(parsed);
            const result = getDocumentBasedOnLanguage(yamlContent, 'yaml');
            expect(result).toEqual(parsed);
        });

        it('should parse JSON content correctly', () => {
            const jsonContent = '{"key": "value"}';
            const parsed = { key: 'value' };
            (parseJSON as jest.Mock).mockReturnValue(parsed);
            const result = getDocumentBasedOnLanguage(jsonContent, 'json');
            expect(result).toEqual(parsed);
        });

        it('should return undefined for unsupported language', () => {
            const result = getDocumentBasedOnLanguage('content', 'xml');
            expect(result).toBeUndefined();
        });

        it('should handle parsing errors gracefully', () => {
            (loadYaml as jest.Mock).mockImplementation(() => { throw new Error('YAML parse error'); });
            const result = getDocumentBasedOnLanguage('invalid yaml', 'yaml');
            expect(result).toBeUndefined();
        });
    });

    describe('getType', () => {
        it('should return "rest" for OpenAPI or Swagger data', () => {
            const mockData = 'openapi data';
            (isOpenAPI as jest.Mock).mockReturnValue(true);
            const result = getType(mockData, 'json');
            expect(result).toBe('rest');
        });

        it('should return "asset" for base asset data', () => {
            const mockData = 'asset data';
            (isOpenAPI as jest.Mock).mockReturnValue(false);
            (isBaseAsset as jest.Mock).mockReturnValue(true);
            const result = getType(mockData, 'json');
            expect(result).toBe('asset');
        });

        it('should return TypeNotFoundException for unknown type', () => {
            const mockData = 'unknown data';
            (isOpenAPI as jest.Mock).mockReturnValue(false);
            (isBaseAsset as jest.Mock).mockReturnValue(false);
            const result = getType(mockData, 'json');
            expect(result).toBeInstanceOf(TypeNotFoundException);
            expect(result).toHaveProperty('message', AppConstants.TYPE_NOT_FOUND_EXCEPTION);
        });
    });

    describe('getLanguage', () => {
        it('should return "json" for JSON data', () => {
            (isJSON as jest.Mock).mockReturnValue(true);
            const result = getLanguage('{"key": "value"}');
            expect(result).toBe('json');
        });

        it('should return "yaml" for YAML data', () => {
            (isJSON as jest.Mock).mockReturnValue(false);
            (isYAML as jest.Mock).mockReturnValue(true);
            const result = getLanguage('key: value');
            expect(result).toBe('yaml');
        });

        it('should return an empty string for unknown data formats', () => {
            (isJSON as jest.Mock).mockReturnValue(false);
            (isYAML as jest.Mock).mockReturnValue(false);
            const result = getLanguage('unknown data');
            expect(result).toBe('');
        });
    });

    describe('getContentType', () => {
        it('should return application/yaml for yaml language', () => {
            const result = getContentType('yaml');
            expect(result).toBe(AppConstants.APPLICATION_YAML_REQ_TYPE);
        });

        it('should return application/json for json language', () => {
            const result = getContentType('json');
            expect(result).toBe(AppConstants.APPLICATION_JSON_REQ_TYPE);
        });

        it('should return empty string for unsupported language', () => {
            const result = getContentType('xml');
            expect(result).toBe('');
        });
    });

    describe('isInvalidFile', () => {
        it('should return true for invalid YAML content', () => {
            expect(isInvalidFile('{invalid yaml}', 'yaml')).toBe(true);
        });

        it('should return false for valid YAML content', () => {
            expect(isInvalidFile('key: value', 'yaml')).toBe(false);
        });

        it('should return true for invalid JSON content', () => {
            expect(isInvalidFile('invalid json', 'json')).toBe(true);
        });

        it('should return false for valid JSON content', () => {
            expect(isInvalidFile('{"key": "value"}', 'json')).toBe(false);
        });

        it('should return true for unsupported file extensions', () => {
            expect(isInvalidFile('content', 'xml')).toBe(true);
        });
    });
});
