import { HomekitControllerMapper } from './homekit_controller.mapper.js';
import type { IHomekitControllerCommand, IHomekitControllerConfig, IHomekitControllerSnapshot, IHomekitEvent } from './homekit_controller.types.js';

type TEventHandler = (eventArg: IHomekitEvent) => void;

export class HomekitControllerClient {
  private readonly eventHandlers = new Set<TEventHandler>();
  private readonly events: IHomekitEvent[] = [];
  private snapshot?: IHomekitControllerSnapshot;

  constructor(private readonly config: IHomekitControllerConfig) {
    this.snapshot = config.snapshot;
  }

  public async getSnapshot(): Promise<IHomekitControllerSnapshot> {
    this.snapshot = HomekitControllerMapper.toSnapshot({ ...this.config, snapshot: this.snapshot }, false, this.events);
    return this.snapshot;
  }

  public async execute(commandArg: IHomekitControllerCommand): Promise<unknown> {
    if (commandArg.command === 'snapshot') {
      return this.getSnapshot();
    }
    if (commandArg.command === 'pair_setup') {
      return this.pairSetup(commandArg);
    }
    if (commandArg.command === 'pair_verify') {
      return this.pairVerify(commandArg);
    }
    if (commandArg.command === 'read_characteristics') {
      return this.readCharacteristics(commandArg);
    }
    if (commandArg.command === 'write_characteristics' || commandArg.command === 'identify') {
      return this.writeCharacteristics(commandArg);
    }
    if (commandArg.command === 'subscribe_events') {
      return this.subscribeEvents(commandArg);
    }
    if (commandArg.command === 'camera_snapshot') {
      return this.cameraSnapshot(commandArg);
    }
    throw new Error(`Unsupported HomeKit Controller command: ${commandArg.command}`);
  }

  public onEvent(handlerArg: TEventHandler): () => void {
    this.eventHandlers.add(handlerArg);
    return () => this.eventHandlers.delete(handlerArg);
  }

  public async destroy(): Promise<void> {
    this.eventHandlers.clear();
  }

  private async readCharacteristics(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    this.throwUnsupportedSecureSession('characteristic reads');
  }

  private async pairSetup(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    throw new Error('HomeKit pair setup is not implemented in this native port. Provide existing pairing data and a cached accessory snapshot, or use snapshot mode until native HAP SRP and secure-session support is added.');
  }

  private async pairVerify(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    this.throwUnsupportedSecureSession('pair-verify sessions');
  }

  private async subscribeEvents(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    this.throwUnsupportedSecureSession('event subscriptions');
  }

  private async writeCharacteristics(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    this.throwUnsupportedSecureSession('characteristic writes');
  }

  private async cameraSnapshot(commandArg: IHomekitControllerCommand): Promise<unknown> {
    void commandArg;
    this.throwUnsupportedSecureSession('camera snapshots');
  }

  private throwUnsupportedSecureSession(operationArg: string): never {
    if (!this.config.host && !this.config.pairingData?.AccessoryIP) {
      throw new Error(`HomeKit ${operationArg} require a host/port and a HAP pair-verify encrypted session. This config only contains snapshot data.`);
    }
    if (!this.config.pairingData) {
      throw new Error(`HomeKit ${operationArg} require pairing data and a HAP pair-verify encrypted session. Pair setup is not implemented in this native port.`);
    }
    throw new Error(`HomeKit ${operationArg} require HAP pair-verify session encryption. This native port exposes snapshots and mappings only until a native HAP secure-session implementation is added.`);
  }
}
