import * as plugins from './plugins.js';
import * as interfaces from '../ts_interfaces/index.js';

import { RouteManager } from './classes.route.js';
import { CertificateManager } from './classes.certificate.js';
import { ApiTokenManager } from './classes.apitoken.js';
import { RemoteIngressManager } from './classes.remoteingress.js';
import { StatsManager } from './classes.stats.js';
import { ConfigManager } from './classes.config.js';
import { LogManager } from './classes.logs.js';
import { EmailManager } from './classes.email.js';
import { RadiusManager } from './classes.radius.js';
import { GatewayClientApi } from './classes.gatewayclient.js';

export interface IDcRouterApiClientOptions {
  baseUrl: string;
  apiToken?: string;
}

export class DcRouterApiClient {
  public baseUrl: string;
  public apiToken?: string;
  public identity?: interfaces.data.IIdentity;

  // Resource managers
  public routes: RouteManager;
  public certificates: CertificateManager;
  public apiTokens: ApiTokenManager;
  public remoteIngress: RemoteIngressManager;
  public stats: StatsManager;
  public config: ConfigManager;
  public logs: LogManager;
  public emails: EmailManager;
  public radius: RadiusManager;
  public gatewayClients: GatewayClientApi;

  constructor(options: IDcRouterApiClientOptions) {
    this.baseUrl = options.baseUrl.replace(/\/+$/, '');
    this.apiToken = options.apiToken;

    this.routes = new RouteManager(this);
    this.certificates = new CertificateManager(this);
    this.apiTokens = new ApiTokenManager(this);
    this.remoteIngress = new RemoteIngressManager(this);
    this.stats = new StatsManager(this);
    this.config = new ConfigManager(this);
    this.logs = new LogManager(this);
    this.emails = new EmailManager(this);
    this.radius = new RadiusManager(this);
    this.gatewayClients = new GatewayClientApi(this);
  }

  // =====================
  // Auth
  // =====================

  public async login(username: string, password: string): Promise<interfaces.data.IIdentity> {
    const response = await this.request<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
      'adminLoginWithUsernameAndPassword',
      { username, password },
    );
    if (response.identity) {
      this.identity = response.identity;
    }
    return response.identity!;
  }

  public async logout(): Promise<void> {
    await this.request<interfaces.requests.IReq_AdminLogout>(
      'adminLogout',
      { identity: this.identity! },
    );
    this.identity = undefined;
  }

  public async verifyIdentity(): Promise<{ valid: boolean; identity?: interfaces.data.IIdentity }> {
    const response = await this.request<interfaces.requests.IReq_VerifyIdentity>(
      'verifyIdentity',
      { identity: this.identity! },
    );
    if (response.identity) {
      this.identity = response.identity;
    }
    return response;
  }

  // =====================
  // Internal request helper
  // =====================

  public async request<T extends plugins.typedrequestInterfaces.ITypedRequest>(
    method: string,
    requestData: T['request'],
  ): Promise<T['response']> {
    const typedRequest = new plugins.typedrequest.TypedRequest<T>(
      `${this.baseUrl}/typedrequest`,
      method,
    );
    return typedRequest.fire(requestData);
  }

  /**
   * Build a request payload with identity and optional API token auto-injected.
   */
  public buildRequestPayload(extra: Record<string, any> = {}): Record<string, any> {
    const payload: Record<string, any> = { ...extra };
    if (this.identity) {
      payload.identity = this.identity;
    }
    if (this.apiToken) {
      payload.apiToken = this.apiToken;
    }
    return payload;
  }
}
