import * as plugins from '../../plugins.js';
import type { IIntegrationEntity } from '../../core/types.js';
import type { ISoundtouchPreset, ISoundtouchSnapshot, ISoundtouchStatus } from './soundtouch.types.js';

export class SoundtouchMapper {
  public static toDevices(snapshotArg: ISoundtouchSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = snapshotArg.lastUpdated || new Date().toISOString();
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'playback', capability: 'media', name: 'Playback', readable: true, writable: true },
      { id: 'source', capability: 'media', name: 'Source', readable: true, writable: true },
      { id: 'volume', capability: 'media', name: 'Volume', readable: true, writable: true, unit: '%' },
      { id: 'muted', capability: 'media', name: 'Muted', readable: true, writable: true },
      { id: 'presets', capability: 'media', name: 'Presets', readable: true, writable: true },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'playback', value: this.mediaState(snapshotArg.status), updatedAt },
      { featureId: 'source', value: snapshotArg.status?.source || null, updatedAt },
      { featureId: 'volume', value: typeof snapshotArg.volume?.actual === 'number' ? snapshotArg.volume.actual : null, updatedAt },
      { featureId: 'muted', value: typeof snapshotArg.volume?.muted === 'boolean' ? snapshotArg.volume.muted : null, updatedAt },
      { featureId: 'presets', value: snapshotArg.presets?.length || 0, updatedAt },
    ];

    if (this.mediaTitle(snapshotArg.status)) {
      features.push({ id: 'current_title', capability: 'media', name: 'Current title', readable: true, writable: false });
      state.push({ featureId: 'current_title', value: this.mediaTitle(snapshotArg.status) || null, updatedAt });
    }

    return [{
      id: this.playerDeviceId(snapshotArg),
      integrationDomain: 'soundtouch',
      name: this.deviceName(snapshotArg),
      protocol: 'http',
      manufacturer: 'Bose Corporation',
      model: snapshotArg.config.type,
      online: snapshotArg.available !== false,
      features,
      state,
      metadata: {
        deviceId: snapshotArg.config.deviceId,
        host: snapshotArg.config.host,
        port: snapshotArg.config.port,
        macAddress: this.macAddress(snapshotArg),
        accountUuid: snapshotArg.config.accountUuid,
        moduleType: snapshotArg.config.moduleType,
        variant: snapshotArg.config.variant,
        softwareVersions: snapshotArg.config.components?.map((componentArg) => componentArg.softwareVersion).filter(Boolean),
      },
    }];
  }

  public static toEntities(snapshotArg: ISoundtouchSnapshot): IIntegrationEntity[] {
    const base = this.entityBase(snapshotArg);
    const entities: IIntegrationEntity[] = [{
      id: `media_player.${base}`,
      uniqueId: `soundtouch_${this.uniqueBase(snapshotArg)}`,
      integrationDomain: 'soundtouch',
      deviceId: this.playerDeviceId(snapshotArg),
      platform: 'media_player',
      name: this.deviceName(snapshotArg),
      state: this.mediaState(snapshotArg.status),
      attributes: {
        deviceClass: 'speaker',
        deviceId: snapshotArg.config.deviceId,
        model: snapshotArg.config.type,
        macAddress: this.macAddress(snapshotArg),
        volumeLevel: typeof snapshotArg.volume?.actual === 'number' ? Math.max(0, Math.min(1, snapshotArg.volume.actual / 100)) : undefined,
        volume: snapshotArg.volume?.actual,
        targetVolume: snapshotArg.volume?.target,
        isVolumeMuted: snapshotArg.volume?.muted,
        source: snapshotArg.status?.source,
        sourceList: snapshotArg.sourceList || [],
        presetList: this.presetList(snapshotArg),
        mediaContentType: snapshotArg.status?.contentItem?.type || snapshotArg.status?.streamType,
        mediaContentId: snapshotArg.status?.contentItem?.location || snapshotArg.status?.trackId,
        mediaTitle: this.mediaTitle(snapshotArg.status),
        mediaArtist: snapshotArg.status?.artist,
        mediaTrack: snapshotArg.status?.track,
        mediaAlbumName: snapshotArg.status?.album,
        mediaImageUrl: snapshotArg.status?.image,
        mediaDuration: snapshotArg.status?.duration,
        mediaPosition: snapshotArg.status?.position,
        shuffle: snapshotArg.status?.shuffleSetting,
        repeat: snapshotArg.status?.repeatSetting,
        stationName: snapshotArg.status?.stationName,
        stationLocation: snapshotArg.status?.stationLocation,
        soundtouchZone: this.zoneAttribute(snapshotArg),
        soundtouchGroup: this.groupAttribute(snapshotArg),
      },
      available: snapshotArg.available !== false,
    }];

    entities.push({
      id: `sensor.${base}_soundtouch_presets`,
      uniqueId: `soundtouch_${this.uniqueBase(snapshotArg)}_presets`,
      integrationDomain: 'soundtouch',
      deviceId: this.playerDeviceId(snapshotArg),
      platform: 'sensor',
      name: `${this.deviceName(snapshotArg)} SoundTouch Presets`,
      state: snapshotArg.presets?.length || 0,
      attributes: { presets: this.presetList(snapshotArg) },
      available: snapshotArg.available !== false,
    });

    entities.push({
      id: `sensor.${base}_soundtouch_sources`,
      uniqueId: `soundtouch_${this.uniqueBase(snapshotArg)}_sources`,
      integrationDomain: 'soundtouch',
      deviceId: this.playerDeviceId(snapshotArg),
      platform: 'sensor',
      name: `${this.deviceName(snapshotArg)} SoundTouch Sources`,
      state: snapshotArg.sourceList?.length || 0,
      attributes: { sourceList: snapshotArg.sourceList || [] },
      available: snapshotArg.available !== false,
    });

    entities.push({
      id: `sensor.${base}_soundtouch_media`,
      uniqueId: `soundtouch_${this.uniqueBase(snapshotArg)}_media`,
      integrationDomain: 'soundtouch',
      deviceId: this.playerDeviceId(snapshotArg),
      platform: 'sensor',
      name: `${this.deviceName(snapshotArg)} SoundTouch Media`,
      state: this.mediaTitle(snapshotArg.status) || snapshotArg.status?.source || 'None',
      attributes: { status: snapshotArg.status },
      available: snapshotArg.available !== false,
    });

    return entities;
  }

  public static playerDeviceId(snapshotArg: ISoundtouchSnapshot): string {
    return `soundtouch.player.${this.uniqueBase(snapshotArg)}`;
  }

  public static slug(valueArg: string | undefined): string {
    return (valueArg || 'soundtouch').toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'soundtouch';
  }

  private static mediaState(statusArg: ISoundtouchStatus | undefined): string {
    if (!statusArg || statusArg.source === 'STANDBY' || statusArg.playStatus === 'STOP_STATE') {
      return 'off';
    }
    if (statusArg.source === 'INVALID_SOURCE') {
      return 'unknown';
    }
    if (statusArg.playStatus === 'PLAY_STATE' || statusArg.playStatus === 'BUFFERING_STATE') {
      return 'playing';
    }
    if (statusArg.playStatus === 'PAUSE_STATE') {
      return 'paused';
    }
    return 'idle';
  }

  private static mediaTitle(statusArg: ISoundtouchStatus | undefined): string | undefined {
    if (!statusArg) {
      return undefined;
    }
    if (statusArg.stationName) {
      return statusArg.stationName;
    }
    if (statusArg.artist && statusArg.track) {
      return `${statusArg.artist} - ${statusArg.track}`;
    }
    return statusArg.track || statusArg.contentItem?.name || statusArg.description;
  }

  private static presetList(snapshotArg: ISoundtouchSnapshot): Array<Record<string, unknown>> {
    return (snapshotArg.presets || []).map((presetArg: ISoundtouchPreset) => ({
      presetId: presetArg.presetId,
      name: presetArg.name,
      source: presetArg.source,
      type: presetArg.type,
      location: presetArg.location,
      sourceAccount: presetArg.sourceAccount,
      isPresetable: presetArg.isPresetable,
    }));
  }

  private static zoneAttribute(snapshotArg: ISoundtouchSnapshot): Record<string, unknown> | undefined {
    if (!snapshotArg.zone) {
      return undefined;
    }
    return {
      master: snapshotArg.zone.masterId,
      masterIp: snapshotArg.zone.masterIp,
      isMaster: snapshotArg.zone.isMaster,
      slaves: snapshotArg.zone.slaves,
    };
  }

  private static groupAttribute(snapshotArg: ISoundtouchSnapshot): string[] | undefined {
    if (!snapshotArg.zone) {
      return undefined;
    }
    return [
      snapshotArg.zone.masterId || snapshotArg.zone.masterIp,
      ...snapshotArg.zone.slaves.map((slaveArg) => slaveArg.deviceId || slaveArg.ipAddress),
    ].filter((valueArg): valueArg is string => Boolean(valueArg));
  }

  private static deviceName(snapshotArg: ISoundtouchSnapshot): string {
    return snapshotArg.config.name || snapshotArg.config.type || 'Bose SoundTouch';
  }

  private static entityBase(snapshotArg: ISoundtouchSnapshot): string {
    return this.slug(this.deviceName(snapshotArg));
  }

  private static uniqueBase(snapshotArg: ISoundtouchSnapshot): string {
    return this.slug(snapshotArg.config.deviceId || this.macAddress(snapshotArg) || snapshotArg.config.host || this.deviceName(snapshotArg));
  }

  private static macAddress(snapshotArg: ISoundtouchSnapshot): string | undefined {
    return snapshotArg.config.networks?.find((networkArg) => networkArg.type === 'SMSC')?.macAddress || snapshotArg.config.networks?.[0]?.macAddress;
  }
}
