import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import { SimpleLocalMapper, type IIntegrationEntity, type ISimpleLocalEntitySnapshot, type ISimpleLocalSnapshot, type ISimpleLocalSnapshotOptions, type TSimpleLocalRawData } from '../../core/index.js';
import type { IEdimaxConfig } from './edimax.types.js';
import { edimaxDefaultName, edimaxProfile } from './edimax.types.js';

export class EdimaxMapper {
  public static toSnapshot(optionsArg: Omit<ISimpleLocalSnapshotOptions<IEdimaxConfig>, 'profile'>): ISimpleLocalSnapshot {
    return SimpleLocalMapper.toSnapshot({
      ...optionsArg,
      profile: edimaxProfile,
      rawData: this.normalizeRawData(optionsArg.config, optionsArg.rawData),
    });
  }

  public static toSnapshotFromRaw(configArg: IEdimaxConfig, rawDataArg: TSimpleLocalRawData): ISimpleLocalSnapshot {
    return this.toSnapshot({ config: configArg, rawData: rawDataArg, online: true, source: 'manual' });
  }

  public static toDevices(snapshotArg: ISimpleLocalSnapshot): shxInterfaces.data.IDeviceDefinition[] {
    return SimpleLocalMapper.toDevices(edimaxProfile, snapshotArg);
  }

  public static toEntities(snapshotArg: ISimpleLocalSnapshot): IIntegrationEntity[] {
    return SimpleLocalMapper.toEntities(edimaxProfile, snapshotArg);
  }

  public static slug(valueArg: unknown): string {
    return SimpleLocalMapper.slug(valueArg);
  }

  private static normalizeRawData(configArg: IEdimaxConfig, rawDataArg: unknown): unknown {
    if (!isRecord(rawDataArg) || ('device' in rawDataArg && 'entities' in rawDataArg)) {
      return rawDataArg;
    }

    const info = recordValue(rawDataArg.info) || rawDataArg;
    const state = switchState(rawDataArg.state ?? rawDataArg.power ?? rawDataArg.is_on ?? rawDataArg.isOn);
    if (state === undefined) {
      return rawDataArg;
    }

    const host = configArg.host || stringValue(rawDataArg.host) || stringValue(info.host);
    const mac = stringValue(info.mac) || stringValue(rawDataArg.mac) || stringValue(info.macAddress) || stringValue(rawDataArg.macAddress);
    const name = configArg.name || stringValue(rawDataArg.name) || stringValue(info.name) || edimaxDefaultName;
    const entity: ISimpleLocalEntitySnapshot = {
      id: 'switch',
      uniqueId: `${edimaxProfile.domain}_${SimpleLocalMapper.slug(mac || host || name)}_switch`,
      name,
      platform: 'switch',
      state,
      available: true,
      writable: true,
      attributes: {
        mac,
        rawState: rawDataArg.state,
      },
    };

    return {
      device: {
        id: configArg.uniqueId || mac || (host ? `${host}:${configArg.port || ''}` : undefined) || name,
        name,
        manufacturer: edimaxProfile.manufacturer,
        model: stringValue(rawDataArg.model) || stringValue(info.model) || edimaxProfile.model,
        serialNumber: mac,
        host,
        port: configArg.port,
        protocol: edimaxProfile.defaultProtocol,
        attributes: {
          mac,
        },
      },
      entities: [entity],
      online: configArg.online ?? true,
      updatedAt: new Date().toISOString(),
      source: 'manual',
      rawData: rawDataArg,
    } satisfies ISimpleLocalSnapshot;
  }
}

const switchState = (valueArg: unknown): boolean | undefined => {
  if (typeof valueArg === 'boolean') {
    return valueArg;
  }
  if (typeof valueArg === 'number') {
    return valueArg !== 0;
  }
  const value = stringValue(valueArg)?.toUpperCase();
  if (!value) {
    return undefined;
  }
  if (['ON', 'TRUE', '1'].includes(value)) {
    return true;
  }
  if (['OFF', 'FALSE', '0'].includes(value)) {
    return false;
  }
  return undefined;
};

const recordValue = (valueArg: unknown): Record<string, unknown> | undefined => isRecord(valueArg) ? valueArg : undefined;

const isRecord = (valueArg: unknown): valueArg is Record<string, unknown> => Boolean(valueArg && typeof valueArg === 'object' && !Array.isArray(valueArg));

const stringValue = (valueArg: unknown): string | undefined => typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim() : undefined;
