import type DcRouter from '../classes.dcrouter.js';
import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import * as handlers from './handlers/index.js';
import * as interfaces from '../../ts_interfaces/index.js';

export class OpsServer {
  public dcRouterRef: DcRouter;
  public server!: plugins.typedserver.utilityservers.UtilityWebsiteServer;

  // Main TypedRouter — unauthenticated endpoints (login/logout/verify) and own-auth handlers
  public typedrouter = new plugins.typedrequest.TypedRouter();

  // Grouped routers. Handlers enforce auth explicitly with per-endpoint scopes.
  public viewRouter = new plugins.typedrequest.TypedRouter<{ request: { identity?: interfaces.data.IIdentity; apiToken?: string } }>();
  public adminRouter = new plugins.typedrequest.TypedRouter<{ request: { identity?: interfaces.data.IIdentity; apiToken?: string } }>();

  // Handler instances
  public adminHandler!: handlers.AdminHandler;
  private configHandler!: handlers.ConfigHandler;
  private logsHandler!: handlers.LogsHandler;
  private securityHandler!: handlers.SecurityHandler;
  private statsHandler!: handlers.StatsHandler;
  private radiusHandler!: handlers.RadiusHandler;
  private emailOpsHandler!: handlers.EmailOpsHandler;
  private emailSettingsHandler!: handlers.EmailSettingsHandler;
  private certificateHandler!: handlers.CertificateHandler;
  private remoteIngressHandler!: handlers.RemoteIngressHandler;
  private routeManagementHandler!: handlers.RouteManagementHandler;
  private apiTokenHandler!: handlers.ApiTokenHandler;
  private vpnHandler!: handlers.VpnHandler;
  private sourceProfileHandler!: handlers.SourceProfileHandler;
  private targetProfileHandler!: handlers.TargetProfileHandler;
  private networkTargetHandler!: handlers.NetworkTargetHandler;
  private usersHandler!: handlers.UsersHandler;
  private dnsProviderHandler!: handlers.DnsProviderHandler;
  private domainHandler!: handlers.DomainHandler;
  private dnsRecordHandler!: handlers.DnsRecordHandler;
  private acmeConfigHandler!: handlers.AcmeConfigHandler;
  private emailDomainHandler!: handlers.EmailDomainHandler;
  private workHosterHandler!: handlers.WorkHosterHandler;

  constructor(dcRouterRefArg: DcRouter) {
    this.dcRouterRef = dcRouterRefArg;

    // Add our typedrouter to the dcRouter's main typedrouter
    this.dcRouterRef.typedrouter.addTypedRouter(this.typedrouter);
  }

  public async start() {
    this.server = new plugins.typedserver.utilityservers.UtilityWebsiteServer({
      domain: 'localhost',
      feedMetadata: undefined,
      serveDir: paths.distServe,
    });
    
    // The server has a built-in typedrouter at /typedrequest
    // Add the main dcRouter typedrouter to the server's typedrouter
    this.server.typedrouter.addTypedRouter(this.dcRouterRef.typedrouter);
    
    // Set up handlers
    await this.setupHandlers();

    await this.server.start(this.dcRouterRef.options.opsServerPort ?? 3000);
  }
  
  /**
   * Set up all TypedRequest handlers
   */
  private async setupHandlers(): Promise<void> {
    // AdminHandler must be initialized first (JWT setup needed for guards)
    this.adminHandler = new handlers.AdminHandler(this);
    await this.adminHandler.initialize();

    // Connect auth routers to the main typedrouter
    this.typedrouter.addTypedRouter(this.viewRouter);
    this.typedrouter.addTypedRouter(this.adminRouter);

    // Instantiate all handlers — they self-register with the appropriate router
    this.configHandler = new handlers.ConfigHandler(this);
    this.logsHandler = new handlers.LogsHandler(this);
    this.securityHandler = new handlers.SecurityHandler(this);
    this.statsHandler = new handlers.StatsHandler(this);
    this.radiusHandler = new handlers.RadiusHandler(this);
    this.emailOpsHandler = new handlers.EmailOpsHandler(this);
    this.emailSettingsHandler = new handlers.EmailSettingsHandler(this);
    this.certificateHandler = new handlers.CertificateHandler(this);
    this.remoteIngressHandler = new handlers.RemoteIngressHandler(this);
    this.routeManagementHandler = new handlers.RouteManagementHandler(this);
    this.apiTokenHandler = new handlers.ApiTokenHandler(this);
    this.vpnHandler = new handlers.VpnHandler(this);
    this.sourceProfileHandler = new handlers.SourceProfileHandler(this);
    this.targetProfileHandler = new handlers.TargetProfileHandler(this);
    this.networkTargetHandler = new handlers.NetworkTargetHandler(this);
    this.usersHandler = new handlers.UsersHandler(this);
    this.dnsProviderHandler = new handlers.DnsProviderHandler(this);
    this.domainHandler = new handlers.DomainHandler(this);
    this.dnsRecordHandler = new handlers.DnsRecordHandler(this);
    this.acmeConfigHandler = new handlers.AcmeConfigHandler(this);
    this.emailDomainHandler = new handlers.EmailDomainHandler(this);
    this.workHosterHandler = new handlers.WorkHosterHandler(this);

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

  public async stop() {
    if (this.adminHandler) {
      await this.adminHandler.stop();
    }
    // Clean up log handler streams and push destination before stopping the server
    if (this.logsHandler) {
      this.logsHandler.cleanup();
    }
    if (this.server) {
      await this.server.stop();
    }
  }
}
