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

export const synologySrmDomain = 'synology_srm';
export const synologySrmDefaultHttpPort = 8000;
export const synologySrmDefaultHttpsPort = 8001;
export const synologySrmDefaultSsl = true;
export const synologySrmDefaultVerifySsl = false;
export const synologySrmDefaultUsername = 'admin';
export const synologySrmDefaultConsiderHomeSeconds = 180;

export type TSynologySrmSnapshotSource = 'snapshot' | 'manual' | 'provider' | 'runtime';
export type TSynologySrmCommandType = 'router.action' | 'client.action' | 'switch.set';
export type TSynologySrmRouterAction = 'reboot';
export type TSynologySrmClientAction = 'block_client' | 'unblock_client' | 'set_client_blocked' | 'set_client_high_qos' | 'set_client_low_qos' | 'set_client_parental_control';
export type TSynologySrmSwitchAction = 'set_switch_enabled';
export type TSynologySrmAction = TSynologySrmRouterAction | TSynologySrmClientAction | TSynologySrmSwitchAction;

export interface ISynologySrmConfig {
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  username?: string;
  password?: string;
  considerHomeSeconds?: number;
  connected?: boolean;
  online?: boolean;
  uniqueId?: string;
  name?: string;
  snapshot?: ISynologySrmSnapshot;
  router?: ISynologySrmRouterInfo;
  system?: ISynologySrmSystemInfo;
  network?: ISynologySrmNetworkInfo;
  interfaces?: ISynologySrmInterfaceStats[];
  clients?: ISynologySrmClientDevice[];
  devices?: ISynologySrmClientDevice[];
  traffic?: ISynologySrmTrafficInfo;
  sensors?: ISynologySrmSensorMap;
  switches?: ISynologySrmSwitchInfo[] | Record<string, unknown>;
  actions?: ISynologySrmActionDescriptor[];
  manualEntries?: ISynologySrmManualEntry[];
  events?: ISynologySrmEvent[];
  snapshotProvider?: TSynologySrmSnapshotProvider;
  commandExecutor?: TSynologySrmCommandExecutor;
  nativeClient?: ISynologySrmNativeClient;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHomeAssistantSynologySrmConfig extends ISynologySrmConfig {}

export interface ISynologySrmRouterInfo {
  id?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  name?: string;
  hostname?: string;
  model?: string;
  serialNumber?: string;
  firmware?: string;
  version?: string;
  versionString?: string;
  macAddress?: string;
  configurationUrl?: string;
  manufacturer?: string;
  actions?: TSynologySrmRouterAction[];
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologySrmSystemInfo {
  hostname?: string;
  firmware?: string;
  version?: string;
  versionString?: string;
  uptimeSeconds?: number;
  temperature?: number;
  cpuLoad?: number;
  memoryUsage?: number;
  memoryTotal?: number;
  memoryFree?: number;
  [key: string]: unknown;
}

export interface ISynologySrmNetworkInfo {
  hostname?: string;
  wanIp?: string;
  wanIpv6?: string;
  macs?: string[];
  interfaces?: ISynologySrmInterfaceStats[];
  [key: string]: unknown;
}

export interface ISynologySrmInterfaceStats {
  id?: string;
  name: string;
  label?: string;
  type?: string;
  connected?: boolean;
  macAddress?: string;
  ipAddress?: string;
  ipv6Address?: string;
  rxBytes?: number;
  txBytes?: number;
  rxRate?: number;
  txRate?: number;
  downloadBytes?: number;
  uploadBytes?: number;
  downloadRate?: number;
  uploadRate?: number;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologySrmTrafficInfo {
  downloadBytes?: number;
  uploadBytes?: number;
  downloadRate?: number;
  uploadRate?: number;
  rxBytes?: number;
  txBytes?: number;
  rxRate?: number;
  txRate?: number;
  [key: string]: unknown;
}

export interface ISynologySrmSensorMap {
  connectedClients?: number;
  downloadBytes?: number;
  uploadBytes?: number;
  downloadRate?: number;
  uploadRate?: number;
  cpuLoad?: number;
  memoryUsage?: number;
  temperature?: number;
  uptimeSeconds?: number;
  [key: string]: string | number | boolean | null | undefined;
}

export interface ISynologySrmClientDevice {
  id?: string;
  mac?: string;
  macAddress?: string;
  hostname?: string;
  name?: string;
  ipAddress?: string;
  ip?: string;
  ip6Address?: string;
  connected?: boolean;
  wireless?: boolean;
  guest?: boolean;
  banned?: boolean;
  highQos?: boolean;
  lowQos?: boolean;
  qos?: boolean;
  parentalControlled?: boolean;
  band?: string;
  connection?: string;
  currentRate?: number;
  maxRate?: number;
  rateQuality?: number | string;
  signalStrength?: number;
  transferRxRate?: number;
  transferTxRate?: number;
  meshNodeId?: string;
  deviceType?: string;
  manualDeviceType?: boolean;
  manualHostname?: boolean;
  beamforming?: boolean;
  actions?: TSynologySrmClientAction[];
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologySrmSwitchInfo {
  id?: string;
  key?: string;
  name?: string;
  enabled: boolean;
  type?: 'client_access' | 'client_high_qos' | 'client_low_qos' | 'client_parental_control' | string;
  target?: 'router' | 'client' | 'system';
  mac?: string;
  entityId?: string;
  deviceId?: string;
  action?: TSynologySrmClientAction | TSynologySrmSwitchAction;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologySrmActionDescriptor {
  target: 'router' | 'client' | 'switch';
  action: TSynologySrmAction;
  service?: string;
  mac?: string;
  switchKey?: string;
  entityId?: string;
  deviceId?: string;
  label?: string;
  metadata?: Record<string, unknown>;
}

export interface ISynologySrmSnapshot {
  connected: boolean;
  source?: TSynologySrmSnapshotSource;
  updatedAt?: string;
  router: ISynologySrmRouterInfo;
  system: ISynologySrmSystemInfo;
  network: ISynologySrmNetworkInfo;
  interfaces: ISynologySrmInterfaceStats[];
  clients: ISynologySrmClientDevice[];
  traffic: ISynologySrmTrafficInfo;
  sensors: ISynologySrmSensorMap;
  switches: ISynologySrmSwitchInfo[];
  actions?: ISynologySrmActionDescriptor[];
  events?: ISynologySrmEvent[];
  error?: string;
  metadata?: Record<string, unknown>;
}

export interface ISynologySrmManualEntry {
  id?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  router?: ISynologySrmRouterInfo;
  system?: ISynologySrmSystemInfo;
  network?: ISynologySrmNetworkInfo;
  interfaces?: ISynologySrmInterfaceStats[];
  clients?: ISynologySrmClientDevice[];
  devices?: ISynologySrmClientDevice[];
  traffic?: ISynologySrmTrafficInfo;
  sensors?: ISynologySrmSensorMap;
  switches?: ISynologySrmSwitchInfo[] | Record<string, unknown>;
  actions?: ISynologySrmActionDescriptor[];
  snapshot?: ISynologySrmSnapshot;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologySrmManualDiscoveryRecord extends ISynologySrmManualEntry {
  integrationDomain?: string;
  url?: string;
  username?: string;
  password?: string;
}

export interface ISynologySrmHttpDiscoveryRecord {
  url?: string;
  location?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  name?: string;
  manufacturer?: string;
  model?: string;
  headers?: Record<string, string | undefined>;
  metadata?: Record<string, unknown>;
}

export interface ISynologySrmCommand {
  type: TSynologySrmCommandType;
  service: string;
  action: TSynologySrmAction;
  target: {
    entityId?: string;
    deviceId?: string;
  };
  routerId?: string;
  mac?: string;
  switchKey?: string;
  entityId?: string;
  deviceId?: string;
  payload?: Record<string, unknown>;
}

export interface ISynologySrmCommandResult extends IServiceCallResult {}

export interface ISynologySrmEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  command?: ISynologySrmCommand;
  snapshot?: ISynologySrmSnapshot;
  error?: string;
  data?: unknown;
  [key: string]: unknown;
}

export interface ISynologySrmNativeClient {
  getSnapshot(): Promise<ISynologySrmSnapshot> | ISynologySrmSnapshot;
  executeCommand?(commandArg: ISynologySrmCommand): Promise<ISynologySrmCommandResult | unknown> | ISynologySrmCommandResult | unknown;
  destroy?(): Promise<void> | void;
}

export type TSynologySrmSnapshotProvider = () => Promise<ISynologySrmSnapshot | undefined> | ISynologySrmSnapshot | undefined;
export type TSynologySrmCommandExecutor = (
  commandArg: ISynologySrmCommand
) => Promise<ISynologySrmCommandResult | unknown> | ISynologySrmCommandResult | unknown;
