#!/usr/bin/env node
let json = require('format-json');
let program = require('commander');
let LaunchDarklyUtils = require('./dist/src/LaunchDarklyUtils.js').LaunchDarklyUtils;
require('dotenv').config();

if (!process.env.LAUNCHDARKLY_API_TOKEN) {
    console.log('missing environment var LAUNCHDARKLY_API_TOKEN - exiting..');
    process.exit(1);
}

let log = console;

// fallback to bunyan logger if debug mode
if (process.env.LAUNCHDARKLY_API_LOGLEVEL === 'debug') log = undefined;

process.on('unhandledRejection', (reason, p) => {
    console.error(json.plain({ error: reason }));
    process.exit(1);
});

new LaunchDarklyUtils().create(process.env.LAUNCHDARKLY_API_TOKEN, log).then(ldUtils => {
    program.version('1.0.0').description('Manage LaunchDarkly flags and other assets from the command line.');

    program
        .command('getProjects')
        .description('get all the projects associated with the account')
        .action(() => {
            ldUtils.projects.getProjects().then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getProject <projectKey>')
        .description('get a project for the specified projectKey')
        .action(projectKey => {
            ldUtils.projects.getProject(projectKey).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(
            'createProject <projectKey> <projectName> [includeInSnippetByDefault] [environments] [defaultClientSideAvailability] [tags]'
        )
        .description('Create a new project')
        .action(
            (projectKey, projectName, includeInSnippetByDefault, tags, environments, defaultClientSideAvailability) => {
                ldUtils.projects
                    .createProject(
                        projectKey,
                        projectName,
                        includeInSnippetByDefault,
                        tags,
                        environments,
                        defaultClientSideAvailability
                    )
                    .then(response => {
                        console.log(json.plain(response));
                    });
            }
        );

    program
        .command('deleteProject <projectKey>')
        .description('delete a project by the specified projectKey')
        .action(projectKey => {
            ldUtils.projects.deleteProject(projectKey).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getFeatureFlags <projectKey>')
        .description('get all flags for a given project')
        .action(projectKey => {
            ldUtils.flags.getFeatureFlags(projectKey).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(`getFeatureFlag <projectKey> <featureFlagKey> [environmentKeyQuery]`)
        .description('get a single flag - with optional env')
        .action((projectKey, featureFlagKey, environmentKeyQuery) => {
            ldUtils.flags.getFeatureFlag(projectKey, featureFlagKey, environmentKeyQuery).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(`getFeatureFlagState <projectKey> <featureFlagKey> <environmentKeyQuery>`)
        .description('get boolean flag state')
        .action((projectKey, featureFlagKey, environmentKeyQuery) => {
            ldUtils.flags.getFeatureFlagState(projectKey, featureFlagKey, environmentKeyQuery).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(`toggleFeatureFlag <projectKey> <featureFlagKey> <environmentKeyQuery> <value>`)
        .description('set boolean flag state')
        .action((projectKey, featureFlagKey, environmentKeyQuery, value) => {
            let enabled = value === 'true';
            ldUtils.flags.toggleFeatureFlag(projectKey, featureFlagKey, environmentKeyQuery, enabled).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(`migrateFeatureFlag <projectKey> <featureFlagKey> <fromEnv> <toEnv> (includeState)`)
        .description('migrate flag settings from one environment to another')
        .action((projectKey, featureFlagKey, fromEnv, toEnv, includeState) => {
            ldUtils.flags
                .migrateFeatureFlag(projectKey, featureFlagKey, fromEnv, toEnv, includeState)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command(`bulkMigrateFeatureFlags <projectKey> <featureFlagKeys> <fromEnv> <toEnv> (includeState)`)
        .description('migrate multiple flag settings from one environment to another')
        .action((projectKey, featureFlagKeys, fromEnv, toEnv, includeState) => {
            ldUtils.flags
                .bulkMigrateFeatureFlags(projectKey, featureFlagKeys, fromEnv, toEnv, includeState)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command(`restoreFeatureFlags <projectKey> <featureFlagKeys> <targetEnv> <backupJsonFile> (includeState)`)
        .description('restore environment flag settings from a backup file - backup from getFeatureFlags')
        .action((projectKey, featureFlagKeys, targetEnv, backupJsonFile, includeState) => {
            ldUtils.flags
                .restoreFeatureFlags(projectKey, featureFlagKeys, targetEnv, backupJsonFile, includeState)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command('getCustomRoles')
        .description('get all custom roles in account')
        .action(() => {
            ldUtils.roles.getCustomRoles().then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getCustomRole <customRoleKey>')
        .description('get custom role by key')
        .action(customRoleKey => {
            ldUtils.roles.getCustomRole(customRoleKey).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getCustomRoleById <customRoleId>')
        .description('get custom role by id')
        .action(customRoleId => {
            ldUtils.roles.getCustomRoleById(customRoleId).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command(`createCustomRole <customRoleKey> <customRoleName> <customRolePolicyArray> [customRoleDescription]`)
        .description('create custom role')
        .action((customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) => {
            customRolePolicyArray = JSON.parse(customRolePolicyArray);
            ldUtils.roles
                .createCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command(`updateCustomRole <customRoleKey> <customRoleName> <customRolePolicyArray> [customRoleDescription]`)
        .description('update custom role')
        .action((customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) => {
            customRolePolicyArray = JSON.parse(customRolePolicyArray);
            ldUtils.roles
                .updateCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command(`upsertCustomRole <customRoleKey> <customRoleName> <customRolePolicyArray> [customRoleDescription]`)
        .description('create or update custom role')
        .action((customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription) => {
            customRolePolicyArray = JSON.parse(customRolePolicyArray);
            ldUtils.roles
                .upsertCustomRole(customRoleKey, customRoleName, customRolePolicyArray, customRoleDescription)
                .then(response => {
                    console.log(json.plain(response));
                });
        });

    program
        .command('bulkUpsertCustomRoles <roleBulkLoadFile>')
        .description('path to a file containing array of role json')
        .action(roleBulkLoadFile => {
            ldUtils.roles.bulkUpsertCustomRoles(roleBulkLoadFile).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('bulkUpsertCustomRoleFolder <roleFolder>')
        .description('path to a directory containing multiple files of role json')
        .action(roleFolder => {
            ldUtils.roles.bulkUpsertCustomRoleFolder(roleFolder).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('inviteTeamMember <emailAddress> <initialRoleName>')
        .description('Invite a New Team Member')
        .action((emailAddress, initialRoleName) => {
            ldUtils.members.inviteTeamMember(emailAddress, initialRoleName).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getTeamMembers [limit] [offset] [filter]')
        .description('list all team members in account')
        .action((limit, offset, filter) => {
            ldUtils.members.getTeamMembers(limit, offset, filter).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getTeamMember <memberId>')
        .description('get a team member by id')
        .action(memberId => {
            ldUtils.members.getTeamMember(memberId).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getTeamMemberByEmail <emailAddress>')
        .description('get a team member by email address')
        .action(emailAddress => {
            ldUtils.members.getTeamMemberByEmail(emailAddress).then(response => {
                console.log(json.plain(response));
            });
        });

    program
        .command('getTeamMemberCustomRoles <emailAddress>')
        .description('get a team members custom roles by email address')
        .action(emailAddress => {
            ldUtils.members.getTeamMemberCustomRoles(emailAddress).then(response => {
                console.log(json.plain(response));
            });
        });

    program.on('--help', () => {
        console.log('\n  See https://github.com/zotoio/launchdarkly-nodeutils/API.md for examples.\n');
    });

    if (process.argv.length < 3) {
        program.help();
        process.exit(1);
    }

    program.parse(process.argv);
});