// tslint:disable:no-console
import { CognitoIdentityProvider, ListUserPoolClientsCommandOutput, UserPoolClientDescription } from '@aws-sdk/client-cognito-identity-provider';
import { fromEnv } from '@aws-sdk/credential-providers';
import * as mongoose from 'mongoose';

import { chevre } from '../../../../lib/index';

const USERPOOL_PROVIDER_NAME = (typeof process.env.DISCONTINUE_PEOPLE_USERPOOL_PROVIDER_NAME === 'string')
    ? process.env.DISCONTINUE_PEOPLE_USERPOOL_PROVIDER_NAME
    : 'SSKTS';

// tslint:disable-next-line:max-func-body-length
async function main(): Promise<void> {
    await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });

    const settingRepo = await chevre.repository.Setting.createInstance(mongoose.connection);
    const setting = await settingRepo.findOne({ project: { id: { $eq: '*' } } }, ['userPoolIdNew']);
    if (typeof setting?.userPoolIdNew !== 'string') {
        throw new chevre.factory.errors.NotFound('setting.userPoolIdNew');
    }
    const userPoolId: string = setting.userPoolIdNew;

    const awsCredentials = fromEnv();
    const cognitoIdentityServiceProvider = new CognitoIdentityProvider({
        apiVersion: 'latest',
        region: 'ap-northeast-1',
        credentials: awsCredentials
    });

    // create user
    const newPersonRepo = await chevre.repository.Person.createInstance({
        userPoolId: userPoolId,
        cognitoIdentityServiceProvider
    });

    const clients: UserPoolClientDescription[] = [];
    let nextToken: string | undefined = '';
    let page: number = 0;
    while (typeof nextToken === 'string') {
        // tslint:disable-next-line:no-magic-numbers
        if (page > 1) {
            break;
        }

        page += 1;
        console.log('listUserPoolClients processing...', nextToken, page);
        const listUserPoolClientsResult =
            <ListUserPoolClientsCommandOutput>await newPersonRepo.cognitoIdentityServiceProvider.listUserPoolClients(
                {
                    MaxResults: 50,
                    UserPoolId: userPoolId,
                    ...(typeof nextToken === 'string' && nextToken !== '') ? { NextToken: nextToken } : undefined
                }
            );
        // tslint:disable-next-line:no-null-keyword
        console.dir(listUserPoolClientsResult.UserPoolClients?.at(0), { depth: null });
        nextToken = listUserPoolClientsResult.NextToken;
        if (Array.isArray(listUserPoolClientsResult.UserPoolClients)) {
            clients.push(...listUserPoolClientsResult.UserPoolClients);
        }
    }
    console.log('listUsersInGroup processed', nextToken, page);
    console.log(clients.length, 'users found');

    let i = 0;
    let providerSupportedCount = 0;
    for (const client of clients) {
        i += 1;

        const ClientId = client.ClientId;

        // disable link provider
        const describeUserPoolClientResult = await newPersonRepo.cognitoIdentityServiceProvider.describeUserPoolClient({
            UserPoolId: userPoolId,
            ClientId
        });
        const codeFlowAllowed = describeUserPoolClientResult.UserPoolClient?.AllowedOAuthFlows?.some(
            (flow) => flow !== 'client_credentials'
        );
        if (codeFlowAllowed) {
            const providerSupported = describeUserPoolClientResult.UserPoolClient?.SupportedIdentityProviders?.some(
                (provider) => provider === USERPOOL_PROVIDER_NAME
            );
            if (providerSupported) {
                providerSupportedCount += 1;
                console.log(
                    'describeUserPoolClientResult:',
                    describeUserPoolClientResult.UserPoolClient?.AllowedOAuthFlows,
                    describeUserPoolClientResult.UserPoolClient?.AllowedOAuthScopes,
                    describeUserPoolClientResult.UserPoolClient?.SupportedIdentityProviders,
                    describeUserPoolClientResult.UserPoolClient?.ClientName,
                    ClientId, i
                );
            } else {
                console.log(
                    'describeUserPoolClientResult:',
                    describeUserPoolClientResult.UserPoolClient?.AllowedOAuthFlows,
                    describeUserPoolClientResult.UserPoolClient?.AllowedOAuthScopes,
                    describeUserPoolClientResult.UserPoolClient?.SupportedIdentityProviders,
                    describeUserPoolClientResult.UserPoolClient?.ClientName,
                    ClientId, i
                );
            }
        } else {
            console.log(
                'describeUserPoolClientResult:',
                describeUserPoolClientResult.UserPoolClient?.AllowedOAuthFlows,
                describeUserPoolClientResult.UserPoolClient?.ClientName,
                ClientId, i
            );
        }
    }

    console.log(clients.length, 'clients processed');
    console.log(providerSupportedCount, 'clients supported');
}

main()
    .then()
    .catch(console.error);
