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

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

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

  private registerHandlers(): void {
    // Get all platform services
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetPlatformServices>(
        'getPlatformServices',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const platformServices = this.opsServerRef.oneboxRef.platformServices.getAllPlatformServices();
          const providers = this.opsServerRef.oneboxRef.platformServices.getAllProviders();

          const result = providers.map((provider: any) => {
            const service = platformServices.find((s: any) => s.type === provider.type);
            const isCore = 'isCore' in provider && (provider as any).isCore === true;

            let status: string = service?.status || 'not-deployed';
            if (provider.type === 'caddy') {
              const proxyStatus = this.opsServerRef.oneboxRef.reverseProxy.getStatus() as any;
              status = (proxyStatus.running ?? proxyStatus.http?.running) ? 'running' : 'stopped';
            }

            return {
              type: provider.type,
              displayName: provider.displayName,
              resourceTypes: provider.resourceTypes,
              status: status as interfaces.data.TPlatformServiceStatus,
              containerId: service?.containerId,
              isCore,
              createdAt: service?.createdAt,
              updatedAt: service?.updatedAt,
            };
          });

          return { platformServices: result as interfaces.data.IPlatformService[] };
        },
      ),
    );

    // Get specific platform service
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetPlatformService>(
        'getPlatformService',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.oneboxRef.platformServices.getProvider(dataArg.serviceType);
          if (!provider) {
            throw new plugins.typedrequest.TypedResponseError(`Unknown platform service type: ${dataArg.serviceType}`);
          }

          const service = this.opsServerRef.oneboxRef.database.getPlatformServiceByType(dataArg.serviceType);
          const isCore = 'isCore' in provider && (provider as any).isCore === true;

          let rawStatus: string = service?.status || 'not-deployed';
          if (dataArg.serviceType === 'caddy') {
            const proxyStatus = this.opsServerRef.oneboxRef.reverseProxy.getStatus() as any;
            rawStatus = (proxyStatus.running ?? proxyStatus.http?.running) ? 'running' : 'stopped';
          }

          return {
            platformService: {
              type: provider.type,
              displayName: provider.displayName,
              resourceTypes: provider.resourceTypes,
              status: rawStatus as interfaces.data.TPlatformServiceStatus,
              containerId: service?.containerId,
              isCore,
              createdAt: service?.createdAt,
              updatedAt: service?.updatedAt,
            } as interfaces.data.IPlatformService,
          };
        },
      ),
    );

    // Start platform service
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_StartPlatformService>(
        'startPlatformService',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.oneboxRef.platformServices.getProvider(dataArg.serviceType);
          if (!provider) {
            throw new plugins.typedrequest.TypedResponseError(`Unknown platform service type: ${dataArg.serviceType}`);
          }

          logger.info(`Starting platform service: ${dataArg.serviceType}`);
          const service = await this.opsServerRef.oneboxRef.platformServices.ensureRunning(dataArg.serviceType);

          return {
            platformService: {
              type: service.type,
              displayName: provider.displayName,
              resourceTypes: provider.resourceTypes,
              status: service.status,
              containerId: service.containerId,
            },
          };
        },
      ),
    );

    // Stop platform service
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_StopPlatformService>(
        'stopPlatformService',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const provider = this.opsServerRef.oneboxRef.platformServices.getProvider(dataArg.serviceType);
          if (!provider) {
            throw new plugins.typedrequest.TypedResponseError(`Unknown platform service type: ${dataArg.serviceType}`);
          }

          const isCore = 'isCore' in provider && (provider as any).isCore === true;
          if (isCore) {
            throw new plugins.typedrequest.TypedResponseError(
              `${provider.displayName} is a core service and cannot be stopped`,
            );
          }

          logger.info(`Stopping platform service: ${dataArg.serviceType}`);
          await this.opsServerRef.oneboxRef.platformServices.stopPlatformService(dataArg.serviceType);

          return {
            platformService: {
              type: dataArg.serviceType,
              displayName: provider.displayName,
              resourceTypes: provider.resourceTypes,
              status: 'stopped' as const,
            },
          };
        },
      ),
    );

    // Get platform service stats
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetPlatformServiceStats>(
        'getPlatformServiceStats',
        async (dataArg) => {
          await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
          const service = this.opsServerRef.oneboxRef.database.getPlatformServiceByType(dataArg.serviceType);
          if (!service || !service.containerId) {
            throw new plugins.typedrequest.TypedResponseError('Platform service has no container');
          }

          const stats = await this.opsServerRef.oneboxRef.docker.getContainerStats(service.containerId);
          if (!stats) {
            throw new plugins.typedrequest.TypedResponseError('Could not retrieve container stats');
          }

          return { stats };
        },
      ),
    );
  }
}
