import * as plugins from '../../plugins.ts';
import type { OpsServer } from '../classes.opsserver.ts';
import * as interfaces from '../../../ts_interfaces/index.ts';
import { requireValidIdentity } from '../helpers/guards.ts';

export class SecretsHandler {
  public typedrouter = new plugins.typedrequest.TypedRouter();

  constructor(private opsServerRef: OpsServer) {
    this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
    this.registerHandlers();
  }

  private registerHandlers(): void {
    // Get all secrets (bulk fetch across all entities)
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAllSecrets>(
        'getAllSecrets',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
            dataArg.connectionId,
          );

          const allSecrets: interfaces.data.ISecret[] = [];

          if (dataArg.scope === 'project') {
            const projects = await provider.getProjects();
            // Fetch in batches of 5 for performance
            for (let i = 0; i < projects.length; i += 5) {
              const batch = projects.slice(i, i + 5);
              const results = await Promise.allSettled(
                batch.map(async (p) => {
                  const secrets = await provider.getProjectSecrets(p.id);
                  return secrets.map((s) => ({ ...s, scopeName: p.fullPath || p.name }));
                }),
              );
              for (const result of results) {
                if (result.status === 'fulfilled') {
                  allSecrets.push(...result.value);
                }
              }
            }
          } else {
            const groups = await provider.getGroups();
            for (let i = 0; i < groups.length; i += 5) {
              const batch = groups.slice(i, i + 5);
              const results = await Promise.allSettled(
                batch.map(async (g) => {
                  const secrets = await provider.getGroupSecrets(g.id);
                  return secrets.map((s) => ({ ...s, scopeName: g.fullPath || g.name }));
                }),
              );
              for (const result of results) {
                if (result.status === 'fulfilled') {
                  allSecrets.push(...result.value);
                }
              }
            }
          }

          return { secrets: allSecrets };
        },
      ),
    );

    // Get secrets
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSecrets>(
        'getSecrets',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
            dataArg.connectionId,
          );
          const secrets = dataArg.scope === 'project'
            ? await provider.getProjectSecrets(dataArg.scopeId)
            : await provider.getGroupSecrets(dataArg.scopeId);
          return { secrets };
        },
      ),
    );

    // Create secret
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateSecret>(
        'createSecret',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
            dataArg.connectionId,
          );
          const secret = dataArg.scope === 'project'
            ? await provider.createProjectSecret(dataArg.scopeId, dataArg.key, dataArg.value)
            : await provider.createGroupSecret(dataArg.scopeId, dataArg.key, dataArg.value);
          return { secret };
        },
      ),
    );

    // Update secret
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSecret>(
        'updateSecret',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
            dataArg.connectionId,
          );
          const secret = dataArg.scope === 'project'
            ? await provider.updateProjectSecret(dataArg.scopeId, dataArg.key, dataArg.value)
            : await provider.updateGroupSecret(dataArg.scopeId, dataArg.key, dataArg.value);
          return { secret };
        },
      ),
    );

    // Delete secret
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteSecret>(
        'deleteSecret',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.gitopsAppRef.connectionManager.getProvider(
            dataArg.connectionId,
          );
          if (dataArg.scope === 'project') {
            await provider.deleteProjectSecret(dataArg.scopeId, dataArg.key);
          } else {
            await provider.deleteGroupSecret(dataArg.scopeId, dataArg.key);
          }
          return { ok: true };
        },
      ),
    );
  }
}
