import * as plugins from '../../plugins.js';
import type { IIntegrationEntity, IServiceCallRequest, TEntityPlatform } from '../../core/types.js';
import type {
  IHuaweiLteCommandRequest,
  IHuaweiLteConfig,
  IHuaweiLteHostSnapshot,
  IHuaweiLteRawData,
  IHuaweiLteSnapshot,
  IHuaweiLteValueMap,
  THuaweiLteRawDataKey,
  THuaweiLteSnapshotSource,
} from './huawei_lte.types.js';
import {
  huaweiLteDefaultDeviceName,
  huaweiLteDefaultHttpPort,
  huaweiLteDefaultHttpsPort,
  huaweiLteDefaultManufacturer,
  huaweiLteDisplayName,
  huaweiLteDomain,
} from './huawei_lte.types.js';

interface IHuaweiLteSnapshotOptions {
  config: IHuaweiLteConfig;
  rawData?: Partial<IHuaweiLteRawData>;
  online?: boolean;
  source?: THuaweiLteSnapshotSource;
  suspended?: boolean;
  error?: string;
}

interface IHuaweiLteEntityDefinition {
  key: string;
  name: string;
  value: unknown;
  platform?: TEntityPlatform;
  unit?: string;
  deviceClass?: string;
  stateClass?: string;
  entityCategory?: string;
  available?: boolean;
  attributes?: Record<string, unknown>;
}

const rawSensorGroups: Array<{ key: THuaweiLteRawDataKey; name: string; category?: string; exclude?: Set<string> }> = [
  { key: 'deviceInformation', name: 'Device', category: 'diagnostic', exclude: new Set(['DeviceName', 'SerialNumber', 'HardwareVersion', 'SoftwareVersion', 'MacAddress1', 'MacAddress2', 'WifiMacAddrWl0', 'WifiMacAddrWl1']) },
  { key: 'deviceBasicInformation', name: 'Device Basic', category: 'diagnostic', exclude: new Set(['devicename', 'SerialNumber', 'SoftwareVersion']) },
  { key: 'deviceSignal', name: 'Signal', category: 'diagnostic' },
  { key: 'monitoringCheckNotifications', name: 'Notifications' },
  { key: 'monitoringMonthStatistics', name: 'Month' },
  { key: 'monitoringStatus', name: 'Status', category: 'diagnostic' },
  { key: 'monitoringTrafficStatistics', name: 'Traffic' },
  { key: 'netCurrentPlmn', name: 'Network', category: 'diagnostic' },
  { key: 'netNetMode', name: 'Network Mode', category: 'diagnostic' },
  { key: 'smsSmsCount', name: 'SMS' },
];

const knownSensorUnits: Record<string, string> = {
  BatteryPercent: '%',
  CurrentConnectTime: 's',
  TotalConnectTime: 's',
  CurrentDownload: 'B',
  CurrentUpload: 'B',
  CurrentDownloadRate: 'B/s',
  CurrentUploadRate: 'B/s',
  MaxDownloadRate: 'B/s',
  MaxUploadRate: 'B/s',
  TotalDownload: 'B',
  TotalUpload: 'B',
  CurrentMonthDownload: 'B',
  CurrentMonthUpload: 'B',
  CurrentDayUsed: 'B',
  rssi: 'dBm',
  rsrp: 'dBm',
  nrrsrp: 'dBm',
  rsrq: 'dB',
  nrrsrq: 'dB',
  sinr: 'dB',
  nrsinr: 'dB',
};

const knownDeviceClasses: Record<string, string> = {
  BatteryPercent: 'battery',
  CurrentDownload: 'data_size',
  CurrentUpload: 'data_size',
  TotalDownload: 'data_size',
  TotalUpload: 'data_size',
  CurrentMonthDownload: 'data_size',
  CurrentMonthUpload: 'data_size',
  CurrentDayUsed: 'data_size',
  CurrentDownloadRate: 'data_rate',
  CurrentUploadRate: 'data_rate',
  MaxDownloadRate: 'data_rate',
  MaxUploadRate: 'data_rate',
  CurrentConnectTime: 'duration',
  TotalConnectTime: 'duration',
  rssi: 'signal_strength',
  rsrp: 'signal_strength',
  nrrsrp: 'signal_strength',
  rsrq: 'signal_strength',
  nrrsrq: 'signal_strength',
  sinr: 'signal_strength',
  nrsinr: 'signal_strength',
};

const networkModeOptions = ['00', '0302', '0301', '03', '0201', '02', '01'];

export class HuaweiLteMapper {
  public static toSnapshot(optionsArg: IHuaweiLteSnapshotOptions): IHuaweiLteSnapshot {
    if (optionsArg.config.snapshot && !optionsArg.rawData) {
      return this.normalizeSnapshot(this.clone(optionsArg.config.snapshot), optionsArg.config, optionsArg.source || 'snapshot', optionsArg.suspended);
    }

    const rawData = this.rawData(optionsArg.config, optionsArg.rawData);
    const hasData = this.hasRawData(rawData);
    const device = this.deviceInfo(optionsArg.config, rawData);
    const connection = this.connection(rawData);
    const signal = this.signal(rawData.deviceSignal || {});
    const traffic = this.traffic(rawData);
    const sms = this.sms(rawData);
    const network = this.network(rawData);
    const hosts = this.hosts(rawData);
    const online = optionsArg.online ?? optionsArg.config.online ?? hasData;
    const source = optionsArg.source || (hasData ? 'manual' : 'runtime');
    const localControl = Boolean(optionsArg.config.url || optionsArg.config.host || optionsArg.config.commandExecutor || optionsArg.config.client?.execute);

    return {
      device,
      connection,
      signal,
      traffic,
      sms,
      network,
      hosts,
      capabilities: {
        localControl,
        mobileDataSwitch: localControl && connection.mobileDataEnabled !== undefined,
        guestWifiSwitch: localControl && connection.guestWifiEnabled !== undefined,
        reboot: localControl,
        clearTraffic: localControl,
        sendSms: localControl,
        networkModeSelect: localControl && network.networkMode !== undefined,
      },
      rawData: hasData ? this.clone(rawData) : undefined,
      online,
      updatedAt: rawData.fetchedAt || new Date().toISOString(),
      source,
      suspended: optionsArg.suspended,
      error: optionsArg.error,
    };
  }

  public static toDevices(snapshotArg: IHuaweiLteSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] {
    const updatedAt = snapshotArg.updatedAt || new Date().toISOString();
    const features: plugins.shxInterfaces.data.IDeviceFeature[] = [
      { id: 'mobile_connection', capability: 'sensor', name: 'Mobile connection', readable: true, writable: false },
      { id: 'mobile_data', capability: 'switch', name: 'Mobile data', readable: true, writable: snapshotArg.capabilities.mobileDataSwitch },
      { id: 'wifi_status', capability: 'sensor', name: 'WiFi status', readable: true, writable: false },
      { id: 'host_count', capability: 'sensor', name: 'Connected clients', readable: true, writable: false },
    ];
    const state: plugins.shxInterfaces.data.IDeviceState[] = [
      { featureId: 'mobile_connection', value: snapshotArg.connection.mobileConnected ?? null, updatedAt },
      { featureId: 'mobile_data', value: snapshotArg.connection.mobileDataEnabled ?? null, updatedAt },
      { featureId: 'wifi_status', value: snapshotArg.connection.wifiEnabled ?? null, updatedAt },
      { featureId: 'host_count', value: snapshotArg.hosts.filter((hostArg) => hostArg.active).length, updatedAt },
    ];

    for (const key of ['rsrp', 'rsrq', 'sinr', 'nrrsrp', 'nrrsrq', 'nrsinr'] as const) {
      const value = snapshotArg.signal[key];
      if (value === undefined) {
        continue;
      }
      features.push({ id: key, capability: 'sensor', name: this.humanName(key), readable: true, writable: false, unit: knownSensorUnits[key] });
      state.push({ featureId: key, value, updatedAt });
    }
    if (snapshotArg.traffic.currentDownloadRate !== undefined) {
      features.push({ id: 'current_download_rate', capability: 'sensor', name: 'Current download rate', readable: true, writable: false, unit: 'B/s' });
      state.push({ featureId: 'current_download_rate', value: snapshotArg.traffic.currentDownloadRate, updatedAt });
    }
    if (snapshotArg.sms.unread !== undefined) {
      features.push({ id: 'sms_unread', capability: 'sensor', name: 'Unread SMS', readable: true, writable: false });
      state.push({ featureId: 'sms_unread', value: snapshotArg.sms.unread, updatedAt });
    }
    if (snapshotArg.capabilities.sendSms) {
      features.push({ id: 'send_sms', capability: 'notification', name: 'Send SMS', readable: false, writable: true });
    }

    return [{
      id: this.deviceId(snapshotArg),
      integrationDomain: huaweiLteDomain,
      name: snapshotArg.device.name,
      protocol: snapshotArg.device.host ? 'http' : 'unknown',
      manufacturer: snapshotArg.device.manufacturer,
      model: snapshotArg.device.model || huaweiLteDisplayName,
      online: snapshotArg.online && !snapshotArg.suspended,
      features,
      state,
      metadata: this.cleanAttributes({
        host: snapshotArg.device.host,
        port: snapshotArg.device.port,
        url: snapshotArg.device.url,
        serialNumber: snapshotArg.device.serialNumber,
        macAddresses: snapshotArg.device.macAddresses,
        hardwareVersion: snapshotArg.device.hardwareVersion,
        softwareVersion: snapshotArg.device.softwareVersion,
        upnpUdn: snapshotArg.device.upnpUdn,
        source: snapshotArg.source,
        suspended: snapshotArg.suspended,
        error: snapshotArg.error,
      }),
    }];
  }

  public static toEntities(snapshotArg: IHuaweiLteSnapshot): IIntegrationEntity[] {
    const deviceId = this.deviceId(snapshotArg);
    const uniqueBase = this.uniqueBase(snapshotArg);
    const baseName = snapshotArg.device.name;
    const entities: IIntegrationEntity[] = [];

    this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
      key: 'mobile_connection',
      name: `${baseName} Mobile Connection`,
      platform: 'binary_sensor',
      value: snapshotArg.connection.mobileConnected ? 'on' : 'off',
      deviceClass: 'connectivity',
      attributes: { key: 'mobile_connection', rawState: snapshotArg.connection.connectionStatus },
      available: snapshotArg.connection.mobileConnected !== undefined,
    });
    this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
      key: 'wifi_status',
      name: `${baseName} WiFi Status`,
      platform: 'binary_sensor',
      value: snapshotArg.connection.wifiEnabled ? 'on' : 'off',
      deviceClass: 'connectivity',
      attributes: { key: 'wifi_status' },
      available: snapshotArg.connection.wifiEnabled !== undefined,
    });
    this.pushBooleanEntity(entities, snapshotArg, deviceId, uniqueBase, 'wifi_24ghz_status', `${baseName} 2.4GHz WiFi Status`, snapshotArg.connection.wifi24ghzEnabled);
    this.pushBooleanEntity(entities, snapshotArg, deviceId, uniqueBase, 'wifi_5ghz_status', `${baseName} 5GHz WiFi Status`, snapshotArg.connection.wifi5ghzEnabled);
    this.pushBooleanEntity(entities, snapshotArg, deviceId, uniqueBase, 'sms_storage_full', `${baseName} SMS Storage Full`, snapshotArg.connection.smsStorageFull);

    if (snapshotArg.connection.mobileDataEnabled !== undefined) {
      this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
        key: 'mobile_data',
        name: `${baseName} Mobile Data`,
        platform: 'switch',
        value: snapshotArg.connection.mobileDataEnabled ? 'on' : 'off',
        attributes: { key: 'mobile_data', writable: snapshotArg.capabilities.mobileDataSwitch },
      });
    }
    if (snapshotArg.connection.guestWifiEnabled !== undefined) {
      this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
        key: 'wifi_guest_network',
        name: `${baseName} WiFi Guest Network`,
        platform: 'switch',
        value: snapshotArg.connection.guestWifiEnabled ? 'on' : 'off',
        attributes: { key: 'wifi_guest_network', writable: snapshotArg.capabilities.guestWifiSwitch },
      });
    }

    for (const definition of this.sensorDefinitions(snapshotArg)) {
      this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, definition);
    }

    if (snapshotArg.network.networkMode !== undefined) {
      this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
        key: 'preferred_network_mode',
        name: `${baseName} Preferred Network Mode`,
        platform: 'select',
        value: snapshotArg.network.networkMode,
        entityCategory: 'config',
        attributes: { key: 'preferred_network_mode', options: networkModeOptions, writable: snapshotArg.capabilities.networkModeSelect },
      });
    }

    this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
      key: 'clear_traffic_statistics',
      name: `${baseName} Clear Traffic Statistics`,
      platform: 'button',
      value: 'available',
      entityCategory: 'config',
      attributes: { key: 'clear_traffic_statistics', writable: snapshotArg.capabilities.clearTraffic },
      available: snapshotArg.online && snapshotArg.capabilities.clearTraffic,
    });
    this.pushEntity(entities, snapshotArg, deviceId, uniqueBase, {
      key: 'restart',
      name: `${baseName} Restart`,
      platform: 'button',
      value: 'available',
      entityCategory: 'config',
      attributes: { key: 'restart', writable: snapshotArg.capabilities.reboot },
      available: snapshotArg.online && snapshotArg.capabilities.reboot,
    });

    return entities.filter((entityArg) => entityArg.available || entityArg.state !== undefined);
  }

  public static commandForService(snapshotArg: IHuaweiLteSnapshot, requestArg: IServiceCallRequest): IHuaweiLteCommandRequest | undefined {
    if (requestArg.domain === huaweiLteDomain) {
      if (requestArg.service === 'refresh') {
        return { action: 'refresh', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'set_mobile_dataswitch') {
        const enabled = this.booleanValue(requestArg.data?.enabled ?? requestArg.data?.dataswitch ?? requestArg.data?.state);
        return enabled === undefined ? undefined : { action: 'set_mobile_dataswitch', enabled, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'set_wifi_guest_network') {
        const enabled = this.booleanValue(requestArg.data?.enabled ?? requestArg.data?.state);
        return enabled === undefined ? undefined : { action: 'set_wifi_guest_network', enabled, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'reboot' || requestArg.service === 'restart') {
        return { action: 'reboot', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'clear_traffic' || requestArg.service === 'clear_traffic_statistics') {
        return { action: 'clear_traffic', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'send_sms') {
        const message = this.stringValue(requestArg.data?.message);
        const phoneNumbers = this.stringList(requestArg.data?.phone_numbers ?? requestArg.data?.phoneNumbers ?? requestArg.data?.target ?? requestArg.data?.recipients);
        return { action: 'send_sms', phoneNumbers, message, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'set_net_mode') {
        const networkMode = this.stringValue(requestArg.data?.network_mode ?? requestArg.data?.networkMode);
        return networkMode ? { action: 'set_net_mode', networkMode, service: requestArg.service, target: requestArg.target, data: requestArg.data } : undefined;
      }
      if (requestArg.service === 'suspend_integration') {
        return { action: 'suspend_integration', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (requestArg.service === 'resume_integration') {
        return { action: 'resume_integration', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
    }

    if (requestArg.domain === 'switch') {
      const enabled = requestArg.service === 'turn_on' ? true : requestArg.service === 'turn_off' ? false : undefined;
      if (enabled === undefined) {
        return undefined;
      }
      const target = `${requestArg.target.entityId || ''} ${requestArg.target.deviceId || ''}`.toLowerCase();
      if (target.includes('guest')) {
        return { action: 'set_wifi_guest_network', enabled, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (target.includes('mobile') || target.includes('dataswitch') || target.includes('data')) {
        return { action: 'set_mobile_dataswitch', enabled, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
    }

    if (requestArg.domain === 'button' && requestArg.service === 'press') {
      const target = `${requestArg.target.entityId || ''} ${requestArg.target.deviceId || ''}`.toLowerCase();
      if (target.includes('clear') || target.includes('traffic')) {
        return { action: 'clear_traffic', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
      if (target.includes('restart') || target.includes('reboot')) {
        return { action: 'reboot', service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
    }

    if (requestArg.domain === 'select' && requestArg.service === 'select_option') {
      const target = `${requestArg.target.entityId || ''} ${requestArg.target.deviceId || ''}`.toLowerCase();
      const option = this.stringValue(requestArg.data?.option);
      if (option && target.includes('network')) {
        return { action: 'set_net_mode', networkMode: option, service: requestArg.service, target: requestArg.target, data: requestArg.data };
      }
    }

    void snapshotArg;
    return undefined;
  }

  public static deviceId(snapshotArg: IHuaweiLteSnapshot): string {
    return `${huaweiLteDomain}.router.${this.uniqueBase(snapshotArg)}`;
  }

  public static snapshotId(snapshotArg: IHuaweiLteSnapshot): string | undefined {
    return snapshotArg.device.serialNumber || snapshotArg.device.upnpUdn || snapshotArg.device.macAddresses[0] || snapshotArg.device.host;
  }

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

  public static normalizeMac(valueArg: unknown): string | undefined {
    const value = this.stringValue(valueArg);
    if (!value) {
      return undefined;
    }
    const compact = value.replace(/[^a-fA-F0-9]/g, '').toLowerCase();
    return compact.length === 12 ? compact.match(/.{1,2}/g)?.join(':') : value.toLowerCase();
  }

  public static getDeviceMacs(deviceInfoArg: IHuaweiLteValueMap = {}, wlanSettingsArg: IHuaweiLteValueMap = {}): string[] {
    const values: unknown[] = [
      deviceInfoArg.MacAddress1,
      deviceInfoArg.MacAddress2,
      deviceInfoArg.WifiMacAddrWl0,
      deviceInfoArg.WifiMacAddrWl1,
    ];
    for (const ssid of this.asArray(this.objectValue(wlanSettingsArg.Ssids)?.Ssid)) {
      values.push(this.objectValue(ssid)?.WifiMac);
    }
    return [...new Set(values.map((valueArg) => this.normalizeMac(valueArg)).filter(Boolean) as string[])].sort();
  }

  private static normalizeSnapshot(snapshotArg: IHuaweiLteSnapshot, configArg: IHuaweiLteConfig, sourceArg: THuaweiLteSnapshotSource, suspendedArg?: boolean): IHuaweiLteSnapshot {
    const rawData = this.rawData(configArg, snapshotArg.rawData);
    const derived = this.toSnapshot({ config: { ...configArg, snapshot: undefined }, rawData, online: snapshotArg.online, source: sourceArg, suspended: suspendedArg ?? snapshotArg.suspended, error: snapshotArg.error });
    return {
      ...derived,
      ...snapshotArg,
      device: { ...derived.device, ...snapshotArg.device },
      connection: { ...derived.connection, ...snapshotArg.connection },
      signal: { ...derived.signal, ...snapshotArg.signal },
      traffic: { ...derived.traffic, ...snapshotArg.traffic },
      sms: { ...derived.sms, ...snapshotArg.sms },
      network: { ...derived.network, ...snapshotArg.network },
      capabilities: { ...derived.capabilities, ...snapshotArg.capabilities },
      hosts: snapshotArg.hosts?.length ? snapshotArg.hosts : derived.hosts,
      rawData: this.hasRawData(rawData) ? rawData : snapshotArg.rawData,
      source: snapshotArg.source || sourceArg,
      updatedAt: snapshotArg.updatedAt || new Date().toISOString(),
      suspended: suspendedArg ?? snapshotArg.suspended,
    };
  }

  private static rawData(configArg: IHuaweiLteConfig, rawDataArg?: Partial<IHuaweiLteRawData>): IHuaweiLteRawData {
    const resources = this.cleanAttributes({ ...configArg.rawData?.resources, ...rawDataArg?.resources }) as Partial<Record<THuaweiLteRawDataKey, IHuaweiLteValueMap>>;
    const rawData = this.cleanAttributes({
      ...configArg.rawData,
      ...rawDataArg,
      resources,
      errors: this.cleanAttributes({ ...configArg.rawData?.errors, ...rawDataArg?.errors }),
      fetchedAt: rawDataArg?.fetchedAt || configArg.rawData?.fetchedAt,
    }) as IHuaweiLteRawData;
    for (const [key, value] of Object.entries(resources)) {
      if (value && !(key in rawData)) {
        (rawData as Record<string, unknown>)[key] = value;
      }
    }
    return rawData;
  }

  private static deviceInfo(configArg: IHuaweiLteConfig, rawDataArg: IHuaweiLteRawData): IHuaweiLteSnapshot['device'] {
    const parsed = this.parseEndpoint(configArg.url || configArg.host);
    const host = parsed?.hostname || (configArg.url ? undefined : configArg.host);
    const ssl = configArg.ssl ?? parsed?.ssl;
    const port = configArg.port || parsed?.port || (host ? ssl ? huaweiLteDefaultHttpsPort : huaweiLteDefaultHttpPort : undefined);
    const url = configArg.url || (host ? `${ssl ? 'https' : 'http'}://${this.hostForUrl(host)}${port && port !== (ssl ? huaweiLteDefaultHttpsPort : huaweiLteDefaultHttpPort) ? `:${port}` : ''}/` : undefined);
    const info = rawDataArg.deviceInformation || {};
    const basic = rawDataArg.deviceBasicInformation || {};
    const wlan = rawDataArg.wlanMultiBasicSettings || {};
    const macAddresses = [...new Set([...(configArg.macAddresses || []), configArg.macAddress, ...this.getDeviceMacs(info, wlan)].map((valueArg) => this.normalizeMac(valueArg)).filter(Boolean) as string[])].sort();
    const serialNumber = configArg.serialNumber || this.stringValue(info.SerialNumber || basic.SerialNumber || basic.serialnumber);
    const name = configArg.name || this.stringValue(info.DeviceName || basic.devicename || basic.DeviceName) || host || huaweiLteDefaultDeviceName;
    const model = configArg.model || this.stringValue(info.DeviceName || basic.devicename || basic.ProductFamily || basic.Classify);
    return {
      id: configArg.uniqueId || serialNumber || configArg.upnpUdn || macAddresses[0] || (host ? `${host}:${port || huaweiLteDefaultHttpPort}` : undefined) || name,
      name,
      manufacturer: configArg.manufacturer || huaweiLteDefaultManufacturer,
      model,
      serialNumber,
      hardwareVersion: this.stringValue(info.HardwareVersion || basic.HardwareVersion),
      softwareVersion: this.stringValue(info.SoftwareVersion || basic.SoftwareVersion),
      host,
      port,
      url,
      ssl,
      verifySsl: configArg.verifySsl,
      macAddresses,
      upnpUdn: configArg.upnpUdn,
    };
  }

  private static connection(rawDataArg: IHuaweiLteRawData): IHuaweiLteSnapshot['connection'] {
    const monitoring = rawDataArg.monitoringStatus || {};
    const notifications = rawDataArg.monitoringCheckNotifications || {};
    const wifi = rawDataArg.wlanWifiFeatureSwitch || {};
    const dialup = rawDataArg.dialupMobileDataswitch || {};
    const guest = rawDataArg.wlanWifiGuestNetworkSwitch || {};
    const connectionStatus = this.stringValue(monitoring.ConnectionStatus);
    const connectionNumber = this.numberValue(connectionStatus);
    return this.cleanAttributes({
      mobileConnected: connectionNumber === 901 || connectionNumber === 903 ? true : connectionNumber === undefined ? undefined : false,
      connectionStatus,
      mobileDataEnabled: this.booleanString(dialup.dataswitch),
      wifiEnabled: this.booleanString(monitoring.WifiStatus),
      wifi24ghzEnabled: this.booleanString(wifi.wifi24g_switch_enable),
      wifi5ghzEnabled: this.booleanString(wifi.wifi5g_enabled),
      guestWifiEnabled: this.booleanString(guest.WifiEnable),
      smsStorageFull: notifications.SmsStorageFull === undefined ? undefined : this.numberValue(notifications.SmsStorageFull) !== 0,
    }) as IHuaweiLteSnapshot['connection'];
  }

  private static signal(valuesArg: IHuaweiLteValueMap): IHuaweiLteSnapshot['signal'] {
    const signal: IHuaweiLteSnapshot['signal'] = { values: this.cleanAttributes({ ...valuesArg }) };
    for (const key of ['rssi', 'rsrp', 'rsrq', 'sinr', 'nrrsrp', 'nrrsrq', 'nrsinr'] as const) {
      const value = this.numberValue(valuesArg[key]);
      if (value !== undefined) {
        signal[key] = value;
      }
    }
    return signal;
  }

  private static traffic(rawDataArg: IHuaweiLteRawData): IHuaweiLteSnapshot['traffic'] {
    const traffic = rawDataArg.monitoringTrafficStatistics || {};
    const month = rawDataArg.monitoringMonthStatistics || {};
    return this.cleanAttributes({
      currentDownload: this.numberValue(traffic.CurrentDownload),
      currentUpload: this.numberValue(traffic.CurrentUpload),
      currentDownloadRate: this.numberValue(traffic.CurrentDownloadRate),
      currentUploadRate: this.numberValue(traffic.CurrentUploadRate),
      totalDownload: this.numberValue(traffic.TotalDownload),
      totalUpload: this.numberValue(traffic.TotalUpload),
      currentConnectTime: this.numberValue(traffic.CurrentConnectTime),
      totalConnectTime: this.numberValue(traffic.TotalConnectTime),
      currentMonthDownload: this.numberValue(month.CurrentMonthDownload),
      currentMonthUpload: this.numberValue(month.CurrentMonthUpload),
      currentDayUsed: this.numberValue(month.CurrentDayUsed),
    }) as IHuaweiLteSnapshot['traffic'];
  }

  private static sms(rawDataArg: IHuaweiLteRawData): IHuaweiLteSnapshot['sms'] {
    const smsCount = rawDataArg.smsSmsCount || {};
    const notifications = rawDataArg.monitoringCheckNotifications || {};
    return this.cleanAttributes({
      unread: this.numberValue(notifications.UnreadMessage ?? smsCount.LocalUnread),
      localUnread: this.numberValue(smsCount.LocalUnread),
      localInbox: this.numberValue(smsCount.LocalInbox),
      localOutbox: this.numberValue(smsCount.LocalOutbox),
      localDraft: this.numberValue(smsCount.LocalDraft),
      localMax: this.numberValue(smsCount.LocalMax),
      simUnread: this.numberValue(smsCount.SimUnread),
      simInbox: this.numberValue(smsCount.SimInbox),
      simOutbox: this.numberValue(smsCount.SimOutbox),
      simDraft: this.numberValue(smsCount.SimDraft),
      simMax: this.numberValue(smsCount.SimMax),
    }) as IHuaweiLteSnapshot['sms'];
  }

  private static network(rawDataArg: IHuaweiLteRawData): IHuaweiLteSnapshot['network'] {
    const plmn = rawDataArg.netCurrentPlmn || {};
    const netMode = rawDataArg.netNetMode || {};
    return this.cleanAttributes({
      operatorName: this.stringValue(plmn.FullName || plmn.ShortName || plmn.Spn),
      operatorCode: this.stringValue(plmn.Numeric),
      operatorSearchMode: this.stringValue(plmn.State),
      networkMode: this.stringValue(netMode.NetworkMode),
    }) as IHuaweiLteSnapshot['network'];
  }

  private static hosts(rawDataArg: IHuaweiLteRawData): IHuaweiLteHostSnapshot[] {
    const source = rawDataArg.lanHostInfo || rawDataArg.wlanHostList || {};
    const hosts = this.asArray(this.objectValue(source.Hosts)?.Host);
    return hosts.map((hostArg) => this.objectValue(hostArg)).filter(Boolean).map((hostArg) => {
      const macAddress = this.normalizeMac(hostArg!.MacAddress) || this.stringValue(hostArg!.MacAddress) || '';
      const hostname = this.stringValue(hostArg!.HostName);
      const ipAddress = this.stringValue(hostArg!.IpAddress)?.split(';', 2)[0] || undefined;
      const interfaceType = this.stringValue(hostArg!.InterfaceType || 'Wireless');
      return this.cleanAttributes({
        id: macAddress || hostname || ipAddress || 'unknown',
        macAddress,
        hostname,
        ipAddress,
        active: this.stringValue(hostArg!.Active || '1') !== '0',
        wireless: interfaceType !== 'Ethernet',
        isLocalDevice: this.stringValue(hostArg!.isLocalDevice || '0') === '1',
        attributes: this.cleanAttributes({
          addressSource: hostArg!.AddressSource,
          associatedSsid: hostArg!.AssociatedSsid,
          interfaceType,
        }),
      }) as IHuaweiLteHostSnapshot;
    }).filter((hostArg) => Boolean(hostArg.macAddress || hostArg.hostname || hostArg.ipAddress));
  }

  private static sensorDefinitions(snapshotArg: IHuaweiLteSnapshot): IHuaweiLteEntityDefinition[] {
    const definitions: IHuaweiLteEntityDefinition[] = [];
    definitions.push({
      key: 'host_count',
      name: `${snapshotArg.device.name} Connected Clients`,
      value: snapshotArg.hosts.filter((hostArg) => hostArg.active).length,
      unit: undefined,
      stateClass: 'measurement',
      attributes: { key: 'host_count', trackedHosts: snapshotArg.hosts.length },
    });
    for (const group of rawSensorGroups) {
      const items = snapshotArg.rawData?.[group.key];
      if (!items) {
        continue;
      }
      for (const [item, rawValue] of Object.entries(items)) {
        if (group.exclude?.has(item) || !this.isScalar(rawValue)) {
          continue;
        }
        const formatted = this.formatSensorValue(item, rawValue);
        if (formatted.value === undefined || formatted.value === null || formatted.value === '') {
          continue;
        }
        definitions.push({
          key: `${group.key}_${item}`,
          name: `${snapshotArg.device.name} ${group.name} ${this.humanName(item)}`,
          value: formatted.value,
          unit: formatted.unit,
          deviceClass: knownDeviceClasses[item],
          stateClass: typeof formatted.value === 'number' ? 'measurement' : undefined,
          entityCategory: group.category,
          attributes: { rawKey: group.key, item, rawValue },
        });
      }
    }
    return definitions;
  }

  private static pushBooleanEntity(entitiesArg: IIntegrationEntity[], snapshotArg: IHuaweiLteSnapshot, deviceIdArg: string, uniqueBaseArg: string, keyArg: string, nameArg: string, valueArg: boolean | undefined): void {
    if (valueArg === undefined) {
      return;
    }
    this.pushEntity(entitiesArg, snapshotArg, deviceIdArg, uniqueBaseArg, {
      key: keyArg,
      name: nameArg,
      platform: 'binary_sensor',
      value: valueArg ? 'on' : 'off',
      deviceClass: 'connectivity',
      attributes: { key: keyArg },
    });
  }

  private static pushEntity(entitiesArg: IIntegrationEntity[], snapshotArg: IHuaweiLteSnapshot, deviceIdArg: string, uniqueBaseArg: string, definitionArg: IHuaweiLteEntityDefinition): void {
    const platform = definitionArg.platform || 'sensor';
    entitiesArg.push({
      id: `${platform}.${this.slug(definitionArg.name)}`,
      uniqueId: `${huaweiLteDomain}_${uniqueBaseArg}_${this.slug(definitionArg.key)}`,
      integrationDomain: huaweiLteDomain,
      deviceId: deviceIdArg,
      platform,
      name: definitionArg.name,
      state: this.stateValue(definitionArg.value),
      attributes: this.cleanAttributes({
        key: definitionArg.key,
        unitOfMeasurement: definitionArg.unit,
        deviceClass: definitionArg.deviceClass,
        stateClass: definitionArg.stateClass,
        entityCategory: definitionArg.entityCategory,
        source: snapshotArg.source,
        error: snapshotArg.error,
        ...definitionArg.attributes,
      }),
      available: definitionArg.available ?? (snapshotArg.online && !snapshotArg.suspended && definitionArg.value !== undefined && definitionArg.value !== null),
    });
  }

  private static uniqueBase(snapshotArg: IHuaweiLteSnapshot): string {
    return this.slug(snapshotArg.device.serialNumber || snapshotArg.device.upnpUdn || snapshotArg.device.macAddresses[0] || snapshotArg.device.id || snapshotArg.device.host || snapshotArg.device.name);
  }

  private static formatSensorValue(keyArg: string, valueArg: unknown): { value: unknown; unit?: string } {
    const parsed = this.numberWithUnit(valueArg);
    if (parsed) {
      return { value: parsed.value, unit: knownSensorUnits[keyArg] || parsed.unit };
    }
    const number = this.numberValue(valueArg);
    if (number !== undefined && String(valueArg).trim() === String(number)) {
      return { value: number, unit: knownSensorUnits[keyArg] };
    }
    return { value: valueArg, unit: knownSensorUnits[keyArg] };
  }

  private static numberWithUnit(valueArg: unknown): { value: number; unit?: string } | undefined {
    if (typeof valueArg !== 'string') {
      return undefined;
    }
    const match = valueArg.trim().match(/^(?:[<>]=?)?\s*(-?\d+(?:\.\d+)?)\s*([a-zA-Z/%]+)$/);
    if (!match) {
      return undefined;
    }
    const value = Number(match[1]);
    return Number.isFinite(value) ? { value, unit: match[2] } : undefined;
  }

  private static stateValue(valueArg: unknown): unknown {
    return valueArg instanceof Date ? valueArg.toISOString() : valueArg;
  }

  private static parseEndpoint(valueArg: string | undefined): { hostname: string; port?: number; ssl: boolean } | undefined {
    if (!valueArg) {
      return undefined;
    }
    const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(valueArg) ? valueArg : `http://${valueArg}`;
    try {
      const url = new URL(withScheme);
      return { hostname: url.hostname, port: url.port ? Number(url.port) : undefined, ssl: url.protocol === 'https:' };
    } catch {
      return undefined;
    }
  }

  private static booleanString(valueArg: unknown): boolean | undefined {
    if (valueArg === undefined || valueArg === null || valueArg === '') {
      return undefined;
    }
    if (typeof valueArg === 'boolean') {
      return valueArg;
    }
    const value = String(valueArg).trim().toLowerCase();
    if (['1', 'true', 'on', 'yes', 'connected'].includes(value)) {
      return true;
    }
    if (['0', 'false', 'off', 'no', 'disconnected'].includes(value)) {
      return false;
    }
    return undefined;
  }

  private static booleanValue(valueArg: unknown): boolean | undefined {
    if (typeof valueArg === 'boolean') {
      return valueArg;
    }
    if (typeof valueArg === 'number' && Number.isFinite(valueArg)) {
      return valueArg !== 0;
    }
    return this.booleanString(valueArg);
  }

  private static numberValue(valueArg: unknown): number | undefined {
    if (typeof valueArg === 'number' && Number.isFinite(valueArg)) {
      return valueArg;
    }
    if (typeof valueArg === 'string' && valueArg.trim()) {
      const match = valueArg.trim().match(/^-?\d+(?:\.\d+)?/);
      if (match) {
        const parsed = Number(match[0]);
        return Number.isFinite(parsed) ? parsed : undefined;
      }
    }
    return undefined;
  }

  private static stringValue(valueArg: unknown): string | undefined {
    if (typeof valueArg === 'string') {
      return valueArg.trim() || undefined;
    }
    if (typeof valueArg === 'number' || typeof valueArg === 'boolean') {
      return String(valueArg);
    }
    return undefined;
  }

  private static stringList(valueArg: unknown): string[] | undefined {
    if (Array.isArray(valueArg)) {
      return valueArg.map((itemArg) => this.stringValue(itemArg)).filter(Boolean) as string[];
    }
    const value = this.stringValue(valueArg);
    return value ? value.split(',').map((itemArg) => itemArg.trim()).filter(Boolean) : undefined;
  }

  private static humanName(valueArg: string): string {
    return valueArg
      .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
      .replace(/[_-]+/g, ' ')
      .replace(/\b\w/g, (matchArg) => matchArg.toUpperCase())
      .replace(/\bSms\b/g, 'SMS')
      .replace(/\bWifi\b/g, 'WiFi')
      .trim();
  }

  private static hostForUrl(hostArg: string): string {
    return hostArg.includes(':') && !hostArg.startsWith('[') ? `[${hostArg}]` : hostArg;
  }

  private static objectValue(valueArg: unknown): IHuaweiLteValueMap | undefined {
    return valueArg && typeof valueArg === 'object' && !Array.isArray(valueArg) ? valueArg as IHuaweiLteValueMap : undefined;
  }

  private static asArray(valueArg: unknown): unknown[] {
    if (Array.isArray(valueArg)) {
      return valueArg;
    }
    if (valueArg === undefined || valueArg === null || valueArg === '') {
      return [];
    }
    return [valueArg];
  }

  private static isScalar(valueArg: unknown): boolean {
    return valueArg === null || ['string', 'number', 'boolean'].includes(typeof valueArg);
  }

  private static hasRawData(rawDataArg: IHuaweiLteRawData | undefined): boolean {
    if (!rawDataArg) {
      return false;
    }
    return Object.entries(rawDataArg).some(([key, value]) => key !== 'errors' && key !== 'fetchedAt' && key !== 'resources' && value && typeof value === 'object' && Object.keys(value).length > 0);
  }

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

  private static clone<TValue>(valueArg: TValue): TValue {
    return JSON.parse(JSON.stringify(valueArg)) as TValue;
  }
}
