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 { RokuClient } from './roku.classes.client.js';
import { RokuConfigFlow } from './roku.classes.configflow.js';
import { createRokuDiscoveryDescriptor } from './roku.discovery.js';
import { RokuMapper } from './roku.mapper.js';
import type { IRokuConfig } from './roku.types.js';

export class RokuIntegration extends BaseIntegration<IRokuConfig> {
  public readonly domain = 'roku';
  public readonly displayName = 'Roku';
  public readonly status = 'control-runtime' as const;
  public readonly discoveryDescriptor = createRokuDiscoveryDescriptor();
  public readonly configFlow = new RokuConfigFlow();
  public readonly metadata = {
    source: 'home-assistant/core',
    upstreamPath: 'homeassistant/components/roku',
    upstreamDomain: 'roku',
    integrationType: 'device',
    iotClass: 'local_polling',
    qualityScale: 'unknown',
  };

  public async setup(configArg: IRokuConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new RokuRuntime(new RokuClient(configArg));
  }

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

export class HomeAssistantRokuIntegration extends RokuIntegration {}

class RokuRuntime implements IIntegrationRuntime {
  public domain = 'roku';

  constructor(private readonly client: RokuClient) {}

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

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

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.domain === 'remote') {
      const command = requestArg.data?.command;
      if (typeof command === 'string') {
        await this.client.keypress(command);
        return { success: true };
      }
      if (Array.isArray(command)) {
        for (const item of command) {
          if (typeof item === 'string') {
            await this.client.keypress(item);
          }
        }
        return { success: true };
      }
      return { success: false, error: 'Roku remote service requires data.command.' };
    }

    if (requestArg.domain !== 'media_player') {
      return { success: false, error: `Unsupported Roku service domain: ${requestArg.domain}` };
    }

    if (requestArg.service === 'turn_on') {
      await this.client.keypress('PowerOn');
      return { success: true };
    }
    if (requestArg.service === 'turn_off') {
      await this.client.keypress('PowerOff');
      return { success: true };
    }
    if (requestArg.service === 'play' || requestArg.service === 'pause' || requestArg.service === 'play_pause') {
      await this.client.keypress('Play');
      return { success: true };
    }
    if (requestArg.service === 'next_track') {
      await this.client.keypress('Fwd');
      return { success: true };
    }
    if (requestArg.service === 'previous_track') {
      await this.client.keypress('Rev');
      return { success: true };
    }
    if (requestArg.service === 'volume_up') {
      await this.client.keypress('VolumeUp');
      return { success: true };
    }
    if (requestArg.service === 'volume_down') {
      await this.client.keypress('VolumeDown');
      return { success: true };
    }
    if (requestArg.service === 'volume_mute') {
      await this.client.keypress('VolumeMute');
      return { success: true };
    }
    if (requestArg.service === 'select_source') {
      const source = requestArg.data?.source;
      if (source === 'Home') {
        await this.client.keypress('Home');
        return { success: true };
      }
      if (typeof source === 'string') {
        const apps = await this.client.getApps();
        const app = apps.find((appArg) => source === appArg.id || source === appArg.name);
        if (app) {
          await this.client.launch(app.id);
          return { success: true };
        }
      }
      return { success: false, error: 'Roku select_source requires a known source.' };
    }
    if (requestArg.service === 'play_media') {
      const mediaId = requestArg.data?.media_content_id ?? requestArg.data?.uri;
      const mediaType = requestArg.data?.media_content_type ?? requestArg.data?.media_type;
      if (typeof mediaId !== 'string' || !mediaId) {
        return { success: false, error: 'Roku play_media requires data.media_content_id or data.uri.' };
      }
      if (mediaType === 'app') {
        await this.client.launch(mediaId);
        return { success: true };
      }
      await this.client.playUrl(mediaId, mediaType === 'music' || mediaType === 'audio' ? 'audio' : 'video', typeof requestArg.data?.title === 'string' ? requestArg.data.title : undefined);
      return { success: true };
    }

    return { success: false, error: `Unsupported Roku media_player service: ${requestArg.service}` };
  }

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