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

export const fritzDomain = 'fritz';
export const fritzDefaultHost = '192.168.178.1';
export const fritzDefaultHttpPort = 49000;
export const fritzDefaultHttpsPort = 49443;
export const fritzDefaultSsl = false;
export const fritzDefaultConsiderHomeSeconds = 180;

export type TFritzProtocol = 'http' | 'https';
export type TFritzMeshRole = 'none' | 'master' | 'slave';
export type TFritzSnapshotSource = 'snapshot' | 'manual' | 'provider' | 'runtime';
export type TFritzCommandType = 'router.action' | 'client.action' | 'switch.set' | 'service.action';
export type TFritzRouterAction = 'firmware_update' | 'reboot' | 'reconnect' | 'cleanup';
export type TFritzClientAction = 'wake_on_lan' | 'set_wan_access';
export type TFritzSwitchAction = 'set_wifi_enabled' | 'set_port_forward_enabled' | 'set_call_deflection_enabled';
export type TFritzServiceAction = 'set_guest_wifi_password' | 'dial';
export type TFritzAction = TFritzRouterAction | TFritzClientAction | TFritzSwitchAction | TFritzServiceAction;

export interface IFritzConfig {
  host?: string;
  port?: number;
  ssl?: boolean;
  username?: string;
  password?: string;
  featureDeviceTracking?: boolean;
  oldDiscovery?: boolean;
  considerHomeSeconds?: number;
  connected?: boolean;
  uniqueId?: string;
  name?: string;
  model?: string;
  snapshot?: IFritzSnapshot;
  router?: IFritzRouterInfo;
  devices?: IFritzClientDevice[];
  clients?: IFritzClientDevice[];
  interfaces?: IFritzInterfaceStats[];
  connection?: IFritzConnectionInfo;
  sensors?: IFritzSensorMap;
  wifiNetworks?: IFritzWifiNetwork[];
  portForwards?: IFritzPortForward[];
  callDeflections?: IFritzCallDeflection[];
  update?: IFritzUpdateInfo;
  actions?: IFritzActionDescriptor[];
  manualEntries?: IFritzManualEntry[];
  events?: IFritzEvent[];
  snapshotProvider?: TFritzSnapshotProvider;
  commandExecutor?: TFritzCommandExecutor;
  nativeClient?: IFritzNativeClient;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHomeAssistantFritzConfig extends IFritzConfig {}

export interface IFritzRouterInfo {
  id?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  name?: string;
  model?: string;
  serialNumber?: string;
  firmware?: string;
  currentFirmware?: string;
  latestFirmware?: string;
  updateAvailable?: boolean;
  releaseUrl?: string;
  macAddress?: string;
  configurationUrl?: string;
  manufacturer?: string;
  meshRole?: TFritzMeshRole;
  meshWifiUplink?: boolean;
  connectionType?: string;
  isRouter?: boolean;
  wanEnabled?: boolean;
  ipv6Active?: boolean;
  upnpEnabled?: boolean;
  services?: string[];
  actions?: TFritzRouterAction[];
  metadata?: Record<string, unknown>;
}

export interface IFritzConnectionInfo {
  connection?: string;
  wanEnabled?: boolean;
  ipv6Active?: boolean;
  isConnected?: boolean;
  isLinked?: boolean;
  externalIp?: string;
  externalIPv6?: string;
  externalIpv6?: string;
  connectionUptime?: string | number | Date;
  deviceUptime?: string | number | Date;
  transmissionRate?: [number, number];
  maxBitRate?: [number, number];
  maxLinkedBitRate?: [number, number];
  noiseMargin?: [number, number];
  attenuation?: [number, number];
  bytesSent?: number;
  bytesReceived?: number;
  kbSent?: number;
  kbReceived?: number;
  maxKbSent?: number;
  maxKbReceived?: number;
  linkKbSent?: number;
  linkKbReceived?: number;
  gbSent?: number;
  gbReceived?: number;
  cpuTemperature?: number;
  [key: string]: unknown;
}

export interface IFritzSensorMap {
  is_connected?: boolean;
  is_linked?: boolean;
  external_ip?: string;
  external_ipv6?: string;
  connection_uptime?: string | number | Date;
  device_uptime?: string | number | Date;
  kb_s_sent?: number;
  kb_s_received?: number;
  max_kb_s_sent?: number;
  max_kb_s_received?: number;
  gb_sent?: number;
  gb_received?: number;
  link_kb_s_sent?: number;
  link_kb_s_received?: number;
  link_noise_margin_sent?: number;
  link_noise_margin_received?: number;
  link_attenuation_sent?: number;
  link_attenuation_received?: number;
  cpu_temperature?: number;
  [key: string]: string | number | boolean | Date | null | undefined;
}

export interface IFritzClientDevice {
  id?: string;
  mac?: string;
  macAddress?: string;
  name?: string;
  hostname?: string;
  ip?: string;
  ipAddress?: string;
  connected?: boolean;
  connectedTo?: string;
  connectionType?: string;
  ssid?: string | null;
  lastActivity?: string | number | Date;
  wanAccess?: boolean | null;
  manufacturer?: string;
  model?: string;
  actions?: TFritzClientAction[];
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IFritzInterfaceStats {
  id?: string;
  name: string;
  label?: string;
  type?: string;
  connected?: boolean;
  macAddress?: string;
  ipAddress?: string;
  ssid?: string | null;
  opMode?: string;
  rxBytes?: number;
  txBytes?: number;
  rxRateKbps?: number;
  txRateKbps?: number;
  downloadBytes?: number;
  uploadBytes?: number;
  downloadRateKbps?: number;
  uploadRateKbps?: number;
  metadata?: Record<string, unknown>;
}

export interface IFritzWifiNetwork {
  id?: string;
  index?: number;
  name?: string;
  switchName?: string;
  ssid?: string;
  enabled?: boolean;
  guest?: boolean;
  band?: string;
  standard?: string;
  bssid?: string;
  macAddressControl?: boolean;
  hidden?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IFritzPortForward {
  id?: string;
  index?: number;
  connectionType?: string;
  description?: string;
  enabled?: boolean;
  internalClient?: string;
  internalPort?: number;
  externalPort?: number;
  protocol?: string;
  remoteHost?: string;
  leaseDuration?: number;
  metadata?: Record<string, unknown>;
}

export interface IFritzCallDeflection {
  id: string | number;
  enabled?: boolean;
  type?: string;
  number?: string;
  deflectionToNumber?: string;
  mode?: string;
  outgoing?: string;
  phonebookId?: string | number;
  metadata?: Record<string, unknown>;
}

export interface IFritzUpdateInfo {
  installedVersion?: string;
  latestVersion?: string;
  releaseUrl?: string;
  updateAvailable?: boolean;
  metadata?: Record<string, unknown>;
}

export interface IFritzActionDescriptor {
  target: 'router' | 'client' | 'wifi' | 'port_forward' | 'call_deflection' | 'service';
  action: TFritzAction;
  service?: string;
  mac?: string;
  entityId?: string;
  deviceId?: string;
  id?: string | number;
  label?: string;
  metadata?: Record<string, unknown>;
}

export interface IFritzSnapshot {
  connected: boolean;
  source?: TFritzSnapshotSource;
  updatedAt?: string;
  router: IFritzRouterInfo;
  devices: IFritzClientDevice[];
  interfaces: IFritzInterfaceStats[];
  connection: IFritzConnectionInfo;
  sensors: IFritzSensorMap;
  wifiNetworks: IFritzWifiNetwork[];
  portForwards: IFritzPortForward[];
  callDeflections: IFritzCallDeflection[];
  update?: IFritzUpdateInfo;
  actions?: IFritzActionDescriptor[];
  events?: IFritzEvent[];
  error?: string;
  metadata?: Record<string, unknown>;
}

export interface IFritzManualEntry {
  id?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  router?: IFritzRouterInfo;
  devices?: IFritzClientDevice[];
  clients?: IFritzClientDevice[];
  interfaces?: IFritzInterfaceStats[];
  connection?: IFritzConnectionInfo;
  sensors?: IFritzSensorMap;
  wifiNetworks?: IFritzWifiNetwork[];
  portForwards?: IFritzPortForward[];
  callDeflections?: IFritzCallDeflection[];
  update?: IFritzUpdateInfo;
  actions?: IFritzActionDescriptor[];
  snapshot?: IFritzSnapshot;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IFritzManualDiscoveryRecord extends IFritzManualEntry {
  integrationDomain?: string;
}

export interface IFritzSsdpDiscoveryRecord {
  source?: string;
  integrationDomain?: string;
  id?: string;
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  ssdpLocation?: string;
  ssdp_location?: string;
  location?: string;
  st?: string;
  usn?: string;
  udn?: string;
  upnp?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IFritzMdnsDiscoveryRecord {
  source?: string;
  integrationDomain?: string;
  id?: string;
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  serviceType?: string;
  type?: string;
  fullname?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IFritzCommand {
  type: TFritzCommandType;
  service: string;
  action: TFritzAction;
  target: {
    entityId?: string;
    deviceId?: string;
  };
  routerId?: string;
  mac?: string;
  entityId?: string;
  deviceId?: string;
  payload?: Record<string, unknown>;
}

export interface IFritzCommandResult extends IServiceCallResult {}

export interface IFritzEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  command?: IFritzCommand;
  snapshot?: IFritzSnapshot;
  error?: string;
  data?: unknown;
  [key: string]: unknown;
}

export interface IFritzNativeClient {
  getSnapshot(): Promise<IFritzSnapshot> | IFritzSnapshot;
  executeCommand?(commandArg: IFritzCommand): Promise<IFritzCommandResult | unknown> | IFritzCommandResult | unknown;
  destroy?(): Promise<void> | void;
}

export type TFritzSnapshotProvider = () => Promise<IFritzSnapshot | undefined> | IFritzSnapshot | undefined;
export type TFritzCommandExecutor = (
  commandArg: IFritzCommand
) => Promise<IFritzCommandResult | unknown> | IFritzCommandResult | unknown;
