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 { BraviatvClient } from './braviatv.classes.client.js';
import { BraviatvConfigFlow } from './braviatv.classes.configflow.js';
import { createBraviatvDiscoveryDescriptor } from './braviatv.discovery.js';
import { BraviatvMapper } from './braviatv.mapper.js';
import type { IBraviatvConfig } from './braviatv.types.js';

export class BraviatvIntegration extends BaseIntegration<IBraviatvConfig> {
  public readonly domain = 'braviatv';
  public readonly displayName = 'Sony Bravia TV';
  public readonly status = 'control-runtime' as const;
  public readonly discoveryDescriptor = createBraviatvDiscoveryDescriptor();
  public readonly configFlow = new BraviatvConfigFlow();
  public readonly metadata = {
    source: 'home-assistant/core',
    upstreamPath: 'homeassistant/components/braviatv',
    upstreamDomain: 'braviatv',
    integrationType: 'device',
    iotClass: 'local_polling',
    requirements: ['pybravia==0.4.1'],
    dependencies: ['ssdp'],
    afterDependencies: [],
    codeowners: ['@bieniu', '@Drafteed'],
    configFlow: true,
    documentation: 'https://www.home-assistant.io/integrations/braviatv',
  };

  public async setup(configArg: IBraviatvConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new BraviatvRuntime(new BraviatvClient(configArg));
  }

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

export class HomeAssistantBraviatvIntegration extends BraviatvIntegration {}

class BraviatvRuntime implements IIntegrationRuntime {
  public domain = 'braviatv';

  constructor(private readonly client: BraviatvClient) {}

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

  public async entities(): Promise<IIntegrationEntity[]> {
    return BraviatvMapper.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 === 'braviatv') {
        return await this.callBraviatvService(requestArg);
      }
      if (requestArg.domain !== 'media_player') {
        return { success: false, error: `Unsupported Sony Bravia TV 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 !== 'send_command') {
      return { success: false, error: `Unsupported Sony Bravia TV 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: 'Sony Bravia TV remote.send_command requires data.command.' };
    }
    const repeatsValue = requestArg.data?.num_repeats ?? requestArg.data?.numRepeats ?? 1;
    const repeats = typeof repeatsValue === 'number' && Number.isFinite(repeatsValue) ? repeatsValue : 1;
    await this.client.sendCommands(commands, repeats);
    return { success: true };
  }

  private async callBraviatvService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    if (requestArg.service === 'reboot') {
      await this.client.reboot();
      return { success: true };
    }
    if (requestArg.service === 'terminate_apps') {
      await this.client.terminateApps();
      return { success: true };
    }
    return { success: false, error: `Unsupported Sony Bravia TV 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.sendCommand('Play');
      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.nextTrack();
      return { success: true };
    }
    if (requestArg.service === 'previous_track' || requestArg.service === 'media_previous_track') {
      await this.client.previousTrack();
      return { success: true };
    }
    if (requestArg.service === 'volume_set') {
      const level = requestArg.data?.volume_level;
      if (typeof level !== 'number') {
        return { success: false, error: 'Sony Bravia TV volume_set requires data.volume_level.' };
      }
      await this.client.setVolumeLevel(level);
      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: 'Sony Bravia TV volume_mute requires data.is_volume_muted.' };
      }
      await this.client.muteVolume(muted);
      return { success: true };
    }
    if (requestArg.service === 'select_source') {
      const source = requestArg.data?.source;
      if (typeof source !== 'string' || !source) {
        return { success: false, error: 'Sony Bravia TV select_source requires data.source.' };
      }
      await this.client.selectSource(source);
      return { success: true };
    }
    if (requestArg.service === 'play_media') {
      const mediaId = requestArg.data?.media_content_id;
      const mediaType = requestArg.data?.media_content_type;
      if (typeof mediaId !== 'string' || typeof mediaType !== 'string') {
        return { success: false, error: 'Sony Bravia TV play_media requires data.media_content_type and data.media_content_id.' };
      }
      await this.client.playMedia(mediaType, mediaId);
      return { success: true };
    }
    return { success: false, error: `Unsupported Sony Bravia TV media_player service: ${requestArg.service}` };
  }
}
