import * as plugins from '../plugins.ts';
import type { ObjectStorageContainer } from '../classes/objectstoragecontainer.ts';
import * as handlers from './handlers/index.ts';
import { files as bundledFiles } from '../../ts_bundled/bundle.ts';

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

  // Handler instances
  public adminHandler!: handlers.AdminHandler;
  public statusHandler!: handlers.StatusHandler;
  public bucketsHandler!: handlers.BucketsHandler;
  public objectsHandler!: handlers.ObjectsHandler;
  public configHandler!: handlers.ConfigHandler;
  public credentialsHandler!: handlers.CredentialsHandler;
  public policiesHandler!: handlers.PoliciesHandler;
  public auditHandler!: handlers.AuditHandler;

  constructor(objectStorageRef: ObjectStorageContainer) {
    this.objectStorageRef = objectStorageRef;
  }

  public async start(port = 3000) {
    this.server = new plugins.typedserver.utilityservers.UtilityWebsiteServer({
      domain: 'localhost',
      feedMetadata: undefined,
      bundledContent: bundledFiles,
      addCustomRoutes: async (typedserver) => {
        typedserver.addRoute('/livez', 'GET', async () => {
          return this.jsonResponse({ ok: true, status: 'alive' });
        });
        typedserver.addRoute('/readyz', 'GET', async () => {
          const ready = await this.objectStorageRef.isReady();
          return this.jsonResponse(
            { ok: ready, status: ready ? 'ready' : 'starting' },
            ready ? 200 : 503,
          );
        });
        typedserver.addRoute('/healthz', 'GET', async () => {
          return this.jsonResponse(await this.objectStorageRef.getOperationalHealth());
        });
        typedserver.addRoute('/metrics', 'GET', async () => {
          const metrics = await this.objectStorageRef.getOperationalMetrics();
          return new Response(metrics, {
            headers: { 'content-type': 'text/plain; version=0.0.4' },
          });
        });
      },
    });

    // Chain typedrouters: server -> opsServer -> individual handlers
    this.server.typedrouter.addTypedRouter(this.typedrouter);

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

    await this.server.start(port);
    console.log(`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.statusHandler = new handlers.StatusHandler(this);
    this.bucketsHandler = new handlers.BucketsHandler(this);
    this.objectsHandler = new handlers.ObjectsHandler(this);
    this.configHandler = new handlers.ConfigHandler(this);
    this.credentialsHandler = new handlers.CredentialsHandler(this);
    this.policiesHandler = new handlers.PoliciesHandler(this);
    this.auditHandler = new handlers.AuditHandler(this);

    console.log('OpsServer TypedRequest handlers initialized');
  }

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

  private jsonResponse(data: unknown, status = 200): Response {
    return new Response(JSON.stringify(data), {
      status,
      headers: { 'content-type': 'application/json' },
    });
  }
}
