import * as plugins from './smartvpn.plugins.js';
import { VpnBridge } from './smartvpn.classes.vpnbridge.js';
import type {
  IVpnClientOptions,
  IVpnClientConfig,
  IVpnStatus,
  IVpnStatistics,
  IVpnConnectionQuality,
  IVpnMtuInfo,
  TVpnClientCommands,
} from './smartvpn.interfaces.js';

/**
 * VPN Client — manages a smartvpn daemon in client mode.
 */
export class VpnClient extends plugins.events.EventEmitter {
  private bridge: VpnBridge<TVpnClientCommands>;
  private options: IVpnClientOptions;

  constructor(options: IVpnClientOptions) {
    super();
    this.options = options;
    this.bridge = new VpnBridge<TVpnClientCommands>({
      transport: options.transport,
      mode: 'client',
    });

    // Forward bridge events
    this.bridge.on('exit', (code: number | null, signal: string | null) => {
      this.emit('exit', { code, signal });
    });
    this.bridge.on('reconnected', () => {
      this.emit('reconnected');
    });
  }

  /**
   * Start the daemon bridge (spawn or connect).
   */
  public async start(): Promise<boolean> {
    return this.bridge.start();
  }

  /**
   * Connect to the VPN server using the provided config.
   */
  public async connect(config?: IVpnClientConfig): Promise<{ assignedIp: string }> {
    const cfg = config || this.options.config;
    if (!cfg) {
      throw new Error('VpnClient.connect: no config provided');
    }
    return this.bridge.sendCommand('connect', { config: cfg });
  }

  /**
   * Disconnect from the VPN server.
   */
  public async disconnect(): Promise<void> {
    await this.bridge.sendCommand('disconnect', {} as Record<string, never>);
  }

  /**
   * Get current connection status.
   */
  public async getStatus(): Promise<IVpnStatus> {
    return this.bridge.sendCommand('getStatus', {} as Record<string, never>);
  }

  /**
   * Get traffic statistics (includes connection quality when connected).
   */
  public async getStatistics(): Promise<IVpnStatistics> {
    return this.bridge.sendCommand('getStatistics', {} as Record<string, never>);
  }

  /**
   * Get connection quality metrics (RTT, jitter, loss, link health).
   */
  public async getConnectionQuality(): Promise<IVpnConnectionQuality> {
    return this.bridge.sendCommand('getConnectionQuality', {} as Record<string, never>);
  }

  /**
   * Get MTU information (overhead, effective MTU, oversized packet stats).
   */
  public async getMtuInfo(): Promise<IVpnMtuInfo> {
    return this.bridge.sendCommand('getMtuInfo', {} as Record<string, never>);
  }

  /**
   * Stop the daemon bridge.
   */
  public stop(): void {
    this.bridge.stop();
  }

  /**
   * Whether the bridge is running.
   */
  public get running(): boolean {
    return this.bridge.running;
  }
}
