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);

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_GetConfigBundlesAndSecretGroups>(
        'adminGetConfigBundlesAndSecretGroups',
        async (dataArg, toolsArg) => {
          await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], dataArg);
          dataArg.identity.jwt
          const secretBundles = await SecretBundle.getInstances({});
          const secretGroups = await SecretGroup.getInstances({});
          return {
            secretBundles: [
              ...(await Promise.all(
                secretBundles.map((configBundle) => configBundle.createSavableObject())
              )),
            ],
            secretGroups: [
              ...(await Promise.all(
                secretGroups.map((secretGroup) => secretGroup.createSavableObject())
              )),
            ],
          };
        }
      )
    );

    this.typedrouter.addTypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_CreateConfigBundlesAndSecretGroups>(
      new plugins.typedrequest.TypedHandler(
        'adminCreateConfigBundlesAndSecretGroups',
        async (dataArg) => {
          for (const secretGroupObject of dataArg.secretGroups) {
            const secretGroup = new SecretGroup();
            secretGroup.id = plugins.smartunique.shortId(8);
            secretGroup.data = secretGroupObject.data;
            await secretGroup.save();
          }
          return {
            ok: true,
          };
        }
      )
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_Admin_DeleteConfigBundlesAndSecretGroups>(
        'adminDeleteConfigBundlesAndSecretGroups',
        async (dataArg) => {
          for (const secretGroupId of dataArg.secretGroupIds) {
            const secretGroup = await SecretGroup.getInstance({
              id: secretGroupId,
            });
            await secretGroup.delete();
          }
          for (const secretBundleId of dataArg.secretBundleIds) {
            const configBundle = await SecretBundle.getInstance({
              id: secretBundleId,
            });
            await configBundle.delete();
            console.log(`deleted configbundle ${secretBundleId}`);
          }
          return {
            ok: true,
          };
        }
      )
    );

    // lets add typedrouter routes for accessing the configvailt from apps
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.secret.IReq_GetEnvBundle>(
        'getEnvBundle',
        async (dataArg) => {
          const wantedBundle = await SecretBundle.getInstance({
            data: {
              authorizations: {
                // @ts-ignore
                $elemMatch: {
                  secretAccessKey: dataArg.authorization,
                },
              },
            },
          });
          const authorization = await wantedBundle.getAuthorizationFromAuthKey(
            dataArg.authorization
          );
          return {
            envBundle: {
              configKeyValueObject: await wantedBundle.getKeyValueObjectForEnvironment(
                authorization.environment
              ),
              environment: authorization.environment,
              timeSensitive: false,
            },
          };
        }
      )
    );
  }

  public async stop() {}
}