export const prusaLinkDomain = 'prusalink';
export const prusaLinkDefaultPort = 80;
export const prusaLinkDefaultUsername = 'maker';
export const prusaLinkDefaultTimeoutMs = 10000;

export type TPrusaLinkSnapshotSource = 'http' | 'client' | 'manual' | 'snapshot' | 'runtime';
export type TPrusaLinkCommandAction = 'pause' | 'resume' | 'cancel' | 'restart';
export type TPrusaLinkPrinterState =
  | 'idle'
  | 'busy'
  | 'printing'
  | 'paused'
  | 'finished'
  | 'stopped'
  | 'error'
  | 'attention'
  | 'ready'
  | 'unknown'
  | string;

export interface IPrusaLinkConfig {
  host?: string;
  port?: number;
  ssl?: boolean;
  tls?: boolean;
  verifySsl?: boolean;
  username?: string;
  password?: string;
  timeoutMs?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  uniqueId?: string;
  snapshot?: IPrusaLinkSnapshot;
  rawData?: Partial<IPrusaLinkRawData>;
  version?: IPrusaLinkVersionInfo;
  status?: IPrusaLinkPrinterStatus;
  legacyStatus?: IPrusaLinkLegacyPrinterStatus;
  job?: IPrusaLinkJobInfo;
  info?: IPrusaLinkPrinterInfo;
  client?: IPrusaLinkClientLike;
  commandExecutor?: IPrusaLinkCommandExecutor;
  online?: boolean;
}

export interface IHomeAssistantPrusalinkConfig extends IPrusaLinkConfig {}

export interface IPrusaLinkClientLike {
  getSnapshot?: () => Promise<IPrusaLinkSnapshot | Partial<IPrusaLinkRawData>>;
  getVersion?: () => Promise<IPrusaLinkVersionInfo>;
  getStatus?: () => Promise<IPrusaLinkPrinterStatus>;
  getLegacyPrinter?: () => Promise<IPrusaLinkLegacyPrinterStatus>;
  getJob?: () => Promise<IPrusaLinkJobInfo>;
  getInfo?: () => Promise<IPrusaLinkPrinterInfo>;
  getFile?: (pathArg: string) => Promise<ArrayBuffer | Uint8Array>;
}

export interface IPrusaLinkCommandExecutor {
  execute(requestArg: IPrusaLinkCommandRequest): Promise<unknown>;
}

export interface IPrusaLinkCommandRequest {
  action: TPrusaLinkCommandAction;
  jobId?: number;
  method?: 'DELETE' | 'PUT';
  path?: string;
  host?: string;
  service?: string;
  target?: Record<string, unknown>;
  data?: Record<string, unknown>;
}

export interface IPrusaLinkRefreshResult {
  success: boolean;
  snapshot?: IPrusaLinkSnapshot;
  error?: string;
  data?: Record<string, unknown>;
}

export interface IPrusaLinkRawData {
  version?: IPrusaLinkVersionInfo;
  status?: IPrusaLinkPrinterStatus;
  legacyStatus?: IPrusaLinkLegacyPrinterStatus;
  job?: IPrusaLinkJobInfo;
  info?: IPrusaLinkPrinterInfo;
}

export interface IPrusaLinkVersionInfo {
  api?: string;
  version?: string;
  printer?: string;
  text?: string;
  firmware?: string;
  sdk?: string | null;
  hostname?: string | null;
  original?: string;
  server?: string;
  capabilities?: {
    upload_by_put?: boolean | null;
    [key: string]: unknown;
  } | null;
  [key: string]: unknown;
}

export interface IPrusaLinkPrinterInfo {
  mmu?: boolean | null;
  name?: string | null;
  location?: string | null;
  farm_mode?: boolean | null;
  nozzle_diameter?: number | string | null;
  min_extrusion_temp?: number | null;
  serial?: string | null;
  sd_ready?: boolean | null;
  active_camera?: boolean | null;
  hostname?: string | null;
  port?: string | number | null;
  network_error_chime?: boolean | null;
  [key: string]: unknown;
}

export interface IPrusaLinkStatusInfo {
  ok?: boolean | null;
  message?: string | null;
  [key: string]: unknown;
}

export interface IPrusaLinkPrinterStatusInfo {
  state?: string | null;
  temp_nozzle?: number | string | null;
  target_nozzle?: number | string | null;
  temp_bed?: number | string | null;
  target_bed?: number | string | null;
  axis_x?: number | string | null;
  axis_y?: number | string | null;
  axis_z?: number | string | null;
  flow?: number | string | null;
  speed?: number | string | null;
  fan_hotend?: number | string | null;
  fan_print?: number | string | null;
  status_printer?: IPrusaLinkStatusInfo | null;
  status_connect?: IPrusaLinkStatusInfo | null;
  [key: string]: unknown;
}

export interface IPrusaLinkPrinterStatus {
  printer?: IPrusaLinkPrinterStatusInfo;
  [key: string]: unknown;
}

export interface IPrusaLinkLegacyPrinterStatus {
  telemetry?: {
    material?: string | null;
    [key: string]: unknown;
  } | null;
  [key: string]: unknown;
}

export interface IPrusaLinkPrintFileRefs {
  download?: string | null;
  icon?: string | null;
  thumbnail?: string | null;
  [key: string]: unknown;
}

export interface IPrusaLinkJobFile {
  name?: string;
  display_name?: string | null;
  path?: string;
  display_path?: string | null;
  size?: number | null;
  m_timestamp?: number | null;
  meta?: Record<string, unknown> | null;
  refs?: IPrusaLinkPrintFileRefs | null;
  [key: string]: unknown;
}

export interface IPrusaLinkJobInfo {
  id?: number | string;
  state?: string;
  progress?: number | string | null;
  time_remaining?: number | string | null;
  time_printing?: number | string | null;
  inaccurate_estimates?: boolean | null;
  serial_print?: boolean | null;
  file?: IPrusaLinkJobFile | null;
  [key: string]: unknown;
}

export interface IPrusaLinkPrinterSnapshotInfo {
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  firmware?: string;
  apiVersion?: string;
  linkVersion?: string;
  sdk?: string | null;
  hostname?: string;
  location?: string;
  host?: string;
  port?: number;
  baseUrl?: string;
  ssl?: boolean;
  nozzleDiameter?: number;
  minExtrusionTemp?: number;
  mmu?: boolean;
  sdReady?: boolean;
  activeCamera?: boolean;
  farmMode?: boolean;
}

export interface IPrusaLinkTelemetrySnapshot {
  state: TPrusaLinkPrinterState;
  tempNozzle?: number;
  targetNozzle?: number;
  tempBed?: number;
  targetBed?: number;
  axisX?: number;
  axisY?: number;
  axisZ?: number;
  printFlow?: number;
  printSpeed?: number;
  fanHotend?: number;
  fanPrint?: number;
  material?: string;
  statusPrinter?: IPrusaLinkStatusInfo;
  statusConnect?: IPrusaLinkStatusInfo;
}

export interface IPrusaLinkJobSnapshot {
  id?: number;
  state?: TPrusaLinkPrinterState;
  progress?: number;
  filename?: string;
  filePath?: string;
  displayPath?: string;
  thumbnailPath?: string;
  downloadPath?: string;
  iconPath?: string;
  fileSize?: number;
  timeRemainingSeconds?: number;
  timePrintingSeconds?: number;
  startedAt?: string;
  finishesAt?: string;
  inaccurateEstimates?: boolean;
  serialPrint?: boolean;
  active: boolean;
  rawFile?: IPrusaLinkJobFile;
}

export interface IPrusaLinkSnapshot {
  printer: IPrusaLinkPrinterSnapshotInfo;
  telemetry: IPrusaLinkTelemetrySnapshot;
  job: IPrusaLinkJobSnapshot;
  rawData?: Partial<IPrusaLinkRawData>;
  online: boolean;
  updatedAt?: string;
  source?: TPrusaLinkSnapshotSource;
  error?: string;
}

export interface IPrusaLinkManualEntry {
  host?: string;
  url?: string;
  port?: number;
  ssl?: boolean;
  tls?: boolean;
  verifySsl?: boolean;
  username?: string;
  password?: string;
  apiKey?: string;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  snapshot?: IPrusaLinkSnapshot;
  rawData?: Partial<IPrusaLinkRawData>;
  version?: IPrusaLinkVersionInfo;
  status?: IPrusaLinkPrinterStatus;
  legacyStatus?: IPrusaLinkLegacyPrinterStatus;
  job?: IPrusaLinkJobInfo;
  info?: IPrusaLinkPrinterInfo;
  metadata?: Record<string, unknown>;
}

export interface IPrusaLinkHttpCandidateRecord {
  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>;
}
