/* eslint-disable no-console */
const _ = require('lodash');
const { argv } = require('yargs');
const QloudApi = require('qloud-api');
const stClient = require('st-client');
const RegistryApi = require('./clients/RegistryApi');

const PROJECT_NAME = 'workspace';
const APPLICATION_NAME = 'portal';

const PACKAGE_JSON_VERSION = require('../package.json').version;

const STAND_PREFIX = 'dir-';

const {
    /**
     * https://oauth.yandex-team.ru/authorize?response_type=token&client_id=75ce16e5643a43feb5d1b1d6f82c2e45
     */
    CONNECT_QLOUD_OAUTH_TOKEN,

    /**
     * https://oauth.yandex-team.ru/authorize?response_type=token&client_id=5f671d781aca402ab7460fde4050267b
     */
    CONNECT_TRACKER_OAUTH_TOKEN,
} = process.env;

const qloudApi = new QloudApi({
    token: CONNECT_QLOUD_OAUTH_TOKEN,
    host: 'https://platform.yandex-team.ru',
});

const registryApi = new RegistryApi({
    token: CONNECT_QLOUD_OAUTH_TOKEN,
    repo: 'workspace/portal',
});

const trackerApi = stClient.init({
    token: CONNECT_TRACKER_OAUTH_TOKEN,
});

// Таймаут в милисекундах, показывающий через какое время после закрытия тикета в трекере
// можно удалять стенд в Qloud
const CLEAR_ENV_TIMEOUT = 86400000;

async function removeDockerPackage(version) {
    try {
        await registryApi.remove(version);
    } catch (e) {
        console.error(`Не удалось удалить пакет ${version}`, e);
    }
}

async function removeEnv(branchName) {
    const envName = branchName.toLowerCase();
    const envId = `${PROJECT_NAME}.${APPLICATION_NAME}.${envName}`;
    let response;

    try {
        response = await qloudApi.deleteEnvironment(envId);
        console.log(`Запущено удаление окружения ${envName}`);
    } catch (e) {
        console.error(`Не удалось удалить окружение ${envName}`, e);
    }

    return response;
}

async function clearUnusedStands(application = APPLICATION_NAME) {
    const { applications } = await qloudApi.getProject(PROJECT_NAME);
    const { environments } = _.find(applications, { objectId: `${PROJECT_NAME}.${application}` });

    for (const { name: envName } of environments) {
        if (!envName.startsWith(STAND_PREFIX)) {
            continue;
        }

        try {
            const { status: { key: statusKey }, resolvedAt } = await trackerApi.getIssue(envName);

            if (statusKey === 'closed' && Date.now() - (new Date(resolvedAt)).getTime() > CLEAR_ENV_TIMEOUT) {
                await removeEnv(envName);

                if (application === APPLICATION_NAME) {
                    await removeDockerPackage(envName.toUpperCase());
                }
            }
        } catch (e) {
            console.error(`Не удалось получить данные о задаче ${envName}`);
        }
    }
}

async function clearUnusedPackages(application = APPLICATION_NAME) {
    const tags = await registryApi.getPackages();
    const { applications } = await qloudApi.getProject(PROJECT_NAME);
    const { environments } = _.find(applications, { objectId: `${PROJECT_NAME}.${application}` });

    const installedPackages = new Set();

    for (const { name: envName } of environments) {
        if (envName.startsWith(STAND_PREFIX)) {
            installedPackages.add(envName.toUpperCase());
            continue;
        }

        try {
            const envId = `${PROJECT_NAME}.${application}.${envName}`;
            const { components: { back: { repository } } } = await qloudApi.getStableEnvironment(envId);
            const [, repoVersion] = repository.split(':');

            installedPackages.add(repoVersion);
        } catch (e) {
            console.error(`Не удалось получить данные из окружения ${envName}`, e);
        }
    }

    const [currentMajor, currentMinor] = PACKAGE_JSON_VERSION.split('.').slice(0, 2).map(Number);

    for (const tag of tags) {
        const [major, minor] = tag.split('.').slice(0, 2).map(Number);

        if (installedPackages.has(tag) ||
            // если не стенд и версия пакета больше или ровна <major>.<minor-1>.0
            (!tag.startsWith(STAND_PREFIX.toUpperCase()) && major === currentMajor && minor > currentMinor - 2)) {
            continue;
        }

        console.log(`Удаление пакета ${tag}`);
        await removeDockerPackage(tag);
    }
}

(async() => {
    if (argv.r && argv['qloud-env']) {
        await removeEnv(argv['qloud-env']);
    }

    if (argv.r && argv['package-version']) {
        await removeDockerPackage(argv['package-version']);
    }

    if (argv['clear-unused-stands']) {
        await clearUnusedStands(argv.project);
    }

    if (argv['clear-unused-packages']) {
        await clearUnusedPackages(argv.project);
    }
})();
