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

export type TKnxConnectionType =
  | 'automatic'
  | 'routing'
  | 'routing_secure'
  | 'tunneling'
  | 'tunneling_tcp'
  | 'tunneling_tcp_secure'
  | string;

export type TKnxGroupAddress = string;
export type TKnxTelegramAction = 'read' | 'write' | 'response';
export type TKnxEntityPlatform = TEntityPlatform | string;

export interface IKnxConfig extends IKnxConnectionConfig {
  gateway?: IKnxGatewayDescriptor;
  gateways?: IKnxGatewayDescriptor[];
  tunnels?: IKnxGatewayDescriptor[];
  groupAddresses?: IKnxGroupAddressDescriptor[];
  group_addresses?: IKnxGroupAddressDescriptor[];
  entities?: IKnxEntityDescriptor[];
  light?: IKnxEntityDescriptor[];
  switch?: IKnxEntityDescriptor[];
  sensor?: IKnxEntityDescriptor[];
  cover?: IKnxEntityDescriptor[];
  climate?: IKnxEntityDescriptor[];
  snapshot?: IKnxSnapshot;
  events?: IKnxEvent[];
  commandExecutor?: TKnxCommandExecutor;
  [key: string]: unknown;
}

export interface IHomeAssistantKnxConfig extends IKnxConfig {}

export interface IKnxConnectionConfig {
  connectionType?: TKnxConnectionType;
  connection_type?: TKnxConnectionType;
  host?: string;
  port?: number;
  individualAddress?: string;
  individual_address?: string;
  localIp?: string;
  local_ip?: string;
  multicastGroup?: string;
  multicast_group?: string;
  multicastPort?: number;
  multicast_port?: number;
  routeBack?: boolean;
  route_back?: boolean;
  tunnelEndpointIa?: string | null;
  tunnel_endpoint_ia?: string | null;
  userId?: number | null;
  user_id?: number | null;
  userPassword?: string | null;
  user_password?: string | null;
  deviceAuthentication?: string | null;
  device_authentication?: string | null;
  backboneKey?: string | null;
  backbone_key?: string | null;
  syncLatencyTolerance?: number | null;
  sync_latency_tolerance?: number | null;
  knxkeysFilename?: string;
  knxkeys_filename?: string;
  knxkeysPassword?: string;
  knxkeys_password?: string;
  stateUpdater?: boolean;
  state_updater?: boolean;
  rateLimit?: number;
  rate_limit?: number;
  telegramLogSize?: number;
  telegram_log_size?: number;
  [key: string]: unknown;
}

export interface IKnxGatewayDescriptor {
  id?: string;
  name?: string;
  host?: string;
  ipAddr?: string;
  ip_addr?: string;
  ipAddress?: string;
  port?: number;
  localIp?: string;
  local_ip?: string;
  localInterface?: string;
  local_interface?: string;
  individualAddress?: unknown;
  individual_address?: unknown;
  supportsRouting?: boolean;
  supports_routing?: boolean;
  supportsTunneling?: boolean;
  supportsTunnelling?: boolean;
  supports_tunnelling?: boolean;
  supportsTunnelingTcp?: boolean;
  supportsTunnellingTcp?: boolean;
  supports_tunnelling_tcp?: boolean;
  supportsSecure?: boolean;
  supports_secure?: boolean;
  routingRequiresSecure?: boolean | null;
  routing_requires_secure?: boolean | null;
  tunnelingRequiresSecure?: boolean | null;
  tunnellingRequiresSecure?: boolean | null;
  tunnelling_requires_secure?: boolean | null;
  tunnelingSlots?: Record<string, IKnxTunnelSlot>;
  tunnellingSlots?: Record<string, IKnxTunnelSlot>;
  tunnelling_slots?: Record<string, IKnxTunnelSlot>;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IKnxTunnelSlot {
  individualAddress?: string;
  individual_address?: string;
  free?: boolean;
  authorized?: boolean;
  usable?: boolean;
  [key: string]: unknown;
}

export interface IKnxGroupAddressDescriptor {
  address: TKnxGroupAddress;
  name?: string;
  role?: string;
  platform?: TKnxEntityPlatform;
  entityId?: string;
  entity_id?: string;
  uniqueId?: string;
  unique_id?: string;
  deviceId?: string;
  device_id?: string;
  dpt?: string;
  type?: string;
  state?: unknown;
  value?: unknown;
  writable?: boolean;
  unit?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IKnxEntityDescriptor {
  platform?: TKnxEntityPlatform;
  entityId?: string;
  entity_id?: string;
  uniqueId?: string;
  unique_id?: string;
  deviceId?: string;
  device_id?: string;
  name?: string;
  originalName?: string;
  original_name?: string;
  fallbackName?: string;
  fallback_name?: string;
  address?: TKnxGroupAddress | TKnxGroupAddress[];
  groupAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  group_address?: TKnxGroupAddress | TKnxGroupAddress[];
  stateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  switchAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  switch_address?: TKnxGroupAddress | TKnxGroupAddress[];
  switchStateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  switch_state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  brightnessAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  brightness_address?: TKnxGroupAddress | TKnxGroupAddress[];
  brightnessStateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  brightness_state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  moveLongAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  move_long_address?: TKnxGroupAddress | TKnxGroupAddress[];
  moveShortAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  move_short_address?: TKnxGroupAddress | TKnxGroupAddress[];
  stopAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  stop_address?: TKnxGroupAddress | TKnxGroupAddress[];
  positionAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  position_address?: TKnxGroupAddress | TKnxGroupAddress[];
  positionStateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  position_state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  temperatureAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  temperature_address?: TKnxGroupAddress | TKnxGroupAddress[];
  targetTemperatureAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  target_temperature_address?: TKnxGroupAddress | TKnxGroupAddress[];
  targetTemperatureStateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  target_temperature_state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  onOffAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  on_off_address?: TKnxGroupAddress | TKnxGroupAddress[];
  onOffStateAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  on_off_state_address?: TKnxGroupAddress | TKnxGroupAddress[];
  operationModeAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  operation_mode_address?: TKnxGroupAddress | TKnxGroupAddress[];
  controllerModeAddress?: TKnxGroupAddress | TKnxGroupAddress[];
  controller_mode_address?: TKnxGroupAddress | TKnxGroupAddress[];
  dpt?: string;
  type?: string;
  state?: unknown;
  nativeValue?: unknown;
  native_value?: unknown;
  value?: unknown;
  isOn?: boolean;
  is_on?: boolean;
  isClosed?: boolean;
  is_closed?: boolean;
  currentCoverPosition?: number;
  current_cover_position?: number;
  position?: number;
  currentTemperature?: number;
  current_temperature?: number;
  targetTemperature?: number;
  target_temperature?: number;
  hvacMode?: string;
  hvac_mode?: string;
  deviceClass?: string;
  device_class?: string;
  unit?: string;
  unitOfMeasurement?: string;
  unit_of_measurement?: string;
  available?: boolean;
  writable?: boolean;
  invert?: boolean;
  invertUpdown?: boolean;
  invert_updown?: boolean;
  invertPosition?: boolean;
  invert_position?: boolean;
  syncState?: boolean;
  sync_state?: boolean;
  attributes?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
  raw?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IKnxConnectionSnapshot extends IKnxConnectionConfig {
  connectionType: TKnxConnectionType;
  host?: string;
  port: number;
  multicastGroup: string;
  multicastPort: number;
  secure?: boolean;
}

export interface IKnxSnapshot {
  connected: boolean;
  connection: IKnxConnectionSnapshot;
  gateways: IKnxGatewayDescriptor[];
  groupAddresses: IKnxGroupAddressDescriptor[];
  entities: IKnxEntityDescriptor[];
  events: IKnxEvent[];
}

export interface IKnxTelegramCommand {
  action: TKnxTelegramAction;
  address: TKnxGroupAddress;
  payload?: unknown;
  dpt?: string;
}

export interface IKnxClientCommand {
  type: 'group.write' | 'group.read' | 'entity.command';
  service: string;
  platform?: TKnxEntityPlatform;
  entityId?: string;
  uniqueId?: string;
  telegrams: IKnxTelegramCommand[];
  payload: Record<string, unknown>;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
}

export interface IKnxCommandResult {
  success: boolean;
  error?: string;
  data?: unknown;
}

export interface IKnxEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  uniqueId?: string;
  source?: string;
  destination?: string;
  telegramtype?: string;
  payload?: unknown;
  value?: unknown;
  command?: IKnxClientCommand;
  data?: unknown;
  [key: string]: unknown;
}

export type TKnxCommandExecutor = (
  commandArg: IKnxClientCommand
) => Promise<IKnxCommandResult | unknown> | IKnxCommandResult | unknown;

export interface IKnxManualDiscoveryEntry extends IKnxConnectionConfig {
  id?: string;
  name?: string;
  model?: string;
  manufacturer?: string;
  gateway?: IKnxGatewayDescriptor;
  metadata?: Record<string, unknown>;
}

export interface IKnxMdnsRecord {
  type?: string;
  name?: string;
  host?: string;
  hostname?: string;
  addresses?: string[];
  port?: number;
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
}
