// tslint:disable:no-console
import { CognitoIdentityProvider } from '@aws-sdk/client-cognito-identity-provider';
// tslint:disable-next-line:no-submodule-imports
import type { UserPoolClientType } from '@aws-sdk/client-cognito-identity-provider/dist-types/models/models_0';
import { fromEnv } from '@aws-sdk/credential-providers';
import * as fs from 'fs';
// tslint:disable-next-line:no-implicit-dependencies
import * as json2csv from 'json2csv';
import * as mongoose from 'mongoose';

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

// const project = { id: String(process.env.PROJECT_ID) };
// const excludedProject = { id: String(process.env.EXCLUDED_PROJECT_ID) };
const userPoolId = `${process.env.COGNITO_USER_POOL_ID}`;

// tslint:disable-next-line:max-func-body-length
async function main() {
    const awsCredentials = fromEnv();
    const cognitoIdentityServiceProvider = new CognitoIdentityProvider({
        apiVersion: 'latest',
        region: 'ap-northeast-1',
        credentials: awsCredentials
    });

    await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });

    const memberRepo = await chevre.repository.Member.createInstance(mongoose.connection);

    const cursor = memberRepo.getCursor(
        {
            'project.id': { $eq: '*' }
            // _id: { $eq: '67de46777ec0510590b68922' }
        },
        {
            _id: 1,
            member: 1,
            project: 1,
            typeOf: 1
        }
    );
    console.log('docs found');

    let i = 0;
    // let commonClients: {
    //     clientId?: string;
    //     clientSecret?: string;
    //     name?: string;
    // }[] = [];
    const commonClients: {
        projectId: string;
        clientId: string;
        clientSecret: string;
        name: string;
        memberName: string;
    }[] = [];
    // tslint:disable-next-line:max-func-body-length
    await cursor.eachAsync(async (doc) => {
        i += 1;
        const member: Pick<
            chevre.factory.iam.IMember,
            'member' | 'project' | 'typeOf'
        > = doc.toObject();

        const client = await new Promise<UserPoolClientType>(async (resolve, reject) => {
            cognitoIdentityServiceProvider.describeUserPoolClient(
                {
                    ClientId: member.member.id,
                    UserPoolId: userPoolId
                },
                {},
                (err, data) => {
                    if (err instanceof Error) {
                        reject(err);
                    } else {
                        if (data?.UserPoolClient === undefined) {
                            reject(new chevre.factory.errors.NotFound('UserPoolClient'));
                        } else {
                            resolve(data.UserPoolClient);
                        }
                    }
                }
            );
        });

        if (typeof client.ClientId !== 'string'
            || typeof client.ClientSecret !== 'string'
            || typeof client.ClientName !== 'string') {
            throw new Error('invalid client');
        }

        const allowClientCredentials = client.AllowedOAuthFlows?.includes('client_credentials') === true;
        if (allowClientCredentials) {
            commonClients.push({
                projectId: member.project.id,
                clientId: client.ClientId,
                clientSecret: client.ClientSecret,
                name: client.ClientName,
                memberName: String(member.member.name)
            });
        }
    });

    console.log(commonClients);

    // tslint:disable-next-line:no-null-keyword
    const json = JSON.stringify(commonClients, null, '');
    // tslint:disable-next-line:non-literal-fs-path
    fs.writeFileSync(`${__dirname}/../../../commonClients.json`, json);
    console.log(i, 'docs checked');

    const parser = new json2csv.Parser({
        fields: ['projectId', 'clientId', 'clientSecret', 'name', 'memberName']
    });
    const csv = parser.parse(commonClients.sort(
        (a, b) => {
            return (String(a.name) > String(b.name)) ? 1 : -1;
        }
    ));
    // tslint:disable-next-line:non-literal-fs-path
    fs.writeFileSync(`${__dirname}/../../../commonClients.csv`, csv);
}

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