import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { SecretBundle } from './classes.secretbundle.js';
import { SecretGroup } from './classes.secretgroup.js';
import { logger } from '../logger.js';
import type { Cloudly } from '../classes.cloudly.js';

/**
 * The `ConfigVault` class provides methods for reading and writing configuration data to a file.
 * It uses the `TypedServer` and `TypedRouter` classes from the `configvault.plugins.js` module to handle HTTP requests and route them to the appropriate handlers.
 *
 * @class
 */
export class CloudlySecretManager {
  // attached classes
  public CSecretBundle = plugins.smartdata.setDefaultManagerForDoc(this, SecretBundle);
  public CSecretGroup = plugins.smartdata.setDefaultManagerForDoc(this, SecretGroup);

  // INSTANCE
  public cloudlyRef: Cloudly;
  public projectinfo = new plugins.projectinfo.ProjectinfoNpm(paths.packageDir);
  public serviceQenv = new plugins.qenv.Qenv(paths.packageDir, paths.nogitDir);
  public typedrouter: plugins.typedrequest.TypedRouter;

  get db() {
    return this.cloudlyRef.mongodbConnector.smartdataDb;
  }

  constructor(cloudlyRefArg: Cloudly) {
    this.cloudlyRef = cloudlyRefArg;
  }

  public async start() {
    // lets set up a typedrouter
    this.typedrouter = new plugins.typedrequest.TypedRouter();
    this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);

    // secretbundle routes
    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetSecretBundles>(
      new plugins.typedrequest.TypedHandler(
        'getSecretBundles',
        async (dataArg, toolsArg) => {
          await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
          dataArg.identity.jwt;
          const secretBundles = await SecretBundle.getInstances({});
          return {
            secretBundles: [
              ...(await Promise.all(
                secretBundles.map((configBundle) => configBundle.createSavableObject()),
              )),
            ],
          };
        },
      ),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_CreateSecretBundle>(
      new plugins.typedrequest.TypedHandler('createSecretBundle', async (dataArg) => {
        const secretBundle = new SecretBundle();
        secretBundle.id = plugins.smartunique.shortId(8);
        secretBundle.data = dataArg.secretBundle.data;
        await secretBundle.save();
        return {
          resultSecretBundle: await secretBundle.createSavableObject(),
        };
      }),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_UpdateSecretBundle>(
      new plugins.typedrequest.TypedHandler('updateSecretBundle', async (dataArg) => {
        const secretBundle = await SecretBundle.getInstance({
          id: dataArg.secretBundle.id,
        });
        secretBundle.data = dataArg.secretBundle.data;
        await secretBundle.save();
        return {
          resultSecretBundle: await secretBundle.createSavableObject(),
        };
      }),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_DeleteSecretBundleById>(
      new plugins.typedrequest.TypedHandler('deleteSecretBundleById', async (dataArg) => {
        const secretBundle = await SecretBundle.getInstance({
          id: dataArg.secretBundleId,
        });
        await secretBundle.delete();
        return {
          ok: true,
        };
      }),
    );

    // secretgroup routes
    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_GetSecretGroups>(
      new plugins.typedrequest.TypedHandler(
        'getSecretGroups',
        async (dataArg, toolsArg) => {
          await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
          dataArg.identity.jwt;
          const secretGroups = await SecretGroup.getInstances({});
          return {
            secretGroups: [
              ...(await Promise.all(
                secretGroups.map((secretGroup) => secretGroup.createSavableObject()),
              )),
            ],
          };
        },
      ),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_CreateSecretGroup>(
      new plugins.typedrequest.TypedHandler('createSecretGroup', async (dataArg) => {
        const secretGroup = new SecretGroup();
        secretGroup.id = plugins.smartunique.shortId(8);
        secretGroup.data = dataArg.secretGroup.data;
        await secretGroup.save();
        return {
          resultSecretGroup: await secretGroup.createSavableObject(),
        };
      }),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_UpdateSecretGroup>(
      new plugins.typedrequest.TypedHandler('updateSecretGroup', async (dataArg) => {
        const secretGroup = await SecretGroup.getInstance({
          id: dataArg.secretGroup.id,
        });
        secretGroup.data = dataArg.secretGroup.data;
        await secretGroup.save();
        return {
          resultSecretGroup: await secretGroup.createSavableObject(),
        };
      }),
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secretgroup.IReq_DeleteSecretGroupById>(
      new plugins.typedrequest.TypedHandler('deleteSecretGroupById', async (dataArg) => {
        const secretGroup = await SecretGroup.getInstance({
          id: dataArg.secretGroupId,
        });
        await secretGroup.delete();
        return {
          ok: true,
        };
      }),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secretbundle.IReq_GetFlatKeyValueObject>(
        'getFlatKeyValueObject',
        async (dataArg) => {
          const wantedBundle = await SecretBundle.getInstance({
            data: {
              authorizations: {
                // @ts-ignore
                $elemMatch: {
                  secretAccessKey: dataArg.secretBundleAuthorization.secretAccessKey,
                },
              },
            },
          });
          const authorization = await wantedBundle.getAuthorizationFromAuthKey(
            dataArg.secretBundleAuthorization.secretAccessKey,
          );
          return {
            flatKeyValueObject:  await wantedBundle.getKeyValueObjectForEnvironment(
              authorization.environment,
            ),
          };
        },
      ),
    );
  }

  public async stop() {}
}