export const freeboxDomain = 'freebox';
export const freeboxDisplayName = 'Freebox';
export const freeboxManufacturer = 'Freebox SAS';
export const freeboxDefaultHost = 'mafreebox.freebox.fr';
export const freeboxDefaultPort = 443;
export const freeboxDefaultApiVersion = 'v6';
export const freeboxWifiApiVersion = 'v2';
export const freeboxDefaultApiBaseUrl = '/api/';
export const freeboxDefaultTimeoutMs = 10000;
export const freeboxZeroconfType = '_fbx-api._tcp.local.';

export const freeboxAppDescription = {
  appId: 'hass',
  appName: 'Home Assistant',
  appVersion: '0.106',
} as const;

export const freeboxHomeCategories = {
  alarm: 'alarm',
  camera: 'camera',
  dws: 'dws',
  iohome: 'iohome',
  kfb: 'kfb',
  opener: 'opener',
  pir: 'pir',
  rts: 'rts',
} as const;

export const freeboxHomeCategoryModels: Record<string, string> = {
  [freeboxHomeCategories.pir]: 'F-HAPIR01A',
  [freeboxHomeCategories.camera]: 'F-HACAM01A',
  [freeboxHomeCategories.dws]: 'F-HADWS01A',
  [freeboxHomeCategories.kfb]: 'F-HAKFB01A',
  [freeboxHomeCategories.alarm]: 'F-MSEC07A',
  [freeboxHomeCategories.rts]: 'RTS',
  [freeboxHomeCategories.iohome]: 'IOHome',
};

export type TFreeboxProtocol = 'http' | 'https';
export type TFreeboxSnapshotSource = 'http' | 'client' | 'manual' | 'snapshot' | 'runtime';
export type TFreeboxAuthorizationStatus = 'unknown' | 'pending' | 'timeout' | 'granted' | 'denied';

export interface IFreeboxAppDescription {
  appId?: string;
  appName?: string;
  appVersion?: string;
  deviceName?: string;
}

export interface IFreeboxCommandRequest {
  action: string;
  service?: string;
  target?: Record<string, unknown>;
  data?: Record<string, unknown>;
  endpoint?: string;
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
  body?: unknown;
}

export interface IFreeboxCommandExecutor {
  execute(commandArg: IFreeboxCommandRequest): Promise<unknown> | unknown;
}

export interface IFreeboxClientLike {
  getSnapshot?(): Promise<IFreeboxSnapshot | Partial<IFreeboxRawData> | unknown> | IFreeboxSnapshot | Partial<IFreeboxRawData> | unknown;
  getRawData?(): Promise<Partial<IFreeboxRawData>> | Partial<IFreeboxRawData>;
  execute?(commandArg: IFreeboxCommandRequest): Promise<unknown> | unknown;
  destroy?(): Promise<void> | void;
}

export interface IFreeboxConfig {
  host?: string;
  url?: string;
  port?: number;
  protocol?: TFreeboxProtocol;
  apiVersion?: string;
  wifiApiVersion?: string;
  apiBaseUrl?: string;
  timeoutMs?: number;
  verifyTls?: boolean;
  appToken?: string;
  token?: string;
  sessionToken?: string;
  appDescription?: IFreeboxAppDescription;
  name?: string;
  manufacturer?: string;
  model?: string;
  modelId?: string;
  uniqueId?: string;
  serialNumber?: string;
  macAddress?: string;
  online?: boolean;
  snapshot?: IFreeboxSnapshot;
  rawData?: Partial<IFreeboxRawData>;
  client?: IFreeboxClientLike;
  commandExecutor?: IFreeboxCommandExecutor;
}

export interface IHomeAssistantFreeboxConfig extends IFreeboxConfig {}

export interface IFreeboxApiVersionInfo {
  uid?: string;
  device_name?: string;
  api_version?: string;
  api_base_url?: string;
  device_type?: string;
  api_domain?: string;
  https_available?: boolean;
  https_port?: number;
  [key: string]: unknown;
}

export interface IFreeboxAuthorizationRequest {
  app_token: string;
  track_id: number;
  [key: string]: unknown;
}

export interface IFreeboxAuthorizationProgress {
  status: TFreeboxAuthorizationStatus;
  challenge?: string;
  [key: string]: unknown;
}

export interface IFreeboxSession {
  session_token: string;
  challenge?: string;
  permissions?: Record<string, boolean>;
  [key: string]: unknown;
}

export interface IFreeboxRawData {
  apiVersionInfo?: IFreeboxApiVersionInfo;
  systemConfig?: Record<string, unknown>;
  connectionStatus?: Record<string, unknown>;
  callLog?: Array<Record<string, unknown>>;
  disks?: Array<Record<string, unknown>>;
  raids?: Array<Record<string, unknown>>;
  lanInterfaces?: Array<Record<string, unknown>>;
  lanHosts?: Array<Record<string, unknown>>;
  wifiConfig?: Record<string, unknown>;
  homeNodes?: Array<Record<string, unknown>>;
  errors?: Record<string, string>;
  fetchedAt?: string;
}

export interface IFreeboxRouterSnapshot {
  id: string;
  name: string;
  host?: string;
  port?: number;
  protocol?: TFreeboxProtocol;
  manufacturer: string;
  model?: string;
  modelId?: string;
  firmwareVersion?: string;
  hardwareVersion?: string;
  serialNumber?: string;
  macAddress?: string;
  apiVersion?: string;
  apiBaseUrl?: string;
  uptimeSeconds?: number;
  connection?: Record<string, unknown>;
  attributes?: Record<string, unknown>;
}

export interface IFreeboxSensorSnapshot {
  id: string;
  deviceId: string;
  kind: string;
  name: string;
  value: unknown;
  unit?: string;
  deviceClass?: string;
  stateClass?: string;
  entityCategory?: string;
  available: boolean;
  attributes?: Record<string, unknown>;
}

export interface IFreeboxLanHostSnapshot {
  id: string;
  deviceId: string;
  name: string;
  macAddress?: string;
  manufacturer?: string;
  hostType?: string;
  active: boolean;
  reachable?: boolean;
  addresses: string[];
  attributes?: Record<string, unknown>;
}

export interface IFreeboxDiskSnapshot {
  id: string;
  name: string;
  diskId?: number | string;
  model?: string;
  serialNumber?: string;
  firmwareVersion?: string;
  type?: string;
  state?: string;
  totalBytes?: number;
  temperature?: number;
  partitions: IFreeboxPartitionSnapshot[];
  attributes?: Record<string, unknown>;
}

export interface IFreeboxPartitionSnapshot {
  id: string;
  partitionId?: number | string;
  diskId?: number | string;
  label: string;
  state?: string;
  filesystem?: string;
  totalBytes?: number;
  freeBytes?: number;
  usedBytes?: number;
  freePercent?: number;
  attributes?: Record<string, unknown>;
}

export interface IFreeboxRaidSnapshot {
  id: string;
  name: string;
  degraded: boolean;
  attributes?: Record<string, unknown>;
}

export interface IFreeboxHomeNodeSnapshot {
  id: string;
  name: string;
  category?: string;
  model?: string;
  manufacturer: string;
  firmwareVersion?: string;
  status?: string;
  streamUrl?: string;
  showEndpoints: Array<Record<string, unknown>>;
  endpoints: Array<Record<string, unknown>>;
  attributes?: Record<string, unknown>;
}

export interface IFreeboxCapabilitiesSnapshot {
  localRead: boolean;
  localControl: boolean;
  authenticated: boolean;
  wifiControl: boolean;
  homeControl: boolean;
  callControl: boolean;
  reboot: boolean;
}

export interface IFreeboxSnapshot {
  router: IFreeboxRouterSnapshot;
  sensors: IFreeboxSensorSnapshot[];
  lanHosts: IFreeboxLanHostSnapshot[];
  disks: IFreeboxDiskSnapshot[];
  raids: IFreeboxRaidSnapshot[];
  homeNodes: IFreeboxHomeNodeSnapshot[];
  wifiConfig?: Record<string, unknown>;
  callLog: Array<Record<string, unknown>>;
  rawData?: Partial<IFreeboxRawData>;
  capabilities: IFreeboxCapabilitiesSnapshot;
  online: boolean;
  updatedAt: string;
  source: TFreeboxSnapshotSource;
  error?: string;
}

export interface IFreeboxRefreshResult {
  success: boolean;
  snapshot: IFreeboxSnapshot;
  error?: string;
  data?: unknown;
}

export interface IFreeboxManualEntry extends IFreeboxConfig {
  id?: string;
  metadata?: Record<string, unknown>;
}

export interface IFreeboxZeroconfRecord {
  type?: string;
  serviceType?: string;
  name?: string;
  host?: string;
  hostname?: string;
  addresses?: string[];
  port?: number;
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
  metadata?: Record<string, unknown>;
}
