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

export const mikrotikDomain = 'mikrotik';
export const mikrotikDefaultApiPort = 8728;
export const mikrotikDefaultDetectionTime = 300;
export const mikrotikManufacturer = 'Mikrotik';

export type TMikrotikProtocol = 'routeros-api' | 'routeros-api-ssl';
export type TMikrotikSnapshotSource = 'snapshot' | 'manual' | 'provider' | 'runtime';
export type TMikrotikActionTarget = 'router' | 'client' | 'interface';
export type TMikrotikRouterAction = 'reboot';
export type TMikrotikClientAction = 'arp_ping' | 'disconnect';
export type TMikrotikInterfaceAction = 'set_enabled';
export type TMikrotikAction = TMikrotikRouterAction | TMikrotikClientAction | TMikrotikInterfaceAction;
export type TMikrotikCommandType = 'router.action' | 'client.action' | 'interface.set';
export type TMikrotikApiPath =
  | '/system/reboot'
  | '/ping'
  | '/interface/set'
  | '/interface/wireless/registration-table/remove'
  | '/caps-man/registration-table/remove'
  | '/interface/wifiwave2/registration-table/remove'
  | '/interface/wifi/registration-table/remove';

export interface IMikrotikConfig {
  host?: string;
  port?: number;
  username?: string;
  password?: string;
  verifySsl?: boolean;
  protocol?: TMikrotikProtocol;
  arpPing?: boolean;
  forceDhcp?: boolean;
  detectionTime?: number;
  connected?: boolean;
  uniqueId?: string;
  name?: string;
  snapshot?: IMikrotikSnapshot;
  router?: IMikrotikRouterInfo;
  resources?: IMikrotikResourceInfo;
  traffic?: IMikrotikTrafficStats;
  devices?: IMikrotikClientDevice[];
  clients?: IMikrotikClientDevice[];
  interfaces?: IMikrotikInterfaceStats[];
  sensors?: IMikrotikSensorMap;
  actions?: IMikrotikActionDescriptor[];
  manualEntries?: IMikrotikManualEntry[];
  events?: IMikrotikEvent[];
  snapshotProvider?: TMikrotikSnapshotProvider;
  commandExecutor?: TMikrotikCommandExecutor;
  nativeClient?: IMikrotikNativeClient;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHomeAssistantMikrotikConfig extends IMikrotikConfig {}

export interface IMikrotikRouterInfo {
  id?: string;
  host?: string;
  port?: number;
  name?: string;
  identity?: string;
  model?: string;
  boardName?: string;
  serialNumber?: string;
  firmware?: string;
  currentFirmware?: string;
  factoryFirmware?: string;
  upgradeFirmware?: string;
  routerOsVersion?: string;
  architectureName?: string;
  macAddress?: string;
  configurationUrl?: string;
  manufacturer?: string;
  verifySsl?: boolean;
  protocol?: TMikrotikProtocol;
  supportsCapsman?: boolean;
  supportsWireless?: boolean;
  supportsWifiwave2?: boolean;
  supportsWifi?: boolean;
  actions?: TMikrotikRouterAction[];
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IMikrotikResourceInfo {
  uptime?: string | number | Date;
  version?: string;
  routerOsVersion?: string;
  buildTime?: string;
  factorySoftware?: string;
  freeMemory?: number;
  totalMemory?: number;
  usedMemory?: number;
  memoryUsagePercent?: number;
  cpu?: string;
  cpuCount?: number;
  cpuFrequency?: number;
  cpuLoad?: number;
  freeHddSpace?: number;
  totalHddSpace?: number;
  badBlocks?: number;
  architectureName?: string;
  boardName?: string;
  platform?: string;
  temperature?: number;
  voltage?: number;
  current?: number;
  fanSpeed?: number;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IMikrotikTrafficStats {
  rxBytes?: number;
  txBytes?: number;
  rxRateMbps?: number;
  txRateMbps?: number;
  rxBitsPerSecond?: number;
  txBitsPerSecond?: number;
  rxRate?: number;
  txRate?: number;
  downloadBytes?: number;
  uploadBytes?: number;
  downloadRateMbps?: number;
  uploadRateMbps?: number;
  [key: string]: unknown;
}

export interface IMikrotikClientDevice {
  id?: string;
  mac?: string;
  macAddress?: string;
  name?: string;
  hostname?: string;
  hostName?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  activeAddress?: string;
  connected?: boolean;
  connectedTo?: string;
  interface?: string;
  ssid?: string;
  comment?: string;
  signalStrength?: number | string;
  signalToNoise?: number | string;
  rxRate?: number | string;
  txRate?: number | string;
  uptime?: string | number | Date;
  lastSeen?: string | number | Date;
  lastActivity?: string | number | Date;
  manufacturer?: string;
  model?: string;
  source?: 'dhcp' | 'arp' | 'wireless' | 'capsman' | 'wifiwave2' | 'wifi' | 'manual' | string;
  actions?: TMikrotikClientAction[];
  metadata?: Record<string, unknown>;
  '.id'?: string;
  'mac-address'?: string;
  'host-name'?: string;
  'active-address'?: string;
  'last-seen'?: string | number | Date;
  'signal-strength'?: number | string;
  'signal-to-noise'?: number | string;
  'rx-rate'?: number | string;
  'tx-rate'?: number | string;
  [key: string]: unknown;
}

export interface IMikrotikInterfaceStats {
  id?: string;
  name: string;
  label?: string;
  type?: string;
  connected?: boolean;
  running?: boolean;
  enabled?: boolean;
  disabled?: boolean;
  macAddress?: string;
  ipAddress?: string;
  ssid?: string;
  comment?: string;
  mtu?: number;
  actualMtu?: number;
  rxBytes?: number;
  txBytes?: number;
  rxRate?: number;
  txRate?: number;
  rxBitsPerSecond?: number;
  txBitsPerSecond?: number;
  downloadBytes?: number;
  uploadBytes?: number;
  rxPackets?: number;
  txPackets?: number;
  rxDrops?: number;
  txDrops?: number;
  rxErrors?: number;
  txErrors?: number;
  lastLinkUpTime?: string | number | Date;
  actions?: TMikrotikInterfaceAction[];
  metadata?: Record<string, unknown>;
  '.id'?: string;
  'mac-address'?: string;
  'actual-mtu'?: number;
  'rx-byte'?: number;
  'tx-byte'?: number;
  'rx-packet'?: number;
  'tx-packet'?: number;
  'rx-drop'?: number;
  'tx-drop'?: number;
  'rx-error'?: number;
  'tx-error'?: number;
  'rx-bits-per-second'?: number;
  'tx-bits-per-second'?: number;
  'last-link-up-time'?: string | number | Date;
  [key: string]: unknown;
}

export interface IMikrotikSensorMap {
  connected_clients?: number;
  cpu_load?: number;
  cpu_count?: number;
  cpu_frequency?: number;
  memory_free?: number;
  memory_total?: number;
  memory_used?: number;
  memory_usage_percent?: number;
  hdd_free?: number;
  hdd_total?: number;
  bad_blocks?: number;
  uptime?: string | number | Date;
  routeros_version?: string;
  firmware?: string;
  rx_bytes?: number;
  tx_bytes?: number;
  rx_rate?: number;
  tx_rate?: number;
  temperature?: number;
  voltage?: number;
  current?: number;
  fan_speed?: number;
  [key: string]: string | number | boolean | Date | null | undefined;
}

export interface IMikrotikActionDescriptor {
  target: TMikrotikActionTarget;
  action: TMikrotikAction;
  command?: TMikrotikApiPath;
  params?: Record<string, unknown>;
  mac?: string;
  id?: string | number;
  interfaceName?: string;
  entityId?: string;
  deviceId?: string;
  label?: string;
  metadata?: Record<string, unknown>;
}

export interface IMikrotikSnapshot {
  connected: boolean;
  source?: TMikrotikSnapshotSource;
  updatedAt?: string;
  router: IMikrotikRouterInfo;
  resources: IMikrotikResourceInfo;
  devices: IMikrotikClientDevice[];
  interfaces: IMikrotikInterfaceStats[];
  sensors: IMikrotikSensorMap;
  traffic?: IMikrotikTrafficStats;
  actions?: IMikrotikActionDescriptor[];
  events?: IMikrotikEvent[];
  error?: string;
  metadata?: Record<string, unknown>;
}

export interface IMikrotikManualEntry {
  id?: string;
  host?: string;
  port?: number;
  username?: string;
  verifySsl?: boolean;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  router?: IMikrotikRouterInfo;
  resources?: IMikrotikResourceInfo;
  traffic?: IMikrotikTrafficStats;
  devices?: IMikrotikClientDevice[];
  clients?: IMikrotikClientDevice[];
  interfaces?: IMikrotikInterfaceStats[];
  sensors?: IMikrotikSensorMap;
  actions?: IMikrotikActionDescriptor[];
  snapshot?: IMikrotikSnapshot;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IMikrotikManualDiscoveryRecord extends IMikrotikManualEntry {
  integrationDomain?: string;
}

export interface IMikrotikCommand {
  type: TMikrotikCommandType;
  service: string;
  action: TMikrotikAction;
  path: TMikrotikApiPath;
  params: Record<string, unknown>;
  target: {
    entityId?: string;
    deviceId?: string;
  };
  routerId?: string;
  mac?: string;
  interfaceId?: string | number;
  interfaceName?: string;
  entityId?: string;
  deviceId?: string;
  payload?: Record<string, unknown>;
}

export interface IMikrotikCommandResult extends IServiceCallResult {}

export interface IMikrotikEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  command?: IMikrotikCommand;
  snapshot?: IMikrotikSnapshot;
  error?: string;
  data?: unknown;
  [key: string]: unknown;
}

export interface IMikrotikNativeClient {
  getSnapshot(): Promise<IMikrotikSnapshot> | IMikrotikSnapshot;
  executeCommand?(commandArg: IMikrotikCommand): Promise<IMikrotikCommandResult | unknown> | IMikrotikCommandResult | unknown;
  destroy?(): Promise<void> | void;
}

export type TMikrotikSnapshotProvider = () => Promise<IMikrotikSnapshot | undefined> | IMikrotikSnapshot | undefined;
export type TMikrotikCommandExecutor = (
  commandArg: IMikrotikCommand
) => Promise<IMikrotikCommandResult | unknown> | IMikrotikCommandResult | unknown;
