export const delugeDomain = 'deluge';
export const delugeDisplayName = 'Deluge';
export const delugeManufacturer = 'Deluge';
export const delugeDefaultRpcPort = 58846;
export const delugeDefaultWebPort = 8112;
export const delugeDefaultTimeoutMs = 10000;

export type TDelugeProtocol = 'http' | 'https';
export type TDelugeSnapshotSource = 'web' | 'client' | 'manual' | 'snapshot' | 'runtime';
export type TDelugeCommandAction = 'snapshot' | 'refresh' | 'pause' | 'resume' | 'add_torrent' | 'remove_torrent';

export interface IDelugeCommandRequest {
  action: TDelugeCommandAction;
  service?: string;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  data?: Record<string, unknown>;
  torrentIds?: string[];
  magnet?: string;
  url?: string;
  path?: string;
  cookie?: string;
  options?: Record<string, unknown>;
  removeData?: boolean;
}

export interface IDelugeCommandExecutor {
  execute(commandArg: IDelugeCommandRequest): Promise<unknown> | unknown;
}

export interface IDelugeClientLike {
  getSnapshot?(): Promise<IDelugeSnapshot | Partial<IDelugeRawData> | unknown> | IDelugeSnapshot | Partial<IDelugeRawData> | unknown;
  getRawData?(): Promise<Partial<IDelugeRawData>> | Partial<IDelugeRawData>;
  call?(methodArg: string, ...paramsArg: unknown[]): Promise<unknown> | unknown;
  execute?(commandArg: IDelugeCommandRequest): Promise<unknown> | unknown;
  destroy?(): Promise<void> | void;
}

export interface IDelugeConfig {
  host?: string;
  url?: string;
  port?: number;
  webPort?: number;
  web_port?: number;
  rpcPort?: number;
  daemonPort?: number;
  protocol?: TDelugeProtocol;
  password?: string;
  webPassword?: string;
  username?: string;
  daemonUsername?: string;
  daemonHost?: string;
  daemonPassword?: string;
  rpcPassword?: string;
  timeoutMs?: number;
  name?: string;
  uniqueId?: string;
  manufacturer?: string;
  model?: string;
  connected?: boolean;
  snapshot?: IDelugeSnapshot;
  rawData?: Partial<IDelugeRawData>;
  client?: IDelugeClientLike;
  commandExecutor?: IDelugeCommandExecutor;
}

export interface IHomeAssistantDelugeConfig extends IDelugeConfig {}

export interface IDelugeDeviceSnapshot {
  id: string;
  name: string;
  manufacturer: string;
  model?: string;
  host?: string;
  webPort?: number;
  rpcPort?: number;
  protocol?: TDelugeProtocol;
  url?: string;
  online: boolean;
}

export interface IDelugeSessionStats {
  downloadRate: number;
  uploadRate: number;
  dhtDownloadRate: number;
  dhtUploadRate: number;
  protocolDownloadRate: number;
  protocolUploadRate: number;
  numConnections?: number;
  dhtNodes?: number;
  freeSpace?: number;
  externalIp?: string;
  maxDownload?: number;
  maxUpload?: number;
  maxConnections?: number;
  hasIncomingConnections?: boolean;
  raw?: Record<string, unknown>;
}

export interface IDelugeTorrentSnapshot {
  id: string;
  name: string;
  state: string;
  paused: boolean;
  progress?: number;
  downloadRate?: number;
  uploadRate?: number;
  totalSize?: number;
  completedSize?: number;
  ratio?: number;
  eta?: number;
  seeds?: number;
  peers?: number;
  trackerHost?: string;
  savePath?: string;
  available: boolean;
  attributes?: Record<string, unknown>;
}

export interface IDelugeSensorSnapshot<TValue = unknown> {
  key: string;
  name: string;
  value: TValue;
  unit?: string;
  deviceClass?: string;
  stateClass?: string;
  entityCategory?: string;
  available: boolean;
  attributes?: Record<string, unknown>;
}

export interface IDelugeSwitchSnapshot {
  key: string;
  name: string;
  isOn: boolean;
  available: boolean;
  attributes?: Record<string, unknown>;
}

export interface IDelugeCapabilitiesSnapshot {
  localRead: boolean;
  localControl: boolean;
  addTorrent: boolean;
  removeTorrent: boolean;
}

export interface IDelugeSnapshot {
  device: IDelugeDeviceSnapshot;
  stats: IDelugeSessionStats;
  torrents: IDelugeTorrentSnapshot[];
  sensors: IDelugeSensorSnapshot[];
  switches: IDelugeSwitchSnapshot[];
  connected: boolean;
  online: boolean;
  source: TDelugeSnapshotSource;
  capabilities: IDelugeCapabilitiesSnapshot;
  updatedAt: string;
  rawData?: Partial<IDelugeRawData>;
  error?: string;
}

export interface IDelugeRawData {
  webUi?: IDelugeWebUpdateUiResponse;
  updateUi?: IDelugeWebUpdateUiResponse;
  sessionStatus?: Record<string, unknown>;
  torrentsStatus?: Record<string, Record<string, unknown>>;
  torrentsPaused?: Record<string, Record<string, unknown>>;
  sessionState?: string[];
  stats?: Record<string, unknown>;
  connected?: boolean;
  fetchedAt?: string;
  errors?: Record<string, string>;
}

export interface IDelugeWebUpdateUiResponse {
  connected?: boolean;
  torrents?: Record<string, Record<string, unknown>>;
  filters?: unknown;
  stats?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IDelugeSnapshotInput {
  config?: IDelugeConfig;
  rawData?: Partial<IDelugeRawData>;
  online?: boolean;
  source?: TDelugeSnapshotSource;
  error?: string;
}

export interface IDelugeSensorDescription {
  key: string;
  name: string;
  unit?: string;
  deviceClass?: string;
  stateClass?: string;
  entityCategory?: string;
}

export interface IDelugeManualEntry {
  host?: string;
  url?: string;
  port?: number;
  webPort?: number;
  web_port?: number;
  rpcPort?: number;
  daemonPort?: number;
  protocol?: TDelugeProtocol;
  password?: string;
  webPassword?: string;
  username?: string;
  daemonUsername?: string;
  daemonHost?: string;
  daemonPassword?: string;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  snapshot?: IDelugeSnapshot;
  rawData?: Partial<IDelugeRawData>;
  client?: IDelugeClientLike;
  commandExecutor?: IDelugeCommandExecutor;
  metadata?: Record<string, unknown>;
}

export interface IDelugeHttpDiscoveryInput {
  id?: string;
  url?: string;
  host?: string;
  port?: number;
  path?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}

export const delugeSensorDescriptions: IDelugeSensorDescription[] = [
  { key: 'current_status', name: 'Status', deviceClass: 'enum' },
  { key: 'download_speed', name: 'Download speed', unit: 'KiB/s', deviceClass: 'data_rate', stateClass: 'measurement' },
  { key: 'upload_speed', name: 'Upload speed', unit: 'KiB/s', deviceClass: 'data_rate', stateClass: 'measurement' },
  { key: 'protocol_traffic_upload_speed', name: 'Protocol traffic upload speed', unit: 'KiB/s', deviceClass: 'data_rate', stateClass: 'measurement' },
  { key: 'protocol_traffic_download_speed', name: 'Protocol traffic download speed', unit: 'KiB/s', deviceClass: 'data_rate', stateClass: 'measurement' },
  { key: 'downloading_count', name: 'Downloading count', stateClass: 'total' },
  { key: 'seeding_count', name: 'Seeding count', stateClass: 'total' },
];
