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

export type TMatterNodeId = number | bigint | string;

export type TMatterEntityPlatform = TEntityPlatform | 'lock';

export interface IMatterConfig {
  url?: string;
  host?: string;
  port?: number;
  connect?: boolean;
  commandTimeoutMs?: number;
  serverInfo?: IMatterServerInfo;
  nodes?: IMatterNode[];
  events?: IMatterServerEvent[];
  snapshot?: IMatterSnapshot;
}

export interface IMatterServerInfo {
  fabric_id: TMatterNodeId;
  compressed_fabric_id: TMatterNodeId;
  fabric_index?: number;
  schema_version: number;
  min_supported_schema_version: number;
  sdk_version: string;
  wifi_credentials_set: boolean;
  thread_credentials_set: boolean;
  bluetooth_enabled: boolean;
}

export interface IMatterNode {
  node_id: TMatterNodeId;
  date_commissioned?: string;
  last_interview?: string;
  interview_version?: number;
  available?: boolean;
  is_bridge?: boolean;
  attributes: Record<string, unknown>;
  attribute_subscriptions?: readonly unknown[];
  matter_version?: string;
}

export interface IMatterEndpoint {
  nodeId: TMatterNodeId;
  endpointId: number;
  deviceTypes: IMatterDeviceType[];
  clusters: IMatterCluster[];
  attributes: IMatterAttribute[];
  deviceInfo: IMatterDeviceInfo;
}

export interface IMatterDeviceType {
  id: number;
  name: string;
  revision?: number;
  raw?: unknown;
}

export interface IMatterCluster {
  id: number;
  name: string;
  attributes: IMatterAttribute[];
}

export interface IMatterAttribute {
  path: string;
  endpointId: number;
  clusterId: number;
  attributeId: number;
  clusterName: string;
  attributeName: string;
  value: unknown;
  readable: boolean;
  writable: boolean;
}

export interface IMatterDeviceInfo {
  nodeLabel?: string;
  productLabel?: string;
  productName?: string;
  vendorName?: string;
  vendorId?: number;
  productId?: number;
  serialNumber?: string;
  hardwareVersionString?: string;
  softwareVersionString?: string;
}

export interface IMatterSnapshot {
  serverInfo?: IMatterServerInfo;
  nodes: IMatterNode[];
  events: IMatterServerEvent[];
  connected: boolean;
  url?: string;
}

export type TMatterServerEventName =
  | 'node_added'
  | 'node_updated'
  | 'node_removed'
  | 'node_event'
  | 'attribute_updated'
  | 'server_shutdown'
  | 'endpoint_added'
  | 'endpoint_removed'
  | 'server_info_updated';

export interface IMatterServerEvent<TData = unknown> {
  event: TMatterServerEventName | string;
  data: TData;
}

export interface IMatterNodeEvent {
  node_id: TMatterNodeId;
  endpoint_id: number;
  cluster_id: number;
  event_id: number;
  event_number: TMatterNodeId;
  priority: number;
  timestamp: TMatterNodeId;
  timestamp_type: number;
  data: unknown | null;
}

export interface IMatterCommandFrame {
  message_id: string;
  command: string;
  args?: Record<string, unknown>;
}

export interface IMatterResultFrame<TResult = unknown> {
  message_id: string;
  result: TResult;
}

export interface IMatterErrorFrame {
  message_id: string;
  error_code: number;
  details?: string;
}

export interface IMatterServerCommand<TArgs extends Record<string, unknown> = Record<string, unknown>> {
  command: string;
  args?: TArgs;
  requireSchema?: number;
  timeoutMs?: number;
}

export interface IMatterServiceCommandArgs extends Record<string, unknown> {
  node_id?: TMatterNodeId;
  endpoint_id?: number;
  cluster_id?: number;
  command_name?: string;
  payload?: Record<string, unknown>;
  response_type?: unknown;
  timed_request_timeout_ms?: number;
  interaction_timeout_ms?: number;
}

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

export interface IMatterManualEntry {
  url?: string;
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}

export type TMatterDiscoveryRecord = IMatterMdnsRecord | IMatterManualEntry;
