import * as plugins from '../../plugins.js';
import type { IIntegrationEntity, IIntegrationEvent } from '../../core/types.js';
import type { ISamsungtvEvent, ISamsungtvSnapshot, ISamsungtvState } from './samsungtv.types.js';

export class SamsungtvMapper {
  public static toDevices(snapshotArg: ISamsungtvSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = new Date().toISOString();
    const state = this.state(snapshotArg);
    return [{
      id: this.deviceId(snapshotArg),
      integrationDomain: 'samsungtv',
      name: this.deviceName(snapshotArg),
      protocol: 'http',
      manufacturer: snapshotArg.deviceInfo.device?.manufacturer || 'Samsung',
      model: snapshotArg.deviceInfo.device?.modelName || snapshotArg.deviceInfo.device?.modelNumber,
      online: state.power !== 'off',
      features: [
        { id: 'power', capability: 'media', name: 'Power', readable: true, writable: true },
        { 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: 'remote_key', capability: 'media', name: 'Remote key', readable: false, writable: true },
      ],
      state: [
        { featureId: 'power', value: state.power, updatedAt },
        { featureId: 'playback', value: state.playback, updatedAt },
        { featureId: 'source', value: state.source ?? null, updatedAt },
        { featureId: 'volume', value: state.volumeLevel ?? null, updatedAt },
        { featureId: 'muted', value: state.muted ?? null, updatedAt },
      ],
      metadata: {
        id: snapshotArg.deviceInfo.id,
        udn: snapshotArg.deviceInfo.device?.udn,
        serialNumber: snapshotArg.deviceInfo.device?.serialNumber,
        macAddress: snapshotArg.deviceInfo.device?.wifiMac,
        frameTvSupport: snapshotArg.deviceInfo.device?.FrameTVSupport,
        apps: snapshotArg.apps.map((appArg) => ({ id: appArg.id, name: appArg.name, type: appArg.type })),
      },
    }];
  }

  public static toEntities(snapshotArg: ISamsungtvSnapshot): IIntegrationEntity[] {
    const state = this.state(snapshotArg);
    return [{
      id: `media_player.${this.slug(this.deviceName(snapshotArg))}`,
      uniqueId: `samsungtv_${this.slug(this.identity(snapshotArg))}`,
      integrationDomain: 'samsungtv',
      deviceId: this.deviceId(snapshotArg),
      platform: 'media_player',
      name: this.deviceName(snapshotArg),
      state: this.mediaState(state),
      attributes: {
        source: state.source,
        appId: state.appId,
        appName: state.appName,
        sourceList: this.sourceList(snapshotArg),
        volumeLevel: state.volumeLevel,
        isVolumeMuted: state.muted,
        mediaTitle: state.mediaTitle,
        model: snapshotArg.deviceInfo.device?.modelName || snapshotArg.deviceInfo.device?.modelNumber,
      },
      available: state.power !== 'off',
    }];
  }

  public static toIntegrationEvent(eventArg: ISamsungtvEvent): IIntegrationEvent {
    return {
      type: eventArg.type === 'error' ? 'error' : 'state_changed',
      integrationDomain: 'samsungtv',
      data: eventArg,
      timestamp: eventArg.timestamp,
    };
  }

  public static deviceId(snapshotArg: ISamsungtvSnapshot): string {
    return `samsungtv.device.${this.slug(this.identity(snapshotArg))}`;
  }

  private static state(snapshotArg: ISamsungtvSnapshot): Required<Pick<ISamsungtvState, 'power' | 'playback'>> & ISamsungtvState {
    const power = snapshotArg.state?.power ?? this.powerFromDeviceInfo(snapshotArg);
    const appId = snapshotArg.state?.appId ?? snapshotArg.activeApp?.id;
    const appName = snapshotArg.state?.appName ?? snapshotArg.activeApp?.name;
    const source = snapshotArg.state?.source ?? appName;
    return {
      ...(snapshotArg.state ?? {}),
      power,
      playback: snapshotArg.state?.playback ?? (power === 'off' ? 'off' : 'idle'),
      appId,
      appName,
      source,
    };
  }

  private static mediaState(stateArg: Required<Pick<ISamsungtvState, 'power' | 'playback'>> & ISamsungtvState): string {
    if (stateArg.power === 'off') {
      return 'off';
    }
    if (stateArg.playback === 'playing') {
      return 'playing';
    }
    if (stateArg.playback === 'paused') {
      return 'paused';
    }
    if (stateArg.power === 'unknown') {
      return 'unknown';
    }
    return stateArg.source ? 'on' : 'idle';
  }

  private static sourceList(snapshotArg: ISamsungtvSnapshot): string[] {
    return [...new Set(['TV', 'HDMI', ...snapshotArg.apps.map((appArg) => appArg.name)])];
  }

  private static powerFromDeviceInfo(snapshotArg: ISamsungtvSnapshot): 'on' | 'off' | 'unknown' {
    const value = String(snapshotArg.deviceInfo.device?.PowerState || '').toLowerCase();
    if (value === 'on') {
      return 'on';
    }
    if (value.includes('off') || value.includes('standby') || value.includes('sleep')) {
      return 'off';
    }
    return 'unknown';
  }

  private static deviceName(snapshotArg: ISamsungtvSnapshot): string {
    const name = snapshotArg.deviceInfo.device?.name || snapshotArg.deviceInfo.device?.modelName || 'Samsung Smart TV';
    return name.replace(/^\[TV\]\s*/i, '') || 'Samsung Smart TV';
  }

  private static identity(snapshotArg: ISamsungtvSnapshot): string {
    return snapshotArg.deviceInfo.id
      || snapshotArg.deviceInfo.device?.udn
      || snapshotArg.deviceInfo.device?.wifiMac
      || snapshotArg.deviceInfo.device?.serialNumber
      || this.deviceName(snapshotArg);
  }

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