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

export const embyDomain = 'emby';
export const embyDisplayName = 'Emby';
export const embyDefaultHttpPort = 8096;
export const embyDefaultHttpsPort = 8920;
export const embyDefaultTimeoutMs = 5000;

export type TEmbyProtocol = 'http' | 'https';
export type TEmbySnapshotSource = 'http' | 'client' | 'manual' | 'snapshot' | 'runtime';

export interface IEmbyServerInfo {
  Id?: string;
  ServerId?: string;
  Name?: string;
  ServerName?: string;
  Version?: string;
  ProductName?: string;
  OperatingSystem?: string;
  OperatingSystemDisplayName?: string;
  LocalAddress?: string;
  WanAddress?: string;
  HttpServerPortNumber?: number;
  HttpsPortNumber?: number;
  SupportsHttps?: boolean;
  [key: string]: unknown;
}

export interface IEmbyUser {
  Id: string;
  Name?: string;
  ServerId?: string;
  PrimaryImageTag?: string;
  HasPassword?: boolean;
  HasConfiguredPassword?: boolean;
  [key: string]: unknown;
}

export interface IEmbyPlayState {
  PositionTicks?: number;
  CanSeek?: boolean;
  IsPaused?: boolean;
  IsMuted?: boolean;
  VolumeLevel?: number;
  AudioStreamIndex?: number;
  SubtitleStreamIndex?: number;
  MediaSourceId?: string;
  PlayMethod?: 'Transcode' | 'DirectStream' | 'DirectPlay' | string;
  RepeatMode?: string;
  Shuffle?: boolean;
  PlaybackRate?: number;
  [key: string]: unknown;
}

export interface IEmbyMediaSource {
  Id?: string;
  Path?: string;
  Protocol?: string;
  Container?: string;
  Size?: number;
  Bitrate?: number;
  RunTimeTicks?: number;
  VideoType?: string;
  [key: string]: unknown;
}

export interface IEmbyMediaItem {
  Id?: string;
  Name?: string;
  Type?: string;
  MediaType?: string;
  RunTimeTicks?: number;
  SeriesName?: string;
  ParentIndexNumber?: number;
  IndexNumber?: number;
  Album?: string;
  AlbumArtist?: string;
  Artists?: string[];
  Overview?: string;
  ProductionYear?: number;
  PremiereDate?: string;
  CommunityRating?: number;
  OfficialRating?: string;
  ImageTags?: Record<string, string | undefined>;
  PrimaryImageTag?: string;
  ParentBackdropItemId?: string;
  AlbumId?: string;
  AlbumPrimaryImageTag?: string;
  MediaSources?: IEmbyMediaSource[];
  ChannelId?: string;
  ChannelName?: string;
  [key: string]: unknown;
}

export interface IEmbySessionCapabilities {
  SupportsMediaControl?: boolean;
  SupportsPersistentIdentifier?: boolean;
  SupportsSync?: boolean;
  SupportsContentUploading?: boolean;
  SupportedCommands?: TEmbyGeneralCommand[];
  [key: string]: unknown;
}

export interface IEmbySession {
  Id: string;
  ServerId?: string;
  UserId?: string;
  UserName?: string;
  Client?: string;
  LastActivityDate?: string;
  LastPlaybackCheckIn?: string;
  DeviceName?: string;
  DeviceId?: string;
  DeviceType?: string;
  ApplicationVersion?: string;
  RemoteEndPoint?: string;
  IsActive?: boolean;
  SupportsRemoteControl?: boolean;
  SupportedCommands?: TEmbyGeneralCommand[];
  PlayState?: IEmbyPlayState;
  NowPlayingItem?: IEmbyMediaItem;
  NowViewingItem?: IEmbyMediaItem;
  TranscodingInfo?: Record<string, unknown>;
  Capabilities?: IEmbySessionCapabilities;
  [key: string]: unknown;
}

export interface IEmbySnapshot {
  server: IEmbyServerInfo;
  sessions: IEmbySession[];
  users?: IEmbyUser[];
  online: boolean;
  updatedAt?: string;
  source?: TEmbySnapshotSource;
  error?: string;
}

export type TEmbyPlaystateCommand =
  | 'Stop'
  | 'Pause'
  | 'Unpause'
  | 'NextTrack'
  | 'PreviousTrack'
  | 'Seek'
  | 'Rewind'
  | 'FastForward'
  | 'PlayPause'
  | 'SeekRelative';

export type TEmbyPlayCommand = 'PlayNow' | 'PlayNext' | 'PlayLast' | 'PlayInstantMix' | 'PlayShuffle';

export type TEmbyGeneralCommand = string;

export interface IEmbyGeneralCommandRequest {
  Name: TEmbyGeneralCommand;
  ControllingUserId?: string;
  Arguments?: Record<string, string>;
}

export interface IEmbyClientLike {
  getSnapshot?: () => Promise<IEmbySnapshot>;
  getSystemInfo?: () => Promise<IEmbyServerInfo>;
  getSessions?: () => Promise<IEmbySession[]>;
  execute?: (commandArg: IEmbyCommandRequest) => Promise<unknown>;
  destroy?: () => Promise<void>;
  [key: string]: unknown;
}

export interface IEmbyCommandExecutor {
  execute(commandArg: IEmbyCommandRequest): Promise<unknown>;
}

export type TEmbyCommandAction = 'refresh' | 'playstate' | 'general_command' | 'play_media';

export interface IEmbyCommandRequest {
  action: TEmbyCommandAction;
  sessionId?: string;
  command?: TEmbyPlaystateCommand | TEmbyGeneralCommand;
  arguments?: Record<string, string>;
  itemIds?: string[];
  playCommand?: TEmbyPlayCommand;
  startPositionTicks?: number;
  seekPositionTicks?: number;
  controllingUserId?: string;
  service?: string;
  target?: IServiceCallRequest['target'];
  data?: Record<string, unknown>;
}

export interface IEmbyRefreshResult {
  success: boolean;
  snapshot: IEmbySnapshot;
  error?: string;
  data?: unknown;
}

export interface IEmbyConfig {
  url?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  protocol?: TEmbyProtocol;
  name?: string;
  uniqueId?: string;
  apiKey?: string;
  api_key?: string;
  apiToken?: string;
  accessToken?: string;
  userId?: string;
  deviceId?: string;
  sessionId?: string;
  clientDeviceId?: string;
  deviceName?: string;
  timeoutMs?: number;
  online?: boolean;
  server?: IEmbyServerInfo;
  sessions?: IEmbySession[];
  users?: IEmbyUser[];
  snapshot?: IEmbySnapshot;
  client?: IEmbyClientLike;
  commandExecutor?: IEmbyCommandExecutor;
}

export interface IHomeAssistantEmbyConfig extends IEmbyConfig {}

export interface IEmbyManualEntry extends IEmbyConfig {
  id?: string;
  manufacturer?: string;
  model?: string;
  metadata?: Record<string, unknown>;
}

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

export interface IEmbySsdpRecord {
  st?: string;
  usn?: string;
  location?: string;
  server?: string;
  friendlyName?: string;
  headers?: Record<string, string | undefined>;
}
