const assert = require('node:assert/strict');
const configUtils = require('../../../../utils/config-utils');
const settingsCache = require('../../../../../core/shared/settings-cache');
const getConfigProperties = require('../../../../../core/server/services/public-config/config');
const sinon = require('sinon');

// List of allowed keys to be returned by the public-config service
// This is kind of a duplicate of the keys in the config.js output serializer in the api-framework
// However the list of keys returned by the public-config service can differ based on flags and config set, so we want to keep this explicit

const allowedKeys = [
    'version',
    'environment',
    'database',
    'mail',
    'useGravatar',
    'labs',
    'clientExtensions',
    'enableDeveloperExperiments',
    'stripeDirect',
    'mailgunIsConfigured',
    'emailAnalytics',
    'hostSettings',
    'klipy',
    'pintura',
    'signupForm',
    'security'
];

describe('Public-config Service', function () {
    describe('Config Properties', function () {
        beforeEach(async function () {
            sinon.stub(settingsCache, 'get')
                .withArgs('site_uuid')
                .returns('931ade9e-a4f1-4217-8625-34bd34250c16');
        });
        afterEach(async function () {
            await configUtils.restore();
            sinon.restore();
        });

        it('should return the correct default config properties', function () {
            const configProperties = getConfigProperties();

            assert.deepEqual(Object.keys(configProperties), allowedKeys);
        });

        it('should return GHOST_BUILD_VERSION as version when set', function () {
            process.env.GHOST_BUILD_VERSION = '6.21.2+abc1234';

            const configProperties = getConfigProperties();

            assert.equal(configProperties.version, '6.21.2+abc1234');

            delete process.env.GHOST_BUILD_VERSION;
        });

        it('should return package version when GHOST_BUILD_VERSION is not set', function () {
            delete process.env.GHOST_BUILD_VERSION;

            const configProperties = getConfigProperties();

            assert.match(configProperties.version, /^\d+\.\d+\.\d+/);
            assert.notEqual(configProperties.version, '6.21.2+abc1234');
        });

        it('should return null for klipy apikey when unset', function () {
            let configProperties = getConfigProperties();

            assert.equal(configProperties.klipy.apiKey, null);
        });

        it('should return klipy apikey when set', function () {
            configUtils.set('klipy:apiKey', 'KLIPY_KEY');

            let configProperties = getConfigProperties();

            assert.equal(configProperties.klipy.apiKey, 'KLIPY_KEY');
        });

        it('should return true for mailgunIsConfigured when mailgun is configured', function () {
            configUtils.set('bulkEmail', {
                mailgun: 'exists'
            });

            let configProperties = getConfigProperties();

            assert.equal(configProperties.mailgunIsConfigured, true);
        });

        it('should return false for mailgunIsConfigured when mailgun is not configured', function () {
            configUtils.set('bulkEmail', {});

            let configProperties = getConfigProperties();

            assert.equal(configProperties.mailgunIsConfigured, false);
        });

        it('should NOT return stats by default', function () {
            let configProperties = getConfigProperties();

            assert.equal(configProperties.stats, undefined);
        });

        it('should return stats when tinybird config is set with the stats key', function () {
            configUtils.set('tinybird', {
                stats: {
                    endpoint: 'xxx',
                    endpointBrowser: 'https://browser.example.com',
                    version: 'v2',
                    datasource: 'analytics_events'
                }
            });

            let configProperties = getConfigProperties();

            assert.deepEqual(configProperties.stats, {
                endpoint: 'xxx',
                endpointBrowser: 'https://browser.example.com',
                version: 'v2',
                datasource: 'analytics_events',
                id: '931ade9e-a4f1-4217-8625-34bd34250c16'
            });
        });

        it('should return stats id when tinybird config is set with the id key', function () {
            configUtils.set('tinybird', {
                stats: {
                    id: '1234567890'
                }
            });

            let configProperties = getConfigProperties();

            assert.deepEqual(configProperties.stats.id, '1234567890');
        });

        it('should not return stats token when tinybird config is set with a token', function () {
            configUtils.set('tinybird', {
                stats: {
                    endpoint: 'xxx',
                    token: 'secret-token'
                }
            });

            let configProperties = getConfigProperties();

            assert.deepEqual(configProperties.stats, {
                endpoint: 'xxx',
                id: '931ade9e-a4f1-4217-8625-34bd34250c16'
            });
            assert.equal(configProperties.stats.token, undefined);
        });

        it('should return public local stats config without the local stats token', function () {
            configUtils.set('tinybird', {
                stats: {
                    endpoint: 'xxx',
                    local: {
                        enabled: true,
                        endpoint: 'http://localhost:7181',
                        datasource: 'analytics_events_local',
                        token: 'local-secret-token'
                    }
                }
            });

            let configProperties = getConfigProperties();

            assert.deepEqual(configProperties.stats, {
                endpoint: 'xxx',
                id: '931ade9e-a4f1-4217-8625-34bd34250c16',
                local: {
                    enabled: true,
                    endpoint: 'http://localhost:7181',
                    datasource: 'analytics_events_local'
                }
            });
            assert.equal(configProperties.stats.local.token, undefined);
        });

        it('should NOT return stats when tinybird config is set without the stats key', function () {
            configUtils.set('tinybird', {
                url: 'xxx'
            });

            let configProperties = getConfigProperties();

            assert.equal(configProperties.stats, undefined);
        });

        it('should return emailAnalytics as boolean from nested config structure', function () {
            // Default config has emailAnalytics.enabled = true
            let configProperties = getConfigProperties();

            assert.equal(configProperties.emailAnalytics, true);
            assert.equal(typeof configProperties.emailAnalytics, 'boolean');
        });

        it('should return false for emailAnalytics when disabled', function () {
            configUtils.set('emailAnalytics:enabled', false);

            let configProperties = getConfigProperties();

            assert.equal(configProperties.emailAnalytics, false);
        });

        it('should NOT return featurebase config by default', function () {
            let configProperties = getConfigProperties();
            assert.equal(configProperties.featurebase, undefined);
        });

        it('should return featurebase config with enabled=false when configured but disabled', function () {
            configUtils.set('labs', {
                featurebaseFeedback: true
            });
            configUtils.set('featurebase', {
                enabled: false,
                organization: 'test-org',
                jwtSecret: 'super-secret-key'
            });

            let configProperties = getConfigProperties();

            assert.equal(configProperties.featurebase.enabled, false);
            assert.equal(configProperties.featurebase.organization, 'test-org');
        });

        it('should return only public featurebase config properties, not sensitive ones', function () {
            configUtils.set('labs', {
                featurebaseFeedback: true
            });
            configUtils.set('featurebase', {
                enabled: true,
                organization: 'test-org',
                jwtSecret: 'super-secret-key',
                apiKey: 'secret-api-key'
            });

            let configProperties = getConfigProperties();

            // Only enabled and organization should be exposed, not jwtSecret/apiKey
            assert.deepEqual(
                configProperties.featurebase,
                {enabled: true, organization: 'test-org'}
            );
            assert.equal(configProperties.featurebase.jwtSecret, undefined);
            assert.equal(configProperties.featurebase.apiKey, undefined);
        });
    });
});
