export const synologyDsmDomain = 'synology_dsm';
export const synologyDsmDefaultPort = 5000;
export const synologyDsmDefaultSslPort = 5001;
export const synologyDsmDefaultSsl = true;
export const synologyDsmDefaultVerifySsl = false;
export const synologyDsmDefaultTimeoutMs = 60000;
export const synologyDsmDefaultSnapshotQuality = 1;

export type TSynologyDsmSnapshotSource = 'manual' | 'snapshot' | 'provider' | 'runtime';
export type TSynologyDsmCommandAction =
  | 'reboot'
  | 'shutdown'
  | 'set_home_mode'
  | 'enable_camera_motion_detection'
  | 'disable_camera_motion_detection';

export type TSynologyDsmCommandType = 'system.action' | 'switch.set' | 'camera.action';

export type TSynologyDsmActionTarget = 'system' | 'switch' | 'camera';

export interface ISynologyDsmConfig {
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  username?: string;
  password?: string;
  timeoutMs?: number;
  name?: string;
  uniqueId?: string;
  serial?: string;
  macs?: string[];
  macAddress?: string;
  snapshotQuality?: number;
  snapshot?: ISynologyDsmSnapshot;
  snapshotProvider?: () => Promise<ISynologyDsmSnapshot | undefined>;
  nativeClient?: ISynologyDsmNativeClient;
  commandExecutor?: (commandArg: ISynologyDsmCommand) => Promise<ISynologyDsmCommandResult | unknown>;
  online?: boolean;
  connected?: boolean;
  system?: Partial<ISynologyDsmSystemInfo> & Record<string, unknown>;
  information?: Record<string, unknown>;
  utilization?: ISynologyDsmUtilizationInfo & Record<string, unknown>;
  storage?: Partial<ISynologyDsmStorageInfo> & Record<string, unknown>;
  volumes?: Array<ISynologyDsmVolumeInfo | Record<string, unknown> | string>;
  disks?: Array<ISynologyDsmDiskInfo | Record<string, unknown> | string>;
  network?: ISynologyDsmNetworkInfo & Record<string, unknown>;
  cameras?: Array<ISynologyDsmCameraInfo | Record<string, unknown>>;
  surveillance?: Record<string, unknown>;
  update?: ISynologyDsmUpdateInfo & Record<string, unknown>;
  switches?: Array<ISynologyDsmSwitchInfo | Record<string, unknown>> | Record<string, unknown>;
  security?: ISynologyDsmSecurityInfo & Record<string, unknown>;
  actions?: ISynologyDsmActionDescriptor[];
  events?: ISynologyDsmEvent[];
  metadata?: Record<string, unknown>;
}

export interface IHomeAssistantSynologyDsmConfig extends ISynologyDsmConfig {}

export interface ISynologyDsmNativeClient {
  getSnapshot(): Promise<ISynologyDsmSnapshot>;
  executeCommand?(commandArg: ISynologyDsmCommand): Promise<ISynologyDsmCommandResult | unknown>;
  destroy?(): Promise<void>;
}

export interface ISynologyDsmSnapshot {
  connected: boolean;
  source?: TSynologyDsmSnapshotSource;
  updatedAt?: string;
  system: ISynologyDsmSystemInfo;
  utilization: ISynologyDsmUtilizationInfo;
  storage: ISynologyDsmStorageInfo;
  network: ISynologyDsmNetworkInfo;
  cameras: ISynologyDsmCameraInfo[];
  update?: ISynologyDsmUpdateInfo;
  switches: ISynologyDsmSwitchInfo[];
  security?: ISynologyDsmSecurityInfo;
  actions: ISynologyDsmActionDescriptor[];
  events?: ISynologyDsmEvent[];
  error?: string;
  metadata?: Record<string, unknown>;
}

export interface ISynologyDsmSystemInfo {
  id?: string;
  serial?: string;
  name?: string;
  hostname?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  manufacturer?: string;
  model?: string;
  version?: string;
  versionString?: string;
  temperature?: number;
  uptimeSeconds?: number;
  macs?: string[];
  [key: string]: unknown;
}

export interface ISynologyDsmUtilizationInfo {
  cpuOtherLoad?: number;
  cpuUserLoad?: number;
  cpuSystemLoad?: number;
  cpuTotalLoad?: number;
  cpu1MinLoad?: number;
  cpu5MinLoad?: number;
  cpu15MinLoad?: number;
  memoryRealUsage?: number;
  memorySize?: number;
  memoryCached?: number;
  memoryAvailableSwap?: number;
  memoryAvailableReal?: number;
  memoryTotalSwap?: number;
  memoryTotalReal?: number;
  networkUp?: number;
  networkDown?: number;
  [key: string]: unknown;
}

export interface ISynologyDsmStorageInfo {
  volumes: ISynologyDsmVolumeInfo[];
  disks: ISynologyDsmDiskInfo[];
  [key: string]: unknown;
}

export interface ISynologyDsmVolumeInfo {
  id: string;
  name?: string;
  status?: string;
  sizeTotal?: number;
  sizeUsed?: number;
  percentageUsed?: number;
  diskTempAvg?: number;
  diskTempMax?: number;
  deviceType?: string;
  raidType?: string;
  [key: string]: unknown;
}

export interface ISynologyDsmDiskInfo {
  id: string;
  name?: string;
  vendor?: string;
  model?: string;
  firmware?: string;
  diskType?: string;
  status?: string;
  smartStatus?: string;
  temperature?: number;
  exceedBadSectorThreshold?: boolean;
  belowRemainLifeThreshold?: boolean;
  [key: string]: unknown;
}

export interface ISynologyDsmNetworkInfo {
  hostname?: string;
  macs?: string[];
  uploadRate?: number;
  downloadRate?: number;
  interfaces?: ISynologyDsmNetworkInterfaceInfo[];
  [key: string]: unknown;
}

export interface ISynologyDsmNetworkInterfaceInfo {
  id?: string;
  name?: string;
  mac?: string;
  ipAddress?: string;
  ipv6Address?: string;
  connected?: boolean;
  speedMbps?: number;
  [key: string]: unknown;
}

export interface ISynologyDsmCameraInfo {
  id: string;
  name?: string;
  model?: string;
  enabled?: boolean;
  recording?: boolean;
  motionDetectionEnabled?: boolean;
  rtsp?: string;
  snapshotUrl?: string;
  [key: string]: unknown;
}

export interface ISynologyDsmUpdateInfo {
  installedVersion?: string;
  latestVersion?: string;
  updateAvailable?: boolean;
  releaseUrl?: string;
  availableVersionDetails?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface ISynologyDsmSwitchInfo {
  key: string;
  name?: string;
  enabled: boolean;
  type?: 'home_mode' | string;
  [key: string]: unknown;
}

export interface ISynologyDsmSecurityInfo {
  status?: string;
  statusByCheck?: Record<string, string>;
  [key: string]: unknown;
}

export interface ISynologyDsmActionDescriptor {
  target: TSynologyDsmActionTarget;
  action: TSynologyDsmCommandAction;
  entityId?: string;
  deviceId?: string;
  cameraId?: string;
  switchKey?: string;
  [key: string]: unknown;
}

export interface ISynologyDsmCommand {
  type: TSynologyDsmCommandType;
  service: string;
  action: TSynologyDsmCommandAction;
  target: {
    entityId?: string;
    deviceId?: string;
  };
  serial?: string;
  deviceId?: string;
  entityId?: string;
  cameraId?: string;
  switchKey?: string;
  payload?: Record<string, unknown>;
  snapshotSource?: TSynologyDsmSnapshotSource;
}

export interface ISynologyDsmCommandResult {
  success: boolean;
  error?: string;
  data?: unknown;
}

export interface ISynologyDsmEvent {
  type: string;
  snapshot?: ISynologyDsmSnapshot;
  command?: ISynologyDsmCommand;
  data?: unknown;
  error?: string;
  deviceId?: string;
  entityId?: string;
  timestamp?: number;
}

export interface ISynologyDsmManualDiscoveryRecord {
  integrationDomain?: string;
  host?: string;
  port?: number;
  url?: string;
  ssl?: boolean;
  verifySsl?: boolean;
  username?: string;
  password?: string;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  snapshot?: ISynologyDsmSnapshot;
  metadata?: Record<string, unknown>;
}

export interface ISynologyDsmHttpDiscoveryRecord {
  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 ISynologyDsmSsdpDiscoveryRecord {
  st?: string;
  usn?: string;
  ssdpLocation?: string;
  ssdp_location?: string;
  location?: string;
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  upnp?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
}

export interface ISynologyDsmMdnsDiscoveryRecord {
  type?: string;
  serviceType?: string;
  fullname?: string;
  name?: string;
  host?: string;
  port?: number;
  properties?: Record<string, unknown>;
  txt?: Record<string, unknown>;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  metadata?: Record<string, unknown>;
}
