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

export const onvifDefaultPort = 80;
export const onvifDefaultDeviceServicePath = '/onvif/device_service';

export type TOnvifTransport = 'http' | 'https';
export type TOnvifStreamProtocol = 'rtsp' | 'rtsps' | 'http' | 'https' | 'unknown';
export type TOnvifEventPlatform = Extract<TEntityPlatform, 'sensor' | 'binary_sensor'>;
export type TOnvifPtzMoveMode = 'ContinuousMove' | 'RelativeMove' | 'AbsoluteMove' | 'GotoPreset' | 'Stop';
export type TOnvifPanDirection = 'LEFT' | 'RIGHT';
export type TOnvifTiltDirection = 'UP' | 'DOWN';
export type TOnvifZoomDirection = 'ZOOM_IN' | 'ZOOM_OUT';

export interface IOnvifConfig {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  username?: string;
  password?: string;
  transport?: TOnvifTransport;
  deviceServicePath?: string;
  deviceInfo?: IOnvifDeviceInfo;
  capabilities?: IOnvifCapabilities;
  profiles?: IOnvifProfile[];
  streams?: IOnvifStream[];
  events?: IOnvifEvent[];
  cameras?: IOnvifCameraSnapshot[];
  snapshot?: IOnvifSnapshot;
  manualEntries?: IOnvifManualEntry[];
  discovery?: IOnvifDiscoveryRecord;
  soap?: IOnvifSoapOptions;
  metadata?: Record<string, unknown>;
}

export interface IHomeAssistantOnvifConfig extends IOnvifConfig {}

export interface IOnvifSoapOptions {
  timeoutMs?: number;
  basicAuth?: boolean;
  wsSecurityUsernameToken?: boolean;
  fetchStreamUris?: boolean;
  fetchSnapshotUris?: boolean;
  liveProbe?: boolean;
}

export interface IOnvifDeviceInfo {
  name?: string;
  manufacturer?: string;
  model?: string;
  firmwareVersion?: string;
  hardwareId?: string;
  serialNumber?: string;
  macAddress?: string;
  host?: string;
  port?: number;
  configurationUrl?: string;
  [key: string]: unknown;
}

export interface IOnvifCapabilities {
  snapshot?: boolean;
  events?: boolean;
  pullPointEvents?: boolean;
  webhookEvents?: boolean;
  ptz?: boolean;
  imaging?: boolean;
  media?: boolean;
  stream?: boolean;
  supportedProfiles?: string[];
  raw?: Record<string, unknown>;
}

export interface IOnvifResolution {
  width: number;
  height: number;
}

export interface IOnvifVideoProfile {
  encoding?: string;
  resolution?: IOnvifResolution;
  frameRate?: number;
  bitrate?: number;
}

export interface IOnvifPtzCapabilities {
  continuous?: boolean;
  relative?: boolean;
  absolute?: boolean;
  presets?: string[];
  auxiliaryCommands?: string[];
}

export interface IOnvifProfile {
  index?: number;
  token: string;
  name?: string;
  video?: IOnvifVideoProfile;
  ptz?: IOnvifPtzCapabilities;
  videoSourceToken?: string;
  streamUri?: string;
  snapshotUri?: string;
  metadata?: Record<string, unknown>;
}

export interface IOnvifStream {
  id?: string;
  profileToken?: string;
  name?: string;
  uri?: string;
  protocol?: TOnvifStreamProtocol;
  encoding?: string;
  resolution?: IOnvifResolution;
  transport?: 'RTP-Unicast' | 'RTP-Multicast' | string;
  metadata?: Record<string, unknown>;
}

export interface IOnvifPtzCommand {
  profileToken?: string;
  moveMode: TOnvifPtzMoveMode;
  pan?: TOnvifPanDirection;
  tilt?: TOnvifTiltDirection;
  zoom?: TOnvifZoomDirection;
  distance?: number;
  speed?: number;
  continuousDuration?: number;
  preset?: string;
}

export interface IOnvifSnapshotCommand {
  profileToken?: string;
  fetchImage?: boolean;
  width?: number;
  height?: number;
}

export interface IOnvifStreamCommand {
  profileToken?: string;
}

export type TOnvifCommandType =
  | 'snapshot'
  | 'stream_metadata'
  | 'snapshot_metadata'
  | 'ptz'
  | 'subscribe_events'
  | 'refresh';

export interface IOnvifClientCommand {
  type: TOnvifCommandType;
  service: string;
  entityId?: string;
  deviceId?: string;
  profileToken?: string;
  ptz?: IOnvifPtzCommand;
  snapshot?: IOnvifSnapshotCommand;
  stream?: IOnvifStreamCommand;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  data?: Record<string, unknown>;
}

export interface IOnvifServiceCallResult extends IServiceCallResult {}

export interface IOnvifEvent {
  uid: string;
  name: string;
  platform: TOnvifEventPlatform;
  deviceClass?: string;
  unit?: string;
  value?: unknown;
  entityCategory?: string;
  entityEnabled?: boolean;
  timestamp?: number;
  topic?: string;
  metadata?: Record<string, unknown>;
}

export interface IOnvifServiceDescriptor {
  namespace: string;
  xaddr: string;
  version?: string;
  capabilities?: Record<string, unknown>;
}

export interface IOnvifCameraSnapshot {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  transport?: TOnvifTransport;
  online?: boolean;
  deviceInfo?: IOnvifDeviceInfo;
  capabilities?: IOnvifCapabilities;
  profiles: IOnvifProfile[];
  streams?: IOnvifStream[];
  events?: IOnvifEvent[];
  services?: IOnvifServiceDescriptor[];
  metadata?: Record<string, unknown>;
}

export interface IOnvifSnapshot {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  transport?: TOnvifTransport;
  connected: boolean;
  configured: boolean;
  deviceInfo?: IOnvifDeviceInfo;
  capabilities?: IOnvifCapabilities;
  profiles?: IOnvifProfile[];
  streams?: IOnvifStream[];
  events?: IOnvifEvent[];
  services?: IOnvifServiceDescriptor[];
  cameras: IOnvifCameraSnapshot[];
  discovery?: IOnvifDiscoveryRecord;
  metadata?: Record<string, unknown>;
}

export interface IOnvifManualEntry {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  username?: string;
  password?: string;
  transport?: TOnvifTransport;
  deviceInfo?: IOnvifDeviceInfo;
  capabilities?: IOnvifCapabilities;
  profiles?: IOnvifProfile[];
  streams?: IOnvifStream[];
  events?: IOnvifEvent[];
  snapshot?: IOnvifSnapshot;
  metadata?: Record<string, unknown>;
}

export interface IOnvifDiscoveryRecord {
  source?: 'ws-discovery' | 'mdns' | 'manual' | 'snapshot';
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  transport?: TOnvifTransport;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  xaddrs?: string[];
  scopes?: string[];
  endpointReference?: string;
  serviceTypes?: string[];
  snapshot?: IOnvifSnapshot;
  txt?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
}

export interface IOnvifWsDiscoveryRecord {
  epr?: string;
  endpointReference?: string;
  endpoint_reference?: string;
  xaddrs?: string[] | string;
  xAddrs?: string[] | string;
  XAddrs?: string[] | string;
  scopes?: Array<string | { value?: string; Value?: string }> | string;
  types?: string[] | string;
  name?: string;
  metadata?: Record<string, unknown>;
}

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

export interface IOnvifManualDiscoveryRecord extends IOnvifManualEntry {
  discovery?: IOnvifDiscoveryRecord;
}
