import * as plugins from '../../plugins.js';
import type { OpsServer } from '../classes.opsserver.js';
import * as interfaces from '../../../ts_interfaces/index.js';
import { requireAdminIdentity } from '../helpers/guards.js';
import type { TPlatformServiceType } from '../../types.js';

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

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

  private getPlatformServicePort(type: TPlatformServiceType): number {
    const ports: Record<TPlatformServiceType, number> = {
      mongodb: 27017,
      minio: 9000,
      smartstorage: 9000,
      valkey: 6379,
      postgresql: 5432,
      rabbitmq: 5672,
      coretraffic: 80,
      clickhouse: 8123,
      mariadb: 3306,
    };
    return ports[type] || 0;
  }

  private registerHandlers(): void {
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetNetworkTargets>(
        'getNetworkTargets',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const targets: interfaces.data.INetworkTarget[] = [];

          // Services
          const services = await this.opsServerRef.oneboxRef.services.listServices();
          for (const svc of services) {
            targets.push({
              type: 'service',
              name: svc.name,
              domain: svc.domain || null,
              targetHost: (svc as any).containerIP || svc.containerID || 'unknown',
              targetPort: svc.port || 80,
              status: svc.status,
            });
          }

          // Registry
          const registryStatus = this.opsServerRef.oneboxRef.registry.getStatus();
          if (registryStatus.running) {
            targets.push({
              type: 'registry',
              name: 'onebox-registry',
              domain: null,
              targetHost: 'localhost',
              targetPort: registryStatus.port,
              status: 'running',
            });
          }

          // Platform services
          const platformServices = await this.opsServerRef.oneboxRef.platformServices.getAllPlatformServices();
          for (const ps of platformServices) {
            const provider = this.opsServerRef.oneboxRef.platformServices.getProvider(ps.type);
            targets.push({
              type: 'platform',
              name: provider?.displayName || ps.type,
              domain: null,
              targetHost: 'localhost',
              targetPort: this.getPlatformServicePort(ps.type),
              status: ps.status,
            });
          }

          return { targets };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetNetworkStats>(
        'getNetworkStats',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const proxyStatus = await this.opsServerRef.oneboxRef.reverseProxy.observeStatus();
          const logReceiverStats = this.opsServerRef.oneboxRef.proxyLogReceiver.getStats();

          return {
            stats: {
              proxy: {
                state: proxyStatus.state,
                running: proxyStatus.running,
                observedAt: proxyStatus.observedAt,
                httpPort: proxyStatus.http.port,
                httpsPort: proxyStatus.https.port,
                routes: proxyStatus.routes,
                certificates: proxyStatus.https.certificates,
              },
              logReceiver: {
                running: logReceiverStats.running,
                port: logReceiverStats.port,
                clients: logReceiverStats.clients,
                connections: logReceiverStats.connections,
                sampleRate: logReceiverStats.sampleRate,
                recentLogsCount: logReceiverStats.recentLogsCount,
              },
            },
          };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetTrafficStats>(
        'getTrafficStats',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const trafficStats = this.opsServerRef.oneboxRef.proxyLogReceiver.getTrafficStats(60);
          return { stats: trafficStats };
        },
      ),
    );
  }
}
