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

export type TBroadlinkDeviceType =
  | 'A1'
  | 'A2'
  | 'BG1'
  | 'HYS'
  | 'LB1'
  | 'LB2'
  | 'MP1'
  | 'MP1S'
  | 'RM4MINI'
  | 'RM4PRO'
  | 'RMMINI'
  | 'RMMINIB'
  | 'RMPRO'
  | 'SP1'
  | 'SP2'
  | 'SP2S'
  | 'SP3'
  | 'SP3S'
  | 'SP4'
  | 'SP4B'
  | string;

export type TBroadlinkCommandType =
  | 'delete_command'
  | 'learn_ir'
  | 'learn_rf'
  | 'remote_turn_off'
  | 'remote_turn_on'
  | 'send_data'
  | 'send_ir'
  | 'send_packet'
  | 'send_rf'
  | 'set_power'
  | 'set_state';

export type TBroadlinkEventType =
  | 'command_deleted'
  | 'command_executed'
  | 'command_failed'
  | 'command_mapped'
  | 'snapshot_refreshed';

export type TBroadlinkPacketKind = 'ir' | 'rf315' | 'rf433' | 'rf' | 'unknown';

export interface IBroadlinkPacket {
  base64: string;
  hex: string;
  bytes: number[];
  byteLength: number;
  kind: TBroadlinkPacketKind;
  firstByte?: number;
  frequency?: number;
  repeatCount?: number;
  source?: 'base64' | 'hex' | 'ir_timings' | 'rf_timings';
}

export type TBroadlinkCodeValue = string | string[];

export type TBroadlinkCodeStore = Record<string, Record<string, TBroadlinkCodeValue>>;

export interface IBroadlinkCustomSwitchConfig {
  id?: string;
  name: string;
  entityId?: string;
  uniqueId?: string;
  commandOn?: string;
  commandOff?: string;
  command_on?: string;
  command_off?: string;
  state?: boolean | string;
  available?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IBroadlinkEntityDescriptor {
  id?: string;
  entityId?: string;
  uniqueId?: string;
  deviceId?: string;
  platform?: TEntityPlatform | 'remote' | string;
  name?: string;
  state?: unknown;
  attributes?: Record<string, unknown>;
  available?: boolean;
}

export interface IBroadlinkDevice {
  id?: string;
  host?: string;
  port?: number;
  macAddress?: string;
  mac?: string;
  type?: TBroadlinkDeviceType;
  devtype?: number;
  name?: string;
  model?: string;
  manufacturer?: string;
  firmwareVersion?: string | number;
  locked?: boolean;
  isLocked?: boolean;
  authorized?: boolean;
  available?: boolean;
  online?: boolean;
  state?: Record<string, unknown>;
  sensors?: Record<string, unknown>;
  codes?: TBroadlinkCodeStore;
  flags?: Record<string, number>;
  switches?: IBroadlinkCustomSwitchConfig[];
  supportsRf?: boolean;
  updatedAt?: string;
  metadata?: Record<string, unknown>;
}

export interface IBroadlinkTransport {
  execute(commandArg: IBroadlinkCommand): Promise<IBroadlinkCommandResult | unknown>;
}

export interface IBroadlinkConfig {
  host?: string;
  port?: number;
  timeout?: number;
  timeoutMs?: number;
  name?: string;
  macAddress?: string;
  mac?: string;
  deviceId?: string;
  type?: TBroadlinkDeviceType;
  devtype?: number;
  model?: string;
  manufacturer?: string;
  firmwareVersion?: string | number;
  isLocked?: boolean;
  locked?: boolean;
  authorized?: boolean;
  connected?: boolean;
  state?: Record<string, unknown>;
  sensors?: Record<string, unknown>;
  codes?: TBroadlinkCodeStore;
  flags?: Record<string, number>;
  switches?: IBroadlinkCustomSwitchConfig[];
  devices?: IBroadlinkDevice[];
  entities?: IBroadlinkEntityDescriptor[];
  manualEntries?: IBroadlinkManualEntry[];
  snapshot?: IBroadlinkSnapshot;
  metadata?: Record<string, unknown>;
  commandExecutor?: (commandArg: IBroadlinkCommand) => Promise<IBroadlinkCommandResult | unknown>;
  transport?: IBroadlinkTransport;
}

export interface IBroadlinkSnapshot {
  connected: boolean;
  host?: string;
  port?: number;
  devices: IBroadlinkDevice[];
  entities: IBroadlinkEntityDescriptor[];
  events: IBroadlinkEvent[];
  metadata?: Record<string, unknown>;
}

export interface IBroadlinkCommand {
  type: TBroadlinkCommandType;
  method: string;
  service: string;
  deviceId?: string;
  entityId?: string;
  target?: IServiceCallRequest['target'];
  data?: Record<string, unknown>;
  payload?: Record<string, unknown>;
  packet?: IBroadlinkPacket;
  packets?: IBroadlinkPacket[];
  commandNames?: string[];
  remoteDevice?: string;
  commandType?: 'ir' | 'rf';
  alternative?: boolean;
  numRepeats?: number;
  delaySecs?: number;
  transmitted?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IBroadlinkCommandResult extends IServiceCallResult {
  transmitted?: boolean;
}

export interface IBroadlinkEvent {
  type: TBroadlinkEventType;
  command?: IBroadlinkCommand;
  deviceId?: string;
  entityId?: string;
  data?: unknown;
  timestamp: number;
}

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

export interface IBroadlinkLocalDiscoveryRecord {
  host?: string;
  port?: number;
  mac?: string;
  macAddress?: string;
  type?: TBroadlinkDeviceType;
  devtype?: number;
  name?: string;
  model?: string;
  manufacturer?: string;
  isLocked?: boolean;
  locked?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IBroadlinkManualEntry extends IBroadlinkLocalDiscoveryRecord {
  id?: string;
  deviceId?: string;
  timeout?: number;
  state?: Record<string, unknown>;
  sensors?: Record<string, unknown>;
  codes?: TBroadlinkCodeStore;
  switches?: IBroadlinkCustomSwitchConfig[];
  device?: IBroadlinkDevice;
  devices?: IBroadlinkDevice[];
  snapshot?: IBroadlinkSnapshot;
  integrationDomain?: string;
}

export interface IBroadlinkCandidateMetadata extends Record<string, unknown> {
  broadlink?: boolean;
  deviceType?: TBroadlinkDeviceType;
  devtype?: number;
  isLocked?: boolean;
  timeout?: number;
  snapshot?: IBroadlinkSnapshot;
}

export type IHomeAssistantBroadlinkConfig = IBroadlinkConfig;
