import * as plugins from '../../plugins.js';
import type { IIntegrationEntity } from '../../core/types.js';
import type { ISonosSnapshot } from './sonos.types.js';

export class SonosMapper {
  public static toDevices(snapshotArg: ISonosSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = new Date().toISOString();
    const deviceId = this.deviceId(snapshotArg);
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'playback', capability: 'media', name: 'Playback', 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 },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'playback', value: this.playbackState(snapshotArg), updatedAt },
      { featureId: 'volume', value: snapshotArg.volume ?? null, updatedAt },
      { featureId: 'muted', value: snapshotArg.muted ?? null, updatedAt },
    ];
    if (snapshotArg.positionInfo.title) {
      features.push({ id: 'current_title', capability: 'media', name: 'Current title', readable: true, writable: false });
      state.push({ featureId: 'current_title', value: snapshotArg.positionInfo.title, updatedAt });
    }

    return [{
      id: deviceId,
      integrationDomain: 'sonos',
      name: snapshotArg.speakerInfo.zoneName,
      protocol: 'http',
      manufacturer: snapshotArg.speakerInfo.manufacturer || 'Sonos',
      model: snapshotArg.speakerInfo.modelName || snapshotArg.speakerInfo.modelNumber,
      online: true,
      features,
      state,
      metadata: {
        uid: snapshotArg.speakerInfo.uid,
        serialNumber: snapshotArg.speakerInfo.serialNumber,
        softwareVersion: snapshotArg.speakerInfo.softwareVersion,
        householdId: snapshotArg.speakerInfo.householdId,
      },
    }];
  }

  public static toEntities(snapshotArg: ISonosSnapshot): IIntegrationEntity[] {
    return [{
      id: `media_player.${this.slug(snapshotArg.speakerInfo.zoneName)}`,
      uniqueId: `sonos_${this.slug(snapshotArg.speakerInfo.uid)}`,
      integrationDomain: 'sonos',
      deviceId: this.deviceId(snapshotArg),
      platform: 'media_player',
      name: snapshotArg.speakerInfo.zoneName,
      state: this.playbackState(snapshotArg),
      attributes: {
        volumeLevel: typeof snapshotArg.volume === 'number' ? snapshotArg.volume / 100 : undefined,
        muted: snapshotArg.muted,
        mediaTitle: snapshotArg.positionInfo.title,
        mediaArtist: snapshotArg.positionInfo.artist,
        mediaAlbum: snapshotArg.positionInfo.album,
        mediaDuration: snapshotArg.positionInfo.trackDuration,
        mediaPosition: snapshotArg.positionInfo.relativeTime,
        mediaUri: snapshotArg.positionInfo.trackUri,
        albumArtUri: snapshotArg.positionInfo.albumArtUri,
      },
      available: true,
    }];
  }

  private static playbackState(snapshotArg: ISonosSnapshot): string {
    const state = snapshotArg.transportInfo.currentTransportState;
    if (state === 'PLAYING' || state === 'TRANSITIONING') {
      return 'playing';
    }
    if (state === 'PAUSED_PLAYBACK') {
      return snapshotArg.positionInfo.title ? 'paused' : 'idle';
    }
    if (state === 'STOPPED') {
      return snapshotArg.positionInfo.title ? 'paused' : 'idle';
    }
    return 'idle';
  }

  private static deviceId(snapshotArg: ISonosSnapshot): string {
    return `sonos.player.${this.slug(snapshotArg.speakerInfo.uid)}`;
  }

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