import * as plugins from '../../plugins.js';
import type { OpsServer } from '../classes.opsserver.js';
import * as interfaces from '../../../ts_interfaces/index.js';
import { requireOpsAuth } from '../helpers/auth.js';

export class ApiTokenHandler {
  constructor(private opsServerRef: OpsServer) {
    this.registerHandlers();
  }

  private registerHandlers(): void {
    // All token management endpoints register directly on adminRouter
    // (middleware enforces admin JWT check, so no per-handler requireAdmin needed)
    const router = this.opsServerRef.adminRouter;

    // Create API token
    router.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateApiToken>(
        'createApiToken',
        async (dataArg) => {
          const auth = await requireOpsAuth(this.opsServerRef, dataArg, {
            scope: 'tokens:manage',
            requireAdminIdentity: true,
            requireAdminToken: true,
          });
          const manager = this.opsServerRef.dcRouterRef.apiTokenManager;
          if (!manager) {
            return { success: false, message: 'Token management not initialized' };
          }
          const result = await manager.createToken(
            dataArg.name,
            dataArg.scopes,
            dataArg.expiresInDays ?? null,
            auth.userId,
            dataArg.policy,
          );
          return { success: true, tokenId: result.id, tokenValue: result.rawToken };
        },
      ),
    );

    // List API tokens
    router.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ListApiTokens>(
        'listApiTokens',
        async (dataArg) => {
          await requireOpsAuth(this.opsServerRef, dataArg, {
            scope: 'tokens:read',
            requireAdminIdentity: true,
            requireAdminToken: true,
          });
          const manager = this.opsServerRef.dcRouterRef.apiTokenManager;
          if (!manager) {
            return { tokens: [] };
          }
          return { tokens: manager.listTokens() };
        },
      ),
    );

    // Revoke API token
    router.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RevokeApiToken>(
        'revokeApiToken',
        async (dataArg) => {
          await requireOpsAuth(this.opsServerRef, dataArg, {
            scope: 'tokens:manage',
            requireAdminIdentity: true,
            requireAdminToken: true,
          });
          const manager = this.opsServerRef.dcRouterRef.apiTokenManager;
          if (!manager) {
            return { success: false, message: 'Token management not initialized' };
          }
          const ok = await manager.revokeToken(dataArg.id);
          return { success: ok, message: ok ? undefined : 'Token not found' };
        },
      ),
    );

    // Roll API token
    router.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RollApiToken>(
        'rollApiToken',
        async (dataArg) => {
          await requireOpsAuth(this.opsServerRef, dataArg, {
            scope: 'tokens:manage',
            requireAdminIdentity: true,
            requireAdminToken: true,
          });
          const manager = this.opsServerRef.dcRouterRef.apiTokenManager;
          if (!manager) {
            return { success: false, message: 'Token management not initialized' };
          }
          const result = await manager.rollToken(dataArg.id);
          if (!result) {
            return { success: false, message: 'Token not found' };
          }
          return { success: true, tokenValue: result.rawToken };
        },
      ),
    );

    // Toggle API token
    router.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ToggleApiToken>(
        'toggleApiToken',
        async (dataArg) => {
          await requireOpsAuth(this.opsServerRef, dataArg, {
            scope: 'tokens:manage',
            requireAdminIdentity: true,
            requireAdminToken: true,
          });
          const manager = this.opsServerRef.dcRouterRef.apiTokenManager;
          if (!manager) {
            return { success: false, message: 'Token management not initialized' };
          }
          const ok = await manager.toggleToken(dataArg.id, dataArg.enabled);
          return { success: ok, message: ok ? undefined : 'Token not found' };
        },
      ),
    );
  }
}
