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

export type TWakeOnLanEntityKind = 'button' | 'switch';
export type TWakeOnLanEntityMode = TWakeOnLanEntityKind | 'both';
export type TWakeOnLanCommandType = 'send_magic_packet' | 'button_press' | 'switch_turn_on' | 'switch_turn_off';
export type TWakeOnLanEventType = 'command_mapped' | 'packet_sent' | 'command_failed' | 'state_changed' | 'snapshot_refreshed';

export interface IWakeOnLanMagicPacket {
  macAddress: string;
  compactMac: string;
  broadcastAddress: string;
  broadcastPort: number;
  byteLength: number;
  bytes: number[];
  hex: string;
  base64: string;
}

export interface IWakeOnLanTarget {
  id?: string;
  name?: string;
  macAddress?: string;
  mac?: string;
  normalizedMac?: string;
  host?: string;
  broadcastAddress?: string;
  broadcast_address?: string;
  broadcastPort?: number;
  broadcast_port?: number;
  platform?: TWakeOnLanEntityMode;
  entityTypes?: TWakeOnLanEntityKind[];
  createButton?: boolean;
  createSwitch?: boolean;
  entityId?: string;
  switchEntityId?: string;
  buttonEntityId?: string;
  uniqueId?: string;
  state?: boolean | string;
  online?: boolean;
  available?: boolean;
  assumedState?: boolean;
  offAction?: unknown;
  turn_off?: unknown;
  metadata?: Record<string, unknown>;
}

export interface IWakeOnLanEntityDescriptor {
  id?: string;
  entityId?: string;
  uniqueId?: string;
  deviceId?: string;
  platform?: TWakeOnLanEntityKind;
  name?: string;
  targetId?: string;
  macAddress?: string;
  state?: unknown;
  available?: boolean;
  attributes?: Record<string, unknown>;
}

export interface IWakeOnLanSnapshot {
  connected: boolean;
  targets: IWakeOnLanTarget[];
  entities: IWakeOnLanEntityDescriptor[];
  events: IWakeOnLanEvent[];
  updatedAt?: string;
  metadata?: Record<string, unknown>;
}

export interface IWakeOnLanCommand {
  type: TWakeOnLanCommandType;
  method: 'wakeonlan.send_magic_packet' | 'local_turn_off_action';
  service: string;
  target?: IServiceCallRequest['target'];
  data?: Record<string, unknown>;
  deviceId?: string;
  entityId?: string;
  targetId?: string;
  macAddress?: string;
  normalizedMac?: string;
  host?: string;
  broadcastAddress?: string;
  broadcastPort?: number;
  packet?: IWakeOnLanMagicPacket;
  offAction?: unknown;
  transmitted?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IWakeOnLanCommandResult extends IServiceCallResult {
  transmitted?: boolean;
  packet?: IWakeOnLanMagicPacket;
}

export interface IWakeOnLanEvent {
  type: TWakeOnLanEventType;
  command?: IWakeOnLanCommand;
  deviceId?: string;
  entityId?: string;
  targetId?: string;
  data?: unknown;
  error?: string;
  timestamp: number;
}

export interface IWakeOnLanTransport {
  execute(commandArg: IWakeOnLanCommand): Promise<IWakeOnLanCommandResult | unknown>;
}

export interface IWakeOnLanConfig extends IWakeOnLanTarget {
  targets?: IWakeOnLanTarget[];
  devices?: IWakeOnLanTarget[];
  entries?: IWakeOnLanTarget[];
  manualEntries?: IWakeOnLanManualEntry[];
  buttons?: IWakeOnLanTarget[];
  switches?: IWakeOnLanTarget[];
  entities?: IWakeOnLanEntityDescriptor[];
  snapshot?: IWakeOnLanSnapshot;
  connected?: boolean;
  nativeUdpEnabled?: boolean;
  udpTimeoutMs?: number;
  commandExecutor?: (commandArg: IWakeOnLanCommand) => Promise<IWakeOnLanCommandResult | unknown>;
  transport?: IWakeOnLanTransport;
  pingExecutor?: (hostArg: string, targetArg: IWakeOnLanTarget) => Promise<boolean>;
}

export interface IWakeOnLanManualEntry extends IWakeOnLanTarget {
  integrationDomain?: string;
  manufacturer?: string;
  model?: string;
  snapshot?: IWakeOnLanSnapshot;
  targets?: IWakeOnLanTarget[];
  buttons?: IWakeOnLanTarget[];
  switches?: IWakeOnLanTarget[];
}

export interface IWakeOnLanStaticHostRecord {
  integrationDomain?: string;
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  name?: string;
  hostname?: string;
  hostName?: string;
  mac?: string;
  macAddress?: string;
  broadcastAddress?: string;
  broadcast_address?: string;
  broadcastPort?: number;
  broadcast_port?: number;
  metadata?: Record<string, unknown>;
}

export interface IWakeOnLanCandidateMetadata extends Record<string, unknown> {
  wakeOnLan?: boolean;
  wake_on_lan?: boolean;
  macAddress?: string;
  host?: string;
  broadcastAddress?: string;
  broadcastPort?: number;
  entityMode?: TWakeOnLanEntityMode;
  snapshot?: IWakeOnLanSnapshot;
}

export type IHomeAssistantWakeOnLanConfig = IWakeOnLanConfig;
