// SPDX-License-Identifier: Apache-2.0
import { expect } from 'chai';
import { describe, it } from 'mocha';
import each from 'mocha-each';
import { Flags as flags } from '../../../src/commands/flags.js';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { NamespaceName } from '../../../src/types/namespace/namespace-name.js';
import yaml from 'yaml';
import * as helpers from '../../../src/core/helpers.js';
import { helmValuesHelper } from '../../../src/core/helm-values-helper.js';
import { ConsensusNode } from '../../../src/core/model/consensus-node.js';
function makeConsensusNode(name, nodeId) {
    return new ConsensusNode(name, nodeId, 'solo', 'cluster', 'ctx', 'cluster.local', 'network-{0}-svc', 'network-node1-svc.solo.svc.cluster.local', [], []);
}
function generateAndParse(nodes, options) {
    const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'test-gen-env-'));
    try {
        const filePath = helmValuesHelper.generateExtraEnvironmentValuesFile(nodes, options, temporaryDirectory);
        const content = fs.readFileSync(filePath, 'utf8');
        return yaml.parse(content);
    }
    finally {
        fs.rmSync(temporaryDirectory, { recursive: true, force: true });
    }
}
describe('Helpers', () => {
    each([
        { input: '', output: [] },
        { input: 'node1', output: ['node1'] },
        { input: 'node1,node3', output: ['node1', 'node3'] },
    ]).it('should parse node aliases for input', ({ input, output }) => {
        expect(helpers.parseNodeAliases(input)).to.deep.equal(output);
    });
    each([
        { input: [], output: [] },
        { input: [1, 2, 3], output: [1, 2, 3] },
        { input: ['a', '2', '3'], output: ['a', '2', '3'] },
    ]).it('should clone array for input', ({ input, output }) => {
        const clonedArray = helpers.cloneArray(input);
        expect(clonedArray).to.deep.equal(output);
        expect(clonedArray).not.to.equal(input); // ensure cloning creates a new array
    });
    it('Should parse argv to args with boolean flag correctly', () => {
        const argv = { [flags.quiet.name]: true };
        const result = flags.stringifyArgv(argv);
        expect(result).to.equal(`--${flags.quiet.name}`);
    });
    it('Should parse argv to args with flag correctly', () => {
        const argv = { [flags.namespace.name]: 'VALUE' };
        const result = flags.stringifyArgv(argv);
        expect(result).to.equal(`--${flags.namespace.name} VALUE`);
    });
    it('Should ipv4ToByteArray convert IPv4 address to string', () => {
        const ipV4Address = '192.168.0.1';
        const byteString = helpers.ipV4ToBase64(ipV4Address);
        expect(byteString).to.equal('wKgAAQ==');
    });
    describe('generateExtraEnvironmentValuesFile', () => {
        it('should sanitize -Xms/-Xmx from JAVA_OPTS coming from baseExtraEnvironmentVariables', () => {
            const node = makeConsensusNode('node1', 0);
            const result = generateAndParse([node], {
                baseExtraEnvironmentVariables: {
                    node1: [{ name: 'JAVA_OPTS', value: '-Xms256m -Xmx2g -Dfoo=bar' }],
                },
            });
            const javaOptions = result.hedera.nodes[0].root?.extraEnv.find((environmentEntry) => environmentEntry.name === 'JAVA_OPTS')?.value;
            expect(javaOptions).to.equal('-Dfoo=bar');
        });
        it('should sanitize -Xms/-Xmx from JAVA_OPTS after debug-node prepend adds base value with heap flags', () => {
            const node = makeConsensusNode('node1', 0);
            const result = generateAndParse([node], {
                debugNodeAlias: 'node1',
                baseExtraEnvironmentVariables: {
                    node1: [{ name: 'JAVA_OPTS', value: '-Xms512m -Xmx4g -Dfoo=bar' }],
                },
            });
            const javaOptions = result.hedera.nodes[0].root?.extraEnv.find((environmentEntry) => environmentEntry.name === 'JAVA_OPTS')?.value;
            // debug jdwp prefix should be present, heap flags should be gone
            expect(javaOptions).to.include('-agentlib:jdwp=');
            expect(javaOptions).to.not.include('-Xms');
            expect(javaOptions).to.not.include('-Xmx');
            expect(javaOptions).to.include('-Dfoo=bar');
        });
        it('should sanitize -Xms/-Xmx from JAVA_OPTS coming from additionalEnvironmentVariables', () => {
            const node = makeConsensusNode('node1', 0);
            const result = generateAndParse([node], {
                additionalEnvironmentVariables: {
                    node1: [{ name: 'JAVA_OPTS', value: '-Xms128m -Xmx1g -Dbaz=qux' }],
                },
            });
            const javaOptions = result.hedera.nodes[0].root?.extraEnv.find((environmentEntry) => environmentEntry.name === 'JAVA_OPTS')?.value;
            expect(javaOptions).to.equal('-Dbaz=qux');
        });
        it('should preserve blockNodesJson from additionalNodeValues in the output structure', () => {
            const node = makeConsensusNode('node1', 0);
            const blockNodesJsonContent = JSON.stringify({ blockNodes: [{ host: 'localhost', port: 8080 }] });
            const result = generateAndParse([node], {
                additionalNodeValues: {
                    node1: { name: 'node1', nodeId: 0, accountId: '0.0.3', blockNodesJson: blockNodesJsonContent },
                },
            });
            expect(result.hedera.nodes[0].blockNodesJson).to.equal(blockNodesJsonContent);
        });
        it('should not include blockNodesJson in output when not provided', () => {
            const node = makeConsensusNode('node1', 0);
            const result = generateAndParse([node], {
                additionalNodeValues: {
                    node1: { name: 'node1', nodeId: 0, accountId: '0.0.3' },
                },
            });
            expect(result.hedera.nodes[0].blockNodesJson).to.be.undefined;
        });
    });
    describe('extractPerNodeBlockNodesJsonFromValuesFile', () => {
        it('should extract blockNodesJson per node from a YAML values file', () => {
            const node = makeConsensusNode('node1', 0);
            const blockNodesJsonContent = JSON.stringify({ nodes: [{ host: 'block-node', port: 8080 }] });
            const valuesContent = [
                'hedera:',
                '  nodes:',
                '    - name: node1',
                '      nodeId: 0',
                `      blockNodesJson: '${blockNodesJsonContent}'`,
            ].join('\n');
            const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'test-helpers-'));
            const temporaryFile = path.join(temporaryDirectory, 'values.yaml');
            fs.writeFileSync(temporaryFile, valuesContent, 'utf8');
            try {
                const result = helmValuesHelper.extractPerNodeBlockNodesJsonFromValuesFile(temporaryFile, [node]);
                expect(result['node1']).to.equal(blockNodesJsonContent);
            }
            finally {
                fs.rmSync(temporaryDirectory, { recursive: true, force: true });
            }
        });
        it('should return empty record when file does not exist', () => {
            const node = makeConsensusNode('node1', 0);
            const result = helmValuesHelper.extractPerNodeBlockNodesJsonFromValuesFile('/nonexistent/file.yaml', [node]);
            expect(result).to.deep.equal({});
        });
        it('should return empty record when hedera.nodes is absent from the file', () => {
            const node = makeConsensusNode('node1', 0);
            const valuesContent = 'hedera:\n  configMaps:\n    configTxt: "foo"\n';
            const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'test-helpers-'));
            const temporaryFile = path.join(temporaryDirectory, 'values.yaml');
            fs.writeFileSync(temporaryFile, valuesContent, 'utf8');
            try {
                const result = helmValuesHelper.extractPerNodeBlockNodesJsonFromValuesFile(temporaryFile, [node]);
                expect(result).to.deep.equal({});
            }
            finally {
                fs.rmSync(temporaryDirectory, { recursive: true, force: true });
            }
        });
    });
    describe('remoteConfigsToDeploymentsTable', () => {
        it('should support clusters as an object map', () => {
            const remoteConfigs = [
                {
                    namespace: NamespaceName.of('default'),
                    name: 'remote-config',
                    data: {
                        'remote-config-data': yaml.stringify({
                            clusters: {
                                clusterA: { deployment: 'deployment-a' },
                            },
                        }),
                    },
                },
            ];
            const rows = helpers.remoteConfigsToDeploymentsTable(remoteConfigs);
            expect(rows).to.deep.equal(['Namespace : deployment', 'default : deployment-a']);
        });
        it('should return header only when clusters is missing', () => {
            const remoteConfigs = [
                {
                    namespace: NamespaceName.of('default'),
                    name: 'remote-config',
                    data: {
                        'remote-config-data': yaml.stringify({}),
                    },
                },
            ];
            const rows = helpers.remoteConfigsToDeploymentsTable(remoteConfigs);
            expect(rows).to.deep.equal(['Namespace : deployment']);
        });
    });
});
//# sourceMappingURL=helpers.test.js.map