import * as plugins from '../../plugins.js';
import { BaseIntegration } from '../../core/classes.baseintegration.js';
import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
import { AndroidtvRemoteClient } from './androidtv_remote.classes.client.js';
import { AndroidtvRemoteConfigFlow } from './androidtv_remote.classes.configflow.js';
import { createAndroidtvRemoteDiscoveryDescriptor } from './androidtv_remote.discovery.js';
import { AndroidtvRemoteMapper } from './androidtv_remote.mapper.js';
import type { IAndroidtvRemoteConfig } from './androidtv_remote.types.js';

export class AndroidtvRemoteIntegration extends BaseIntegration<IAndroidtvRemoteConfig> {
  public readonly domain = 'androidtv_remote';
  public readonly displayName = 'Android TV Remote';
  public readonly status = 'control-runtime' as const;
  public readonly discoveryDescriptor = createAndroidtvRemoteDiscoveryDescriptor();
  public readonly configFlow = new AndroidtvRemoteConfigFlow();
  public readonly metadata = {
    source: 'home-assistant/core',
    upstreamPath: 'homeassistant/components/androidtv_remote',
    upstreamDomain: 'androidtv_remote',
    integrationType: 'device',
    iotClass: 'local_push',
    qualityScale: 'platinum',
    requirements: ['androidtvremote2==0.3.1'],
    dependencies: [],
    afterDependencies: [],
    codeowners: ['@tronikos', '@Drafteed'],
    configFlow: true,
    documentation: 'https://www.home-assistant.io/integrations/androidtv_remote',
  };

  public async setup(configArg: IAndroidtvRemoteConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new AndroidtvRemoteRuntime(new AndroidtvRemoteClient(configArg));
  }

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

export class HomeAssistantAndroidtvRemoteIntegration extends AndroidtvRemoteIntegration {}

class AndroidtvRemoteRuntime implements IIntegrationRuntime {
  public domain = 'androidtv_remote';

  constructor(private readonly client: AndroidtvRemoteClient) {}

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

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

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    try {
      if (requestArg.domain === 'remote') {
        return await this.callRemoteService(requestArg);
      }
      if (requestArg.domain === 'androidtv_remote') {
        return await this.callAndroidtvRemoteService(requestArg);
      }
      if (requestArg.domain !== 'media_player') {
        return { success: false, error: `Unsupported Android TV Remote service domain: ${requestArg.domain}` };
      }
      return await this.callMediaPlayerService(requestArg);
    } catch (errorArg) {
      return { success: false, error: errorArg instanceof Error ? errorArg.message : String(errorArg) };
    }
  }

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

  private async callRemoteService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.service === 'turn_on') {
      await this.client.turnOn();
      const activity = this.stringValue(requestArg.data?.activity);
      if (activity) {
        await this.client.selectActivity(activity);
      }
      return { success: true };
    }
    if (requestArg.service === 'turn_off') {
      await this.client.turnOff();
      return { success: true };
    }
    if (requestArg.service !== 'send_command') {
      return { success: false, error: `Unsupported Android TV Remote remote service: ${requestArg.service}` };
    }
    const command = requestArg.data?.command;
    const commands = typeof command === 'string' ? [command] : Array.isArray(command) ? command.filter((itemArg): itemArg is string => typeof itemArg === 'string' && Boolean(itemArg)) : [];
    if (!commands.length) {
      return { success: false, error: 'Android TV Remote remote.send_command requires data.command.' };
    }
    await this.client.sendCommand(commands, {
      repeats: this.numberValue(requestArg.data?.num_repeats ?? requestArg.data?.numRepeats),
      delaySecs: this.numberValue(requestArg.data?.delay_secs ?? requestArg.data?.delaySecs),
      holdSecs: this.numberValue(requestArg.data?.hold_secs ?? requestArg.data?.holdSecs),
      reason: 'remote_send_command',
    });
    return { success: true };
  }

  private async callAndroidtvRemoteService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.service === 'connect') {
      await this.client.connect();
      return { success: true };
    }
    if (requestArg.service === 'start_pairing') {
      await this.client.startPairing();
      return { success: true };
    }
    if (requestArg.service === 'finish_pairing') {
      const pin = this.stringValue(requestArg.data?.pin);
      if (!pin) {
        return { success: false, error: 'Android TV Remote finish_pairing requires data.pin.' };
      }
      await this.client.finishPairing(pin);
      return { success: true };
    }
    if (requestArg.service === 'launch_app') {
      const app = this.stringValue(requestArg.data?.app_id ?? requestArg.data?.appId ?? requestArg.data?.app_link ?? requestArg.data?.appLink);
      if (!app) {
        return { success: false, error: 'Android TV Remote launch_app requires data.app_id or data.app_link.' };
      }
      await this.client.launchApp(app);
      return { success: true };
    }
    if (requestArg.service === 'send_text') {
      const text = this.stringValue(requestArg.data?.text);
      if (!text) {
        return { success: false, error: 'Android TV Remote send_text requires data.text.' };
      }
      await this.client.sendText(text);
      return { success: true };
    }
    return { success: false, error: `Unsupported Android TV Remote service: ${requestArg.service}` };
  }

  private async callMediaPlayerService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.service === 'turn_on') {
      await this.client.turnOn();
      return { success: true };
    }
    if (requestArg.service === 'turn_off') {
      await this.client.turnOff();
      return { success: true };
    }
    if (requestArg.service === 'play' || requestArg.service === 'media_play') {
      await this.client.mediaPlay();
      return { success: true };
    }
    if (requestArg.service === 'pause' || requestArg.service === 'media_pause') {
      await this.client.mediaPause();
      return { success: true };
    }
    if (requestArg.service === 'play_pause' || requestArg.service === 'media_play_pause') {
      await this.client.mediaPlayPause();
      return { success: true };
    }
    if (requestArg.service === 'stop' || requestArg.service === 'media_stop') {
      await this.client.mediaStop();
      return { success: true };
    }
    if (requestArg.service === 'next_track' || requestArg.service === 'media_next_track') {
      await this.client.mediaNextTrack();
      return { success: true };
    }
    if (requestArg.service === 'previous_track' || requestArg.service === 'media_previous_track') {
      await this.client.mediaPreviousTrack();
      return { success: true };
    }
    if (requestArg.service === 'volume_up') {
      await this.client.volumeUp();
      return { success: true };
    }
    if (requestArg.service === 'volume_down') {
      await this.client.volumeDown();
      return { success: true };
    }
    if (requestArg.service === 'volume_mute' || requestArg.service === 'mute') {
      const muted = requestArg.data?.is_volume_muted ?? requestArg.data?.muted;
      if (typeof muted !== 'boolean') {
        return { success: false, error: 'Android TV Remote volume_mute requires data.is_volume_muted.' };
      }
      await this.client.muteVolume(muted);
      return { success: true };
    }
    if (requestArg.service === 'volume_set') {
      const level = requestArg.data?.volume_level;
      if (typeof level !== 'number') {
        return { success: false, error: 'Android TV Remote volume_set requires data.volume_level.' };
      }
      await this.client.setVolumeLevel(level);
      return { success: true };
    }
    if (requestArg.service === 'select_source') {
      const source = this.stringValue(requestArg.data?.source);
      if (!source) {
        return { success: false, error: 'Android TV Remote select_source requires data.source.' };
      }
      await this.client.selectActivity(source);
      return { success: true };
    }
    if (requestArg.service === 'play_media') {
      return await this.callPlayMediaService(requestArg);
    }
    return { success: false, error: `Unsupported Android TV Remote media_player service: ${requestArg.service}` };
  }

  private async callPlayMediaService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    const mediaId = this.stringValue(requestArg.data?.media_content_id ?? requestArg.data?.media_id ?? requestArg.data?.uri);
    const mediaType = this.stringValue(requestArg.data?.media_content_type ?? requestArg.data?.media_type);
    if (!mediaId) {
      return { success: false, error: 'Android TV Remote play_media requires data.media_content_id.' };
    }
    if (mediaType === 'channel') {
      await this.client.playChannel(mediaId);
      return { success: true };
    }
    if (mediaType === 'app' || mediaType === 'url') {
      await this.client.launchApp(mediaId);
      return { success: true };
    }
    return { success: false, error: `Unsupported Android TV Remote media type: ${mediaType || 'unknown'}` };
  }

  private stringValue(valueArg: unknown): string | undefined {
    return typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim() : undefined;
  }

  private numberValue(valueArg: unknown): number | undefined {
    return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : undefined;
  }
}
