import type { IServiceCallResult, TEntityPlatform } from '../../core/types.js';

export const tplinkDefaultHttpPort = 80;
export const tplinkLegacyDiscoveryPort = 9999;
export const tplinkSmartDiscoveryPort = 20002;

export type TTplinkBrand = 'kasa' | 'tapo' | 'tplink' | string;
export type TTplinkProtocolFamily = 'iot' | 'smart' | 'tapo' | 'kasa' | 'snapshot' | 'manual' | string;
export type TTplinkDeviceKind =
  | 'plug'
  | 'strip'
  | 'switch'
  | 'dimmer'
  | 'bulb'
  | 'light_strip'
  | 'sensor'
  | 'hub'
  | 'camera'
  | 'fan'
  | 'thermostat'
  | 'vacuum'
  | 'unknown'
  | string;
export type TTplinkFeatureType =
  | 'switch'
  | 'sensor'
  | 'binary_sensor'
  | 'number'
  | 'choice'
  | 'action'
  | 'light'
  | 'fan'
  | 'climate'
  | string;

export interface ITplinkCredentials {
  username?: string;
  password?: string;
  credentialsHash?: string;
  aesKeys?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ITplinkConnectionParameters {
  deviceFamily?: string;
  encryptionType?: string;
  loginVersion?: number;
  usesHttp?: boolean;
  httpPort?: number;
  [key: string]: unknown;
}

export type ITplinkStateRecord = Record<string, unknown>;

export interface ITplinkFeature {
  id?: string;
  key?: string;
  name?: string;
  type?: TTplinkFeatureType;
  category?: 'primary' | 'config' | 'info' | 'debug' | string;
  value?: unknown;
  unit?: string;
  readable?: boolean;
  writable?: boolean;
  minimumValue?: number;
  maximumValue?: number;
  min?: number;
  max?: number;
  precisionHint?: number;
  choices?: string[];
  platform?: TEntityPlatform | string;
  deviceClass?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ITplinkModuleState {
  name?: string;
  features?: Record<string, ITplinkFeature> | ITplinkFeature[];
  state?: ITplinkStateRecord;
  [key: string]: unknown;
}

export interface ITplinkEntityDescriptor {
  id?: string;
  entityId?: string;
  uniqueId?: string;
  unique_id?: string;
  deviceId?: string;
  device_id?: string;
  platform?: TEntityPlatform | string;
  key?: string;
  name?: string;
  state?: unknown;
  value?: unknown;
  attributes?: Record<string, unknown>;
  available?: boolean;
  writable?: boolean;
  unit?: string;
  deviceClass?: string;
  device_class?: string;
  [key: string]: unknown;
}

export interface ITplinkDevice {
  id?: string;
  deviceId?: string;
  device_id?: string;
  parentId?: string;
  host?: string;
  port?: number;
  mac?: string;
  macAddress?: string;
  alias?: string;
  name?: string;
  model?: string;
  manufacturer?: string;
  brand?: TTplinkBrand;
  hwVersion?: string;
  swVersion?: string;
  firmwareVersion?: string;
  hardwareVersion?: string;
  serialNumber?: string;
  type?: TTplinkDeviceKind;
  kind?: TTplinkDeviceKind;
  deviceType?: TTplinkDeviceKind;
  device_type?: TTplinkDeviceKind;
  children?: ITplinkChildDevice[];
  features?: Record<string, ITplinkFeature> | ITplinkFeature[];
  modules?: Record<string, ITplinkModuleState>;
  state?: ITplinkStateRecord;
  sysInfo?: ITplinkStateRecord;
  systemInfo?: ITplinkStateRecord;
  lightState?: ITplinkStateRecord;
  emeter?: ITplinkStateRecord;
  sensors?: ITplinkFeature[];
  entities?: ITplinkEntityDescriptor[];
  available?: boolean;
  online?: boolean;
  updatedAt?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ITplinkChildDevice extends ITplinkDevice {}

export interface ITplinkTransportInfo {
  protocol: TTplinkProtocolFamily;
  host?: string;
  port?: number;
  credentialsConfigured?: boolean;
  connectionParameters?: ITplinkConnectionParameters;
  legacyXorImplemented: boolean;
  encryptedLocalProtocolImplemented: boolean;
  [key: string]: unknown;
}

export interface ITplinkSnapshot {
  connected: boolean;
  configured?: boolean;
  host?: string;
  port?: number;
  alias?: string;
  model?: string;
  macAddress?: string;
  devices: ITplinkDevice[];
  entities: ITplinkEntityDescriptor[];
  events: ITplinkEvent[];
  transport?: ITplinkTransportInfo;
  metadata?: Record<string, unknown>;
}

export interface ITplinkManualEntry {
  host?: string;
  port?: number;
  id?: string;
  deviceId?: string;
  macAddress?: string;
  mac?: string;
  alias?: string;
  name?: string;
  model?: string;
  manufacturer?: string;
  brand?: TTplinkBrand;
  deviceType?: TTplinkDeviceKind;
  state?: ITplinkStateRecord;
  features?: Record<string, ITplinkFeature> | ITplinkFeature[];
  device?: ITplinkDevice;
  devices?: ITplinkDevice[];
  snapshot?: ITplinkSnapshot;
  credentials?: ITplinkCredentials;
  metadata?: Record<string, unknown>;
  integrationDomain?: string;
  [key: string]: unknown;
}

export interface ITplinkConfig {
  host?: string;
  port?: number;
  alias?: string;
  name?: string;
  model?: string;
  macAddress?: string;
  deviceId?: string;
  deviceType?: TTplinkDeviceKind;
  brand?: TTplinkBrand;
  username?: string;
  password?: string;
  credentials?: ITplinkCredentials;
  credentialsHash?: string;
  aesKeys?: Record<string, unknown>;
  connectionParameters?: ITplinkConnectionParameters;
  usesHttp?: boolean;
  snapshot?: ITplinkSnapshot;
  device?: ITplinkDevice;
  devices?: ITplinkDevice[];
  manualEntries?: ITplinkManualEntry[];
  state?: ITplinkStateRecord;
  features?: Record<string, ITplinkFeature> | ITplinkFeature[];
  modules?: Record<string, ITplinkModuleState>;
  children?: ITplinkChildDevice[];
  entities?: ITplinkEntityDescriptor[];
  events?: ITplinkEvent[];
  timeoutMs?: number;
  commandExecutor?: TTplinkCommandExecutor;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHomeAssistantTplinkConfig extends ITplinkConfig {}

export interface ITplinkEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  uniqueId?: string;
  command?: ITplinkClientCommand;
  data?: unknown;
  [key: string]: unknown;
}

export interface ITplinkClientCommand {
  type: string;
  service: string;
  method?: string;
  platform?: TEntityPlatform | string;
  protocol?: TTplinkProtocolFamily;
  deviceId?: string;
  entityId?: string;
  uniqueId?: string;
  featureId?: string;
  value?: unknown;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  payload: Record<string, unknown>;
}

export interface ITplinkCommandResult extends IServiceCallResult {}

export type TTplinkCommandExecutor = (
  commandArg: ITplinkClientCommand
) => Promise<ITplinkCommandResult | unknown> | ITplinkCommandResult | unknown;

export interface ITplinkMdnsRecord {
  type?: string;
  serviceType?: string;
  name?: string;
  host?: string;
  hostname?: string;
  addresses?: string[];
  port?: number;
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
  macAddress?: string;
  model?: string;
  manufacturer?: string;
  [key: string]: unknown;
}

export interface ITplinkDhcpRecord {
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  hostname?: string;
  hostName?: string;
  macAddress?: string;
  mac?: string;
  manufacturer?: string;
  model?: string;
  vendorClassIdentifier?: string;
  integrationDomain?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ITplinkManualDiscoveryRecord extends ITplinkManualEntry {}
