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

export const go2rtcDefaultApiPort = 1984;
export const go2rtcDefaultRtspPort = 8554;
export const go2rtcDefaultWebRtcPort = 8555;
export const go2rtcDefaultTimeoutMs = 8000;
export const go2rtcRecommendedVersion = '1.9.14';

export type TGo2rtcProtocol = 'http' | 'https';
export type TGo2rtcSnapshotSource = 'snapshot' | 'http' | 'executor' | 'manual' | 'runtime';
export type TGo2rtcTrackKind = 'video' | 'audio' | 'microphone' | 'application' | 'unknown';
export type TGo2rtcStreamProtocol = 'rtsp' | 'rtsps' | 'http' | 'https' | 'webrtc' | 'ffmpeg' | 'exec' | 'unknown';
export type TGo2rtcCommandType =
  | 'refresh'
  | 'restart'
  | 'stream_source'
  | 'snapshot_image'
  | 'add_stream'
  | 'update_stream'
  | 'delete_stream'
  | 'stream_to_camera';

export interface IGo2rtcConfig {
  url?: string;
  host?: string;
  port?: number;
  protocol?: TGo2rtcProtocol;
  username?: string;
  password?: string;
  timeoutMs?: number;
  name?: string;
  uniqueId?: string;
  snapshot?: IGo2rtcSnapshot;
  streams?: IGo2rtcStream[];
  cameras?: IGo2rtcCamera[];
  sensors?: IGo2rtcSensor[];
  schemes?: string[];
  serverInfo?: IGo2rtcServerInfo;
  rtsp?: IGo2rtcRtspOptions;
  webrtc?: IGo2rtcWebRtcOptions;
  connected?: boolean;
  commandExecutor?: IGo2rtcCommandExecutor;
  metadata?: Record<string, unknown>;
}

export interface IHomeAssistantGo2rtcConfig extends IGo2rtcConfig {}

export interface IGo2rtcRtspOptions {
  host?: string;
  port?: number;
  enabled?: boolean;
  defaultQuery?: string;
}

export interface IGo2rtcWebRtcOptions {
  host?: string;
  port?: number;
  enabled?: boolean;
  candidates?: string[];
  iceServers?: IGo2rtcIceServer[];
}

export interface IGo2rtcIceServer {
  urls: string | string[];
  username?: string;
  credential?: string;
}

export interface IGo2rtcCommandExecutor {
  execute(requestArg: IGo2rtcRawCommandRequest): Promise<IGo2rtcCommandExecutorResult | Response | ArrayBuffer | Uint8Array | string | unknown>;
}

export interface IGo2rtcRawCommandRequest {
  label: string;
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
  path: string;
  query?: Record<string, string | number | boolean | undefined>;
  body?: string | Uint8Array;
  headers?: Record<string, string>;
  expect?: 'json' | 'text' | 'image' | 'empty';
  url?: string;
}

export interface IGo2rtcCommandExecutorResult {
  ok?: boolean;
  success?: boolean;
  status?: number;
  contentType?: string;
  data?: unknown;
  body?: string | Uint8Array | ArrayBuffer;
  response?: unknown;
  responseText?: string;
}

export interface IGo2rtcServerInfo {
  version?: string;
  configPath?: string;
  host?: string;
  rtsp?: {
    listen?: string;
    defaultQuery?: string;
  };
  raw?: Record<string, unknown>;
}

export interface IGo2rtcEndpointSet {
  apiUrl?: string;
  snapshotUrl?: string;
  mjpegUrl?: string;
  mp4Url?: string;
  hlsUrl?: string;
  whepUrl?: string;
  websocketUrl?: string;
  rtspUrl?: string;
}

export interface IGo2rtcTrack {
  kind: TGo2rtcTrackKind;
  codec?: string;
  media?: string;
  direction?: string;
  raw?: Record<string, unknown>;
}

export interface IGo2rtcProducerConsumer {
  id?: string;
  url?: string;
  remoteAddress?: string;
  protocol?: TGo2rtcStreamProtocol;
  userAgent?: string;
  state?: string;
  tracks?: IGo2rtcTrack[];
  raw?: Record<string, unknown>;
}

export interface IGo2rtcStream {
  id: string;
  name: string;
  sourceUrls: string[];
  producerCount: number;
  consumerCount: number;
  producers: IGo2rtcProducerConsumer[];
  consumers: IGo2rtcProducerConsumer[];
  online: boolean;
  configured: boolean;
  endpoints?: IGo2rtcEndpointSet;
  protocols?: TGo2rtcStreamProtocol[];
  tracks?: IGo2rtcTrack[];
  metadata?: Record<string, unknown>;
}

export interface IGo2rtcCamera {
  id: string;
  name: string;
  streamId: string;
  streamName: string;
  available: boolean;
  endpoints: IGo2rtcEndpointSet;
  sourceUrls: string[];
  protocols?: TGo2rtcStreamProtocol[];
  tracks?: IGo2rtcTrack[];
  metadata?: Record<string, unknown>;
}

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

export interface IGo2rtcSnapshot {
  id: string;
  name: string;
  connected: boolean;
  configured: boolean;
  source: TGo2rtcSnapshotSource;
  serverInfo?: IGo2rtcServerInfo;
  schemes: string[];
  streams: IGo2rtcStream[];
  cameras: IGo2rtcCamera[];
  sensors: IGo2rtcSensor[];
  endpoints: IGo2rtcEndpointSet;
  rtsp?: IGo2rtcRtspOptions;
  webrtc?: IGo2rtcWebRtcOptions;
  updatedAt?: string;
  error?: string;
  metadata?: Record<string, unknown>;
}

export interface IGo2rtcRawStreamsResponse {
  [streamName: string]: IGo2rtcRawStreamInfo | undefined;
}

export interface IGo2rtcRawStreamInfo {
  producers?: IGo2rtcRawProducerConsumer[];
  consumers?: IGo2rtcRawProducerConsumer[];
  [key: string]: unknown;
}

export interface IGo2rtcRawProducerConsumer {
  id?: string | number;
  url?: string;
  remote_addr?: string;
  remoteAddr?: string;
  remoteAddress?: string;
  user_agent?: string;
  userAgent?: string;
  state?: string;
  medias?: unknown[];
  tracks?: unknown[];
  [key: string]: unknown;
}

export interface IGo2rtcSnapshotImage {
  contentType: string;
  data: Uint8Array;
}

export interface IGo2rtcSnapshotCommand {
  streamId?: string;
  width?: number;
  height?: number;
  filename?: string;
}

export interface IGo2rtcStreamSourceCommand {
  streamId?: string;
  endpoint?: keyof IGo2rtcEndpointSet;
}

export interface IGo2rtcStreamMutationCommand {
  streamId?: string;
  name?: string;
  src?: string;
  dst?: string;
}

export interface IGo2rtcClientCommand {
  type: TGo2rtcCommandType;
  service: string;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  data?: Record<string, unknown>;
  streamId?: string;
  snapshot?: IGo2rtcSnapshotCommand;
  streamSource?: IGo2rtcStreamSourceCommand;
  streamMutation?: IGo2rtcStreamMutationCommand;
  httpCommands?: IGo2rtcRawCommandRequest[];
}

export interface IGo2rtcServiceCallResult extends IServiceCallResult {}

export interface IGo2rtcManualEntry {
  url?: string;
  host?: string;
  port?: number;
  protocol?: TGo2rtcProtocol;
  id?: string;
  name?: string;
  username?: string;
  password?: string;
  snapshot?: IGo2rtcSnapshot;
  streams?: IGo2rtcStream[];
  metadata?: Record<string, unknown>;
}

export interface IGo2rtcHttpCandidateRecord {
  url?: string;
  host?: string;
  port?: number;
  protocol?: TGo2rtcProtocol;
  name?: string;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}
