import { SimpleLocalIntegration } from '../../core/index.js';
import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/index.js';
import { IndevoltClient } from './indevolt.classes.client.js';
import { IndevoltConfigFlow } from './indevolt.classes.configflow.js';
import { createIndevoltDiscoveryDescriptor } from './indevolt.discovery.js';
import { IndevoltMapper } from './indevolt.mapper.js';
import type { IIndevoltConfig } from './indevolt.types.js';
import { indevoltDomain, indevoltProfile } from './indevolt.types.js';

export class IndevoltIntegration extends SimpleLocalIntegration<IIndevoltConfig> {
  public readonly domain = indevoltDomain;
  public readonly discoveryDescriptor = createIndevoltDiscoveryDescriptor();
  public readonly configFlow = new IndevoltConfigFlow();

  constructor() {
    super(indevoltProfile);
  }

  public async setup(configArg: IIndevoltConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new IndevoltRuntime(new IndevoltClient(configArg));
  }
}

class IndevoltRuntime implements IIntegrationRuntime {
  public readonly domain = indevoltDomain;

  constructor(private readonly client: IndevoltClient) {}

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

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

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (!this.acceptsDomain(requestArg.domain)) {
      return { success: false, error: `Unsupported Indevolt 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();
    }
    if (this.isControlService(requestArg.service)) {
      return this.client.execute(requestArg);
    }
    return { success: false, error: `Unsupported Indevolt service: ${requestArg.service}` };
  }

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

  private acceptsDomain(domainArg: string): boolean {
    return domainArg === indevoltDomain || Boolean(indevoltProfile.serviceDomains?.includes(domainArg));
  }

  private isControlService(serviceArg: string): boolean {
    return Boolean(indevoltProfile.controlServices?.includes(serviceArg)) || ['turn_on', 'turn_off', 'toggle', 'set_value', 'select_option', 'press', 'stop'].includes(serviceArg);
  }
}
