import * as plugins from '../../plugins.js';
import type { IIntegrationEntity } from '../../core/types.js';
import { androidtvKnownApps } from './androidtv.constants.js';
import type { IAndroidtvSnapshot } from './androidtv.types.js';

export class AndroidtvMapper {
  public static toDevices(snapshotArg: IAndroidtvSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = snapshotArg.updatedAt || new Date().toISOString();
    return [{
      id: this.deviceId(snapshotArg),
      integrationDomain: 'androidtv',
      name: this.deviceName(snapshotArg),
      protocol: 'unknown',
      manufacturer: snapshotArg.deviceInfo.manufacturer || this.defaultManufacturer(snapshotArg),
      model: snapshotArg.deviceInfo.model || this.deviceTypeLabel(snapshotArg),
      online: this.available(snapshotArg),
      features: [
        { id: 'power', capability: 'media', name: 'Power', readable: true, writable: true },
        { id: 'media_state', capability: 'media', name: 'Media state', readable: true, writable: false },
        { id: 'source', capability: 'media', name: 'Source', readable: true, writable: true },
        { id: 'volume', capability: 'media', name: 'Volume', readable: true, writable: true },
        { id: 'mute', capability: 'media', name: 'Mute', readable: true, writable: true },
        { id: 'remote_key', capability: 'media', name: 'Remote key', readable: false, writable: true },
      ],
      state: [
        { featureId: 'power', value: this.powerState(snapshotArg), updatedAt },
        { featureId: 'media_state', value: this.mediaState(snapshotArg), updatedAt },
        { featureId: 'source', value: this.source(snapshotArg) || null, updatedAt },
        { featureId: 'volume', value: this.volumePercent(snapshotArg), updatedAt },
        { featureId: 'mute', value: snapshotArg.state.isVolumeMuted ?? null, updatedAt },
      ],
      metadata: {
        host: snapshotArg.deviceInfo.host,
        port: snapshotArg.deviceInfo.port,
        deviceClass: snapshotArg.deviceInfo.deviceClass,
        serialNumber: snapshotArg.deviceInfo.serialNumber,
        softwareVersion: snapshotArg.deviceInfo.softwareVersion,
        productId: snapshotArg.deviceInfo.productId,
        wifiMac: snapshotArg.deviceInfo.wifiMac,
        ethernetMac: snapshotArg.deviceInfo.ethernetMac,
        hdmiInput: snapshotArg.state.hdmiInput,
        apps: snapshotArg.apps.map((appArg) => ({ id: appArg.id, name: appArg.name || androidtvKnownApps[appArg.id] })),
      },
    }];
  }

  public static toEntities(snapshotArg: IAndroidtvSnapshot): IIntegrationEntity[] {
    return [{
      id: `media_player.${this.slug(this.deviceName(snapshotArg))}`,
      uniqueId: `androidtv_${this.slug(this.stableDeviceKey(snapshotArg))}`,
      integrationDomain: 'androidtv',
      deviceId: this.deviceId(snapshotArg),
      platform: 'media_player',
      name: this.deviceName(snapshotArg),
      state: this.mediaState(snapshotArg),
      attributes: {
        source: this.source(snapshotArg),
        appId: snapshotArg.state.currentAppId,
        appName: snapshotArg.state.currentAppName,
        sourceList: this.sourceList(snapshotArg),
        volumeLevel: snapshotArg.state.volumeLevel,
        isVolumeMuted: snapshotArg.state.isVolumeMuted,
        hdmiInput: snapshotArg.state.hdmiInput,
        adbResponse: snapshotArg.state.adbResponse,
        mediaTitle: snapshotArg.state.mediaTitle,
        mediaArtist: snapshotArg.state.mediaArtist,
        mediaAlbumName: snapshotArg.state.mediaAlbumName,
        rawState: snapshotArg.state.rawState,
        deviceClass: snapshotArg.deviceInfo.deviceClass,
      },
      available: this.available(snapshotArg),
    }];
  }

  private static mediaState(snapshotArg: IAndroidtvSnapshot): string {
    if (!this.available(snapshotArg)) {
      return 'unavailable';
    }
    const state = String(snapshotArg.state.rawState || snapshotArg.state.powerState || 'idle').toLowerCase();
    if (state === 'off' || snapshotArg.state.powerState === 'off') {
      return 'off';
    }
    if (state === 'playing') {
      return 'playing';
    }
    if (state === 'paused') {
      return 'paused';
    }
    if (state === 'standby' || state === 'idle' || state === 'stopped') {
      return 'idle';
    }
    return this.source(snapshotArg) ? 'on' : 'idle';
  }

  private static powerState(snapshotArg: IAndroidtvSnapshot): string {
    if (snapshotArg.state.powerState === 'off' || String(snapshotArg.state.rawState).toLowerCase() === 'off') {
      return 'off';
    }
    if (!this.available(snapshotArg)) {
      return 'unknown';
    }
    return 'on';
  }

  private static available(snapshotArg: IAndroidtvSnapshot): boolean {
    return snapshotArg.state.available !== false;
  }

  private static source(snapshotArg: IAndroidtvSnapshot): string | undefined {
    if (snapshotArg.state.source) {
      return snapshotArg.state.source;
    }
    if (snapshotArg.state.currentAppName) {
      return snapshotArg.state.currentAppName;
    }
    const appId = snapshotArg.state.currentAppId;
    return appId ? this.appName(snapshotArg, appId) : undefined;
  }

  private static sourceList(snapshotArg: IAndroidtvSnapshot): string[] {
    const sourceSet = new Set<string>();
    for (const appArg of snapshotArg.apps) {
      const name = appArg.name || androidtvKnownApps[appArg.id] || appArg.id;
      if (name) {
        sourceSet.add(name);
      }
    }
    for (const appId of snapshotArg.state.runningAppIds || []) {
      sourceSet.add(this.appName(snapshotArg, appId) || appId);
    }
    return [...sourceSet];
  }

  private static appName(snapshotArg: IAndroidtvSnapshot, appIdArg: string): string | undefined {
    return snapshotArg.apps.find((appArg) => appArg.id === appIdArg)?.name || androidtvKnownApps[appIdArg];
  }

  private static volumePercent(snapshotArg: IAndroidtvSnapshot): number | null {
    return typeof snapshotArg.state.volumeLevel === 'number' ? Math.round(Math.max(0, Math.min(1, snapshotArg.state.volumeLevel)) * 100) : null;
  }

  private static deviceId(snapshotArg: IAndroidtvSnapshot): string {
    return `androidtv.device.${this.slug(this.stableDeviceKey(snapshotArg))}`;
  }

  private static stableDeviceKey(snapshotArg: IAndroidtvSnapshot): string {
    return snapshotArg.deviceInfo.id || snapshotArg.deviceInfo.serialNumber || snapshotArg.deviceInfo.ethernetMac || snapshotArg.deviceInfo.wifiMac || snapshotArg.deviceInfo.host || this.deviceName(snapshotArg);
  }

  private static deviceName(snapshotArg: IAndroidtvSnapshot): string {
    return snapshotArg.deviceInfo.name || snapshotArg.deviceInfo.model || snapshotArg.deviceInfo.host || 'Android TV';
  }

  private static defaultManufacturer(snapshotArg: IAndroidtvSnapshot): string {
    return snapshotArg.deviceInfo.deviceClass === 'firetv' ? 'Amazon' : 'Android';
  }

  private static deviceTypeLabel(snapshotArg: IAndroidtvSnapshot): string {
    return snapshotArg.deviceInfo.deviceClass === 'firetv' ? 'Fire TV' : 'Android TV';
  }

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