import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import { SimpleLocalIntegration } from '../../core/index.js';
import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/index.js';
import { Nx584Client } from './nx584.classes.client.js';
import { Nx584ConfigFlow } from './nx584.classes.configflow.js';
import { createNx584DiscoveryDescriptor } from './nx584.discovery.js';
import { Nx584Mapper } from './nx584.mapper.js';
import type { INx584Config } from './nx584.types.js';
import { nx584Domain, nx584Profile } from './nx584.types.js';

export class Nx584Integration extends SimpleLocalIntegration<INx584Config> {
  public readonly domain = nx584Domain;
  public readonly discoveryDescriptor = createNx584DiscoveryDescriptor();
  public readonly configFlow = new Nx584ConfigFlow();

  constructor() {
    super(nx584Profile);
  }

  public async setup(configArg: INx584Config, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new Nx584Runtime(new Nx584Client(configArg));
  }
}

export class HomeAssistantNx584Integration extends Nx584Integration {}

class Nx584Runtime implements IIntegrationRuntime {
  public domain = nx584Domain;

  constructor(private readonly client: Nx584Client) {}

  public async devices(): Promise<shxInterfaces.data.IDeviceDefinition[]> {
    return Nx584Mapper.toDevices(await this.client.getSnapshot());
  }

  public async entities(): Promise<IIntegrationEntity[]> {
    return Nx584Mapper.toEntities(await this.client.getSnapshot());
  }

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (!this.acceptsDomain(requestArg.domain)) {
      return { success: false, error: `Unsupported NX584 service domain: ${requestArg.domain}` };
    }
    if (requestArg.service === 'snapshot' || requestArg.service === 'status') {
      return { success: true, data: await this.client.getSnapshot() };
    }
    if (requestArg.service === 'refresh' || requestArg.service === 'reload') {
      return this.client.refresh();
    }
    return this.client.execute(requestArg);
  }

  public async destroy(): Promise<void> {
    await this.client.destroy();
  }

  private acceptsDomain(domainArg: string): boolean {
    return domainArg === nx584Domain || domainArg === 'alarm_control_panel';
  }
}
