import * as plugins from '../../plugins.js';
import type { IIntegrationEntity } from '../../core/types.js';
import type { IHarmanKardonAvrDeviceInfo, IHarmanKardonAvrSnapshot } from './harman_kardon_avr.types.js';
import { harmanKardonAvrDefaultName, harmanKardonAvrDomain } from './harman_kardon_avr.types.js';

export class HarmanKardonAvrMapper {
  public static toDevices(snapshotArg: IHarmanKardonAvrSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = snapshotArg.lastUpdated || new Date().toISOString();
    return [{
      id: this.deviceId(snapshotArg),
      integrationDomain: harmanKardonAvrDomain,
      name: this.deviceName(snapshotArg.deviceInfo),
      protocol: 'unknown',
      manufacturer: snapshotArg.deviceInfo.manufacturer || 'Harman Kardon',
      model: snapshotArg.deviceInfo.model,
      online: snapshotArg.online && snapshotArg.available,
      features: [
        { id: 'power', capability: 'media', name: 'Power', readable: true, writable: true },
        { id: 'source', capability: 'media', name: 'Source', readable: true, writable: true },
        { id: 'muted', capability: 'media', name: 'Muted', readable: true, writable: true },
        { id: 'volume_step', capability: 'media', name: 'Volume step', readable: false, writable: true },
      ],
      state: [
        { featureId: 'power', value: this.powerState(snapshotArg), updatedAt },
        { featureId: 'source', value: snapshotArg.state.source || null, updatedAt },
        { featureId: 'muted', value: snapshotArg.state.muted ?? null, updatedAt },
      ],
      metadata: this.cleanAttributes({
        host: snapshotArg.deviceInfo.host,
        port: snapshotArg.deviceInfo.port,
        zone: snapshotArg.deviceInfo.zone,
        protocol: 'harman-kardon-avr-tcp-http',
        serialNumber: snapshotArg.deviceInfo.serialNumber,
        source: snapshotArg.source,
        rawResponse: snapshotArg.rawResponse,
        error: snapshotArg.error,
      }),
    }];
  }

  public static toEntities(snapshotArg: IHarmanKardonAvrSnapshot): IIntegrationEntity[] {
    const entityBase = this.entityBase(snapshotArg);
    const deviceId = this.deviceId(snapshotArg);
    const entities: IIntegrationEntity[] = [{
      id: `media_player.${entityBase}`,
      uniqueId: `harman_kardon_avr_${this.uniqueBase(snapshotArg)}_media_player`,
      integrationDomain: harmanKardonAvrDomain,
      deviceId,
      platform: 'media_player',
      name: this.deviceName(snapshotArg.deviceInfo),
      state: this.mediaState(snapshotArg),
      attributes: this.cleanAttributes({
        deviceClass: 'receiver',
        power: snapshotArg.state.power,
        isVolumeMuted: snapshotArg.state.muted,
        source: snapshotArg.state.source,
        sourceList: snapshotArg.state.sourceList,
        supportedFeatures: snapshotArg.state.supportedFeatures,
        zone: snapshotArg.deviceInfo.zone,
        rawResponse: snapshotArg.rawResponse,
        error: snapshotArg.error,
      }),
      available: snapshotArg.online && snapshotArg.available,
    }, {
      id: `sensor.${entityBase}_source`,
      uniqueId: `harman_kardon_avr_${this.uniqueBase(snapshotArg)}_source`,
      integrationDomain: harmanKardonAvrDomain,
      deviceId,
      platform: 'sensor',
      name: `${this.deviceName(snapshotArg.deviceInfo)} Source`,
      state: snapshotArg.state.source || 'unknown',
      attributes: {},
      available: snapshotArg.online && snapshotArg.available,
    }];

    if (typeof snapshotArg.state.muted === 'boolean') {
      entities.push({
        id: `switch.${entityBase}_mute`,
        uniqueId: `harman_kardon_avr_${this.uniqueBase(snapshotArg)}_mute`,
        integrationDomain: harmanKardonAvrDomain,
        deviceId,
        platform: 'switch',
        name: `${this.deviceName(snapshotArg.deviceInfo)} Mute`,
        state: snapshotArg.state.muted,
        attributes: {},
        available: snapshotArg.online && snapshotArg.available,
      });
    }

    return entities;
  }

  public static deviceId(snapshotArg: IHarmanKardonAvrSnapshot): string {
    return `harman_kardon_avr.receiver.${this.uniqueBase(snapshotArg)}`;
  }

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

  private static mediaState(snapshotArg: IHarmanKardonAvrSnapshot): string {
    if (!snapshotArg.online || !snapshotArg.available) {
      return 'unavailable';
    }
    const state = snapshotArg.state.state?.toLowerCase();
    if (state === 'on' || state === 'off' || state === 'playing' || state === 'paused' || state === 'idle') {
      return state;
    }
    return 'unknown';
  }

  private static powerState(snapshotArg: IHarmanKardonAvrSnapshot): string {
    if (!snapshotArg.online || !snapshotArg.available) {
      return 'unavailable';
    }
    if (snapshotArg.state.power === 'OFF' || snapshotArg.state.state === 'off') {
      return 'off';
    }
    if (snapshotArg.state.power === 'ON' || snapshotArg.state.state === 'on') {
      return 'on';
    }
    return 'unknown';
  }

  private static deviceIdentity(snapshotArg: IHarmanKardonAvrSnapshot): string {
    return snapshotArg.deviceInfo.serialNumber || snapshotArg.deviceInfo.host || this.deviceName(snapshotArg.deviceInfo);
  }

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

  private static uniqueBase(snapshotArg: IHarmanKardonAvrSnapshot): string {
    return this.slug(this.deviceIdentity(snapshotArg));
  }

  private static deviceName(infoArg: IHarmanKardonAvrDeviceInfo): string {
    return infoArg.name || infoArg.model || harmanKardonAvrDefaultName;
  }

  private static cleanAttributes(attributesArg: Record<string, unknown>): Record<string, unknown> {
    return Object.fromEntries(Object.entries(attributesArg).filter(([, valueArg]) => valueArg !== undefined));
  }
}
