import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import { BaseIntegration } from '../../core/classes.baseintegration.js';
import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
import { HarmanKardonAvrClient } from './harman_kardon_avr.classes.client.js';
import { HarmanKardonAvrConfigFlow } from './harman_kardon_avr.classes.configflow.js';
import { createHarmanKardonAvrDiscoveryDescriptor } from './harman_kardon_avr.discovery.js';
import { HarmanKardonAvrMapper } from './harman_kardon_avr.mapper.js';
import type { IHarmanKardonAvrCommandRequest, IHarmanKardonAvrConfig, THarmanKardonAvrCommand } from './harman_kardon_avr.types.js';
import { harmanKardonAvrDomain } from './harman_kardon_avr.types.js';

export class HarmanKardonAvrIntegration extends BaseIntegration<IHarmanKardonAvrConfig> {
  public readonly domain = harmanKardonAvrDomain;
  public readonly displayName = 'Harman Kardon AVR';
  public readonly status = 'control-runtime' as const;
  public readonly discoveryDescriptor = createHarmanKardonAvrDiscoveryDescriptor();
  public readonly configFlow = new HarmanKardonAvrConfigFlow();
  public readonly metadata = {
    source: 'home-assistant/core',
    upstreamPath: 'homeassistant/components/harman_kardon_avr',
    upstreamDomain: harmanKardonAvrDomain,
    iotClass: 'local_polling',
    qualityScale: 'legacy',
    requirements: ['hkavr==0.0.5'],
    dependencies: [],
    afterDependencies: [],
    codeowners: [],
    configFlow: true,
    runtime: {
      type: 'control-runtime',
      polling: 'local Harman Kardon AVR TCP heartbeat command',
      services: ['snapshot', 'refresh', 'media_player controls'],
      controls: true,
    },
    localApi: {
      implemented: [
        'manual host setup',
        'TCP XML command transport compatible with hkavr power/source/volume/mute/media commands',
        'heartbeat-based reachability snapshots for local TCP endpoints or injected executors',
      ],
      explicitUnsupported: [
        'claiming live command success without config.host, injected client.execute, or commandExecutor',
        'volume level reads or volume_set; upstream hkavr exposes only volume up/down',
        'authoritative mute/media/source state reads when the AVR is controlled outside this runtime',
      ],
    },
  };

  public async setup(configArg: IHarmanKardonAvrConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new HarmanKardonAvrRuntime(new HarmanKardonAvrClient(configArg));
  }

  public async destroy(): Promise<void> {}
}

export class HomeAssistantHarmanKardonAvrIntegration extends HarmanKardonAvrIntegration {}

class HarmanKardonAvrRuntime implements IIntegrationRuntime {
  public domain = harmanKardonAvrDomain;

  constructor(private readonly client: HarmanKardonAvrClient) {}

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

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

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    try {
      if (requestArg.domain === harmanKardonAvrDomain) {
        return this.callHarmanKardonAvrService(requestArg);
      }
      if (requestArg.domain !== 'media_player') {
        return { success: false, error: `Unsupported Harman Kardon AVR service domain: ${requestArg.domain}` };
      }
      const command = this.commandFromService(requestArg);
      if (!command) {
        return { success: false, error: `Unsupported Harman Kardon AVR media_player service: ${requestArg.service}` };
      }
      const commandRequest: IHarmanKardonAvrCommandRequest = {
        command,
        source: this.stringData(requestArg, 'source'),
        muted: this.boolData(requestArg, 'is_volume_muted') ?? this.boolData(requestArg, 'mute'),
      };
      return { success: true, data: await this.client.execute(commandRequest) };
    } catch (errorArg) {
      return { success: false, error: errorArg instanceof Error ? errorArg.message : String(errorArg) };
    }
  }

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

  private async callHarmanKardonAvrService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.service === 'snapshot' || requestArg.service === 'status') {
      return { success: true, data: await this.client.getSnapshot() };
    }
    if (requestArg.service === 'refresh' || requestArg.service === 'reload') {
      const snapshot = await this.client.refresh();
      return snapshot.online
        ? { success: true, data: snapshot }
        : { success: false, error: snapshot.error || 'Harman Kardon AVR refresh requires config.host, config.snapshot, injected client, or commandExecutor.', data: snapshot };
    }
    if (requestArg.service === 'raw_command') {
      const rawCommand = this.stringData(requestArg, 'command') || this.stringData(requestArg, 'rawCommand');
      if (!rawCommand) {
        return { success: false, error: 'Harman Kardon AVR raw_command requires data.command.' };
      }
      return { success: true, data: await this.client.execute({ command: 'raw', rawCommand, parameter: this.stringData(requestArg, 'parameter') }) };
    }
    if (requestArg.service === 'mute_toggle') {
      return { success: true, data: await this.client.execute({ command: 'mute_toggle' }) };
    }
    if (requestArg.service === 'heartbeat') {
      return { success: true, data: await this.client.execute({ command: 'heartbeat' }) };
    }
    return { success: false, error: `Unsupported Harman Kardon AVR service: ${requestArg.service}` };
  }

  private commandFromService(requestArg: IServiceCallRequest): THarmanKardonAvrCommand | undefined {
    if (requestArg.service === 'turn_on') {
      return 'turn_on';
    }
    if (requestArg.service === 'turn_off') {
      return 'turn_off';
    }
    if (requestArg.service === 'volume_up') {
      return 'volume_up';
    }
    if (requestArg.service === 'volume_down') {
      return 'volume_down';
    }
    if (requestArg.service === 'volume_mute') {
      return 'mute';
    }
    if (requestArg.service === 'select_source') {
      return 'select_source';
    }
    if (requestArg.service === 'media_play' || requestArg.service === 'play') {
      return 'play';
    }
    if (requestArg.service === 'media_pause' || requestArg.service === 'pause') {
      return 'pause';
    }
    if (requestArg.service === 'media_next_track' || requestArg.service === 'next_track') {
      return 'next_track';
    }
    if (requestArg.service === 'media_previous_track' || requestArg.service === 'previous_track') {
      return 'previous_track';
    }
    return undefined;
  }

  private stringData(requestArg: IServiceCallRequest, keyArg: string): string | undefined {
    const value = requestArg.data?.[keyArg];
    return typeof value === 'string' ? value : undefined;
  }

  private boolData(requestArg: IServiceCallRequest, keyArg: string): boolean | undefined {
    const value = requestArg.data?.[keyArg];
    return typeof value === 'boolean' ? value : undefined;
  }
}
