import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import { SimpleLocalIntegration, type IIntegrationEntity, type IIntegrationRuntime, type IIntegrationSetupContext, type IServiceCallRequest, type IServiceCallResult } from '../../core/index.js';
import { MaryttsClient } from './marytts.classes.client.js';
import { MaryttsConfigFlow } from './marytts.classes.configflow.js';
import { createMaryttsDiscoveryDescriptor } from './marytts.discovery.js';
import { MaryttsMapper } from './marytts.mapper.js';
import type { IMaryttsConfig } from './marytts.types.js';
import { maryttsDomain, maryttsProfile } from './marytts.types.js';

export class MaryttsIntegration extends SimpleLocalIntegration<IMaryttsConfig> {
  public readonly domain = maryttsDomain;
  public readonly discoveryDescriptor = createMaryttsDiscoveryDescriptor();
  public readonly configFlow = new MaryttsConfigFlow();

  constructor() {
    super(maryttsProfile);
  }

  public async setup(configArg: IMaryttsConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new MaryttsRuntime(new MaryttsClient(configArg));
  }
}

export class HomeAssistantMaryttsIntegration extends MaryttsIntegration {}

class MaryttsRuntime implements IIntegrationRuntime {
  public readonly domain = maryttsDomain;

  constructor(private readonly client: MaryttsClient) {}

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

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

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.domain !== maryttsDomain && requestArg.domain !== 'tts') {
      return { success: false, error: `Unsupported MaryTTS service domain: ${requestArg.domain}` };
    }
    return this.client.execute(requestArg);
  }

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