import type { Attachment, DefaultGenerics, ExtendableGenerics, OGAttachment } from 'stream-chat';
import type { DefaultStreamChatGenerics } from '../../types/types';

export type AttachmentLoadingState = 'uploading' | 'finished' | 'failed';

export enum LinkPreviewState {
  /** Link preview has been dismissed using MessageInputContextValue.dismissLinkPreview **/
  DISMISSED = 'dismissed',
  /** Link preview could not be loaded, the enrichment request has failed. **/
  FAILED = 'failed',
  /** Link preview has been successfully loaded. **/
  LOADED = 'loaded',
  /** The enrichment query is in progress for a given link. **/
  LOADING = 'loading',
  /** The link is scheduled for enrichment. **/
  QUEUED = 'queued',
}

export type LinkURL = string;

export type LinkPreview = OGAttachment & {
  state: LinkPreviewState;
};

export enum SetLinkPreviewMode {
  UPSERT,
  SET,
  REMOVE,
}

export type LinkPreviewMap = Map<LinkURL, LinkPreview>;

export type VoiceRecordingAttachment<
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
> = Attachment<StreamChatGenerics> & {
  asset_url: string;
  type: 'voiceRecording';
  duration?: number;
  file_size?: number;
  mime_type?: string;
  title?: string;
  waveform_data?: Array<number>;
};

type FileAttachment<
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
> = Attachment<StreamChatGenerics> & {
  type: 'file';
  asset_url?: string;
  file_size?: number;
  mime_type?: string;
  title?: string;
};

export type AudioAttachment<
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
> = Attachment<StreamChatGenerics> & {
  type: 'audio';
  asset_url?: string;
  file_size?: number;
  mime_type?: string;
  title?: string;
};

export type VideoAttachment<
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
> = Attachment<StreamChatGenerics> & {
  type: 'video';
  asset_url?: string;
  mime_type?: string;
  thumb_url?: string;
  title?: string;
};

type ImageAttachment<
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
> = Attachment<StreamChatGenerics> & {
  type: 'image';
  fallback?: string;
  image_url?: string;
  original_height?: number;
  original_width?: number;
};

export type BaseLocalAttachmentMetadata = {
  id: string;
};

export type LocalAttachmentUploadMetadata = {
  file?: File;
  uploadState?: AttachmentLoadingState;
};

export type LocalImageAttachmentUploadMetadata = LocalAttachmentUploadMetadata & {
  previewUri?: string;
};

export type LocalAttachmentCast<A, L = Record<string, unknown>> = A & {
  localMetadata: L & BaseLocalAttachmentMetadata;
};

export type LocalAttachmentMetadata<
  CustomLocalMetadata = Record<string, unknown>
> = CustomLocalMetadata & BaseLocalAttachmentMetadata & LocalImageAttachmentUploadMetadata;

export type LocalVoiceRecordingAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  VoiceRecordingAttachment<StreamChatGenerics>,
  LocalAttachmentUploadMetadata & CustomLocalMetadata
>;

export type LocalAudioAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  AudioAttachment<StreamChatGenerics>,
  LocalAttachmentUploadMetadata & CustomLocalMetadata
>;

export type LocalVideoAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  VideoAttachment<StreamChatGenerics>,
  LocalAttachmentUploadMetadata & CustomLocalMetadata
>;

export type LocalImageAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  ImageAttachment<StreamChatGenerics>,
  LocalImageAttachmentUploadMetadata & CustomLocalMetadata
>;

export type LocalFileAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  FileAttachment<StreamChatGenerics>,
  LocalAttachmentUploadMetadata & CustomLocalMetadata
>;

export type AnyLocalAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = LocalAttachmentCast<
  Attachment<StreamChatGenerics>,
  LocalAttachmentMetadata<CustomLocalMetadata>
>;

export type LocalAttachment<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
> =
  | AnyLocalAttachment<StreamChatGenerics>
  | LocalFileAttachment<StreamChatGenerics>
  | LocalImageAttachment<StreamChatGenerics>
  | LocalAudioAttachment<StreamChatGenerics>
  | LocalVideoAttachment<StreamChatGenerics>
  | LocalVoiceRecordingAttachment<StreamChatGenerics>;

export type LocalAttachmentToUpload<
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
  CustomLocalMetadata = Record<string, unknown>
> = Partial<Attachment<StreamChatGenerics>> & {
  localMetadata: Partial<BaseLocalAttachmentMetadata> &
    LocalAttachmentUploadMetadata &
    CustomLocalMetadata;
};
