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

export type TDdwrtSnapshotSource = 'snapshot' | 'manual' | 'client' | 'http' | 'transport' | 'runtime';
export type TDdwrtClientSource = 'wireless' | 'arp' | 'dhcp' | 'manual' | string;
export type TDdwrtCommandAction = 'refresh' | 'reboot';
export type TDdwrtCommandMethod = 'refresh' | 'executor' | 'native_client' | 'transport';
export type TDdwrtEventType = 'snapshot_refreshed' | 'command_mapped' | 'command_succeeded' | 'command_failed' | 'state_changed';

export interface IDdwrtStatusData {
  [key: string]: string;
}

export interface IDdwrtRawStatusSet {
  wireless?: IDdwrtStatusData;
  lan?: IDdwrtStatusData;
  wirelessResponse?: string;
  lanResponse?: string;
}

export interface IDdwrtDhcpLease {
  hostname?: string;
  ipAddress?: string;
  macAddress: string;
  expires?: string;
  raw?: string[];
  metadata?: Record<string, unknown>;
}

export interface IDdwrtClientDevice {
  id?: string;
  macAddress: string;
  name?: string;
  hostname?: string;
  ipAddress?: string;
  active: boolean;
  wireless?: boolean;
  source: TDdwrtClientSource;
  interface?: string;
  metadata?: Record<string, unknown>;
}

export interface IDdwrtRouterInfo {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  wirelessOnly?: boolean;
  configurationUrl?: string;
  macAddress?: string;
  manufacturer?: string;
  model?: string;
  authenticated?: boolean;
  available?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IDdwrtSensorMap {
  connected?: boolean;
  wireless_only?: boolean;
  tracked_clients?: number;
  active_wireless_clients?: number;
  active_lan_clients?: number;
  dhcp_leases?: number;
  [key: string]: unknown;
}

export interface IDdwrtSnapshot {
  connected: boolean;
  source: TDdwrtSnapshotSource;
  router: IDdwrtRouterInfo;
  clients: IDdwrtClientDevice[];
  leases: IDdwrtDhcpLease[];
  sensors: IDdwrtSensorMap;
  rawStatus?: IDdwrtRawStatusSet;
  updatedAt?: string;
  events: IDdwrtEvent[];
  metadata?: Record<string, unknown>;
  error?: string;
}

export interface IDdwrtCommand {
  action: TDdwrtCommandAction;
  method: TDdwrtCommandMethod;
  service: string;
  target?: IServiceCallRequest['target'];
  data?: Record<string, unknown>;
  deviceId?: string;
  entityId?: string;
  host?: string;
  transmitted?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IDdwrtCommandResult extends IServiceCallResult {
  transmitted?: boolean;
  action?: TDdwrtCommandAction;
}

export interface IDdwrtEvent {
  type: TDdwrtEventType;
  command?: IDdwrtCommand;
  deviceId?: string;
  entityId?: string;
  data?: unknown;
  error?: string;
  timestamp: number;
}

export interface IDdwrtNativeClient {
  login?(): Promise<boolean | void>;
  getSnapshot?(): Promise<IDdwrtSnapshot | Partial<IDdwrtSnapshot>>;
  getStatus?(): Promise<IDdwrtRawStatusSet | IDdwrtStatusData>;
  getWirelessStatus?(): Promise<IDdwrtStatusData | string>;
  getLanStatus?(): Promise<IDdwrtStatusData | string>;
  execute?(commandArg: IDdwrtCommand): Promise<IDdwrtCommandResult | unknown>;
  sendCommand?(commandArg: IDdwrtCommand): Promise<IDdwrtCommandResult | unknown>;
  reboot?(): Promise<IDdwrtCommandResult | boolean | Record<string, unknown> | void>;
  destroy?(): Promise<void>;
}

export interface IDdwrtTransport {
  readSnapshot?(): Promise<IDdwrtSnapshot | Partial<IDdwrtSnapshot>>;
  execute?(commandArg: IDdwrtCommand): Promise<IDdwrtCommandResult | unknown>;
}

export type TDdwrtCommandExecutor = ((commandArg: IDdwrtCommand) => Promise<IDdwrtCommandResult | unknown>) | {
  execute(commandArg: IDdwrtCommand): Promise<IDdwrtCommandResult | unknown>;
};

export interface IDdwrtManualEntry {
  integrationDomain?: string;
  id?: string;
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  port?: number;
  name?: string;
  username?: string;
  password?: string;
  ssl?: boolean;
  useSsl?: boolean;
  verifySsl?: boolean;
  verify_ssl?: boolean;
  wirelessOnly?: boolean;
  wireless_only?: boolean;
  manufacturer?: string;
  model?: string;
  mac?: string;
  macAddress?: string;
  snapshot?: IDdwrtSnapshot;
  rawStatus?: IDdwrtRawStatusSet;
  wirelessStatus?: IDdwrtStatusData | string;
  lanStatus?: IDdwrtStatusData | string;
  wirelessResponse?: string;
  lanResponse?: string;
  clients?: IDdwrtClientDevice[];
  leases?: IDdwrtDhcpLease[];
  sensors?: IDdwrtSensorMap;
  metadata?: Record<string, unknown>;
}

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

export interface IDdwrtHttpStatusRecord {
  integrationDomain?: string;
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  port?: number;
  name?: string;
  body?: string;
  statusText?: string;
  wirelessResponse?: string;
  lanResponse?: string;
  wirelessStatus?: IDdwrtStatusData | string;
  lanStatus?: IDdwrtStatusData | string;
  metadata?: Record<string, unknown>;
}

export interface IDdwrtConfig extends IDdwrtManualEntry {
  timeoutMs?: number;
  nativeHttpEnabled?: boolean;
  connected?: boolean;
  nativeClient?: IDdwrtNativeClient;
  commandExecutor?: TDdwrtCommandExecutor;
  transport?: IDdwrtTransport;
  [key: string]: unknown;
}

export type IHomeAssistantDdwrtConfig = IDdwrtConfig;
