export type TRflinkConnectionType = 'serial' | 'tcp' | 'manual';

export type TRflinkEntityPlatform = 'light' | 'switch' | 'sensor' | 'binary_sensor' | 'cover';

export type TRflinkLightType = 'switchable' | 'dimmable' | 'hybrid' | 'toggle';

export type TRflinkCoverType = 'standard' | 'inverted';

export type TRflinkEventType =
  | 'availability'
  | 'command'
  | 'command_mapped'
  | 'command_executed'
  | 'command_failed'
  | 'gateway'
  | 'learn'
  | 'raw_line'
  | 'sensor'
  | 'snapshot_refreshed';

export type TRflinkCommandType =
  | 'turn_on'
  | 'turn_off'
  | 'set_value'
  | 'open_cover'
  | 'close_cover'
  | 'stop_cover'
  | 'learn'
  | 'send_command'
  | 'refresh';

export interface IRflinkConfig {
  host?: string;
  port?: string | number;
  connectionType?: TRflinkConnectionType;
  baudRate?: number;
  waitForAck?: boolean;
  tcpKeepaliveIdleTimer?: number;
  reconnectInterval?: number;
  ignoreDevices?: string[];
  automaticAdd?: boolean;
  connected?: boolean;
  gateway?: IRflinkGateway;
  devices?: TRflinkEntityCollection;
  entities?: IRflinkEntityConfig[];
  lights?: TRflinkEntityCollection;
  switches?: TRflinkEntityCollection;
  sensors?: TRflinkEntityCollection;
  binarySensors?: TRflinkEntityCollection;
  covers?: TRflinkEntityCollection;
  events?: IRflinkEvent[];
  snapshot?: IRflinkSnapshot;
  commandExecutor?: (commandArg: IRflinkCommand) => Promise<IRflinkCommandResult | unknown>;
}

export interface IRflinkGateway {
  id?: string;
  name?: string;
  connectionType?: TRflinkConnectionType;
  host?: string;
  port?: string | number;
  baudRate?: number;
  hardware?: string;
  firmware?: string;
  version?: string;
  revision?: string;
  online?: boolean;
  attributes?: Record<string, unknown>;
}

export type TRflinkEntityCollection = Record<string, Omit<IRflinkEntityConfig, 'id'> | string | undefined> | IRflinkEntityConfig[];

export interface IRflinkEntityConfig {
  id: string;
  platform?: TRflinkEntityPlatform;
  name?: string;
  aliases?: string[];
  groupAliases?: string[];
  noGroupAliases?: string[];
  group?: boolean;
  fireEvent?: boolean;
  signalRepetitions?: number;
  type?: TRflinkLightType | TRflinkCoverType;
  sensorType?: string;
  unitOfMeasurement?: string;
  deviceClass?: string;
  forceUpdate?: boolean;
  offDelaySeconds?: number;
  state?: string;
  value?: unknown;
  command?: string;
  brightness?: number;
  available?: boolean;
  attributes?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
}

export interface IRflinkDevice extends IRflinkEntityConfig {
  id: string;
  platform: TRflinkEntityPlatform;
}

export interface IRflinkEntity extends IRflinkDevice {
  entityId?: string;
  uniqueId?: string;
  updatedAt?: string;
}

export interface IRflinkEvent {
  type: TRflinkEventType;
  id?: string;
  entityId?: string;
  deviceId?: string;
  command?: IRflinkCommand;
  rflinkCommand?: string;
  sensor?: string;
  value?: unknown;
  unit?: string;
  line?: string;
  packet?: IRflinkPacket;
  data?: unknown;
  timestamp: number;
}

export interface IRflinkSnapshot {
  gateway: IRflinkGateway;
  devices: IRflinkDevice[];
  entities: IRflinkEntity[];
  events: IRflinkEvent[];
  connected: boolean;
  updatedAt: string;
  raw?: Record<string, unknown>;
}

export interface IRflinkPacket {
  node?: '10' | '11' | '20' | string;
  sequence?: string;
  protocol?: string;
  id?: string;
  switch?: string;
  command?: string;
  values?: Record<string, unknown>;
  raw?: string;
}

export interface IRflinkLineProtocolCommandShape {
  transport: 'line-protocol';
  line: string;
  packet: IRflinkPacket;
  waitForAck?: boolean;
  repetitions?: number;
}

export interface IRflinkCommand {
  type: TRflinkCommandType;
  deviceId?: string;
  entityId?: string;
  rflinkCommand?: string;
  value?: number;
  brightness?: number;
  rawLine?: string;
  lineProtocol?: IRflinkLineProtocolCommandShape;
  repetitions?: number;
  metadata?: Record<string, unknown>;
}

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

export interface IRflinkManualSerialEntry {
  connectionType?: 'serial';
  port?: string;
  path?: string;
  baudRate?: number;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}

export interface IRflinkManualTcpEntry {
  connectionType?: 'tcp';
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}

export type IRflinkManualEntry = IRflinkManualSerialEntry | IRflinkManualTcpEntry;

export interface IRflinkCandidateMetadata extends Record<string, unknown> {
  rflink?: boolean;
  connectionType?: TRflinkConnectionType;
  serialPort?: string;
  baudRate?: number;
}

export type IHomeAssistantRflinkConfig = IRflinkConfig;
