import * as plugins from '../plugins.ts';
import { logger } from '../logging.ts';
import type { GitopsApp } from '../classes/gitopsapp.ts';
import * as handlers from './handlers/index.ts';
import { files as bundledFiles } from '../../ts_bundled/bundle.ts';

export class OpsServer {
  public gitopsAppRef: GitopsApp;
  public typedrouter = new plugins.typedrequest.TypedRouter();
  public server!: plugins.typedserver.utilityservers.UtilityWebsiteServer;

  // Handler instances
  public adminHandler!: handlers.AdminHandler;
  public connectionsHandler!: handlers.ConnectionsHandler;
  public projectsHandler!: handlers.ProjectsHandler;
  public groupsHandler!: handlers.GroupsHandler;
  public secretsHandler!: handlers.SecretsHandler;
  public pipelinesHandler!: handlers.PipelinesHandler;
  public logsHandler!: handlers.LogsHandler;
  public webhookHandler!: handlers.WebhookHandler;
  public actionsHandler!: handlers.ActionsHandler;
  public actionLogHandler!: handlers.ActionLogHandler;
  public syncHandler!: handlers.SyncHandler;
  public managedSecretsHandler!: handlers.ManagedSecretsHandler;

  constructor(gitopsAppRef: GitopsApp) {
    this.gitopsAppRef = gitopsAppRef;
  }

  public async start(port = 3000) {
    // Create webhook handler before server so routes register via addCustomRoutes
    this.webhookHandler = new handlers.WebhookHandler(this);

    this.server = new plugins.typedserver.utilityservers.UtilityWebsiteServer({
      domain: 'localhost',
      feedMetadata: undefined,
      bundledContent: bundledFiles,
      noCache: true,
      addCustomRoutes: async (typedserver) => {
        this.webhookHandler.registerRoutes(typedserver);
      },
    });

    // Chain typedrouters
    this.server.typedrouter.addTypedRouter(this.typedrouter);

    // Set up all handlers
    await this.setupHandlers();

    await this.server.start(port);
    logger.success(`OpsServer started on http://localhost:${port}`);
  }

  private async setupHandlers(): Promise<void> {
    // AdminHandler requires async initialization for JWT key generation
    this.adminHandler = new handlers.AdminHandler(this);
    await this.adminHandler.initialize();

    // All other handlers self-register in their constructors
    this.connectionsHandler = new handlers.ConnectionsHandler(this);
    this.projectsHandler = new handlers.ProjectsHandler(this);
    this.groupsHandler = new handlers.GroupsHandler(this);
    this.secretsHandler = new handlers.SecretsHandler(this);
    this.pipelinesHandler = new handlers.PipelinesHandler(this);
    this.logsHandler = new handlers.LogsHandler(this);
    this.actionsHandler = new handlers.ActionsHandler(this);
    this.actionLogHandler = new handlers.ActionLogHandler(this);
    this.syncHandler = new handlers.SyncHandler(this);
    this.managedSecretsHandler = new handlers.ManagedSecretsHandler(this);

    logger.success('OpsServer TypedRequest handlers initialized');
  }

  public async stop() {
    if (this.server) {
      await this.server.stop();
      logger.success('OpsServer stopped');
    }
  }
}
