import React, { ReactElement, Ref } from 'react';
import { Selection } from 'react-stately';

import { ModalTypes } from '@/components/modal/constants/ModalTypes';

import { Clip, Playlist } from './clipStore';
import { RootStore, Substore } from './rootStore';
import { FeatureKey } from './sessionStore';
import { makeAutoObservableSubstore } from './utils';

interface Position {
  x: number;
  y: number;
}

type ConfirmationModalOptions = {
  title: string;
  renderMessage: () => ReactElement;
  onConfirmFn?: () => void;
  onActionFn?: () => void;
  onCloseFn?: () => void;
  actionButtonText?: string;
  actionButtonClassName?: string;
  confirmButtonText?: string;
  icon?: React.FC<React.SVGProps<SVGSVGElement>>;
};

type DownloadQuotaModalOptions = {
  clipId: string;
  onDownload: () => void;
};

type DownloadSuccessModalOptions = {
  title: string;
  message?: string;
  subMessage?: string;
  songTitle?: string;
  onDownload: () => void;
};

export class MenusStore implements Substore {
  songDropdownTriggeredAt: null | Position = null;
  selected: Selection = new Set();
  playlistSelectedClipIds: string[] = [];
  refToBlur: Ref<any> = null;
  currentClip: Clip | null = null;
  currentPlaylist: Playlist | null = null;
  confirmationModalOptions: ConfirmationModalOptions | null = null;
  downloadQuotaModalOptions: DownloadQuotaModalOptions | null = null;
  downloadSuccessModalOptions: DownloadSuccessModalOptions | null = null;
  featureUpsellConfig: { [key: string]: any } | null = null;
  currentUpsellFeature: FeatureKey | null = null;

  appModalDisclosures: {
    [key in ModalTypes]?: {
      isOpen: boolean;
      onOpen: () => void;
      onClose: () => void;
    };
  } = {};

  readonly root: RootStore;
  get apiClient() {
    return this.root.apiClient;
  }
  // DO NOT ADD INIT LOGIC IN constructor. this will run on every page! considering adding any it in the component init logic instead
  constructor(root: RootStore) {
    this.root = root;
    makeAutoObservableSubstore(this);
  }

  setSongDropdownTriggeredAt(triggeredAt: Position | null) {
    this.songDropdownTriggeredAt = triggeredAt;
  }

  setRefToBlur(ref: Ref<any>) {
    this.refToBlur = ref;
  }

  setCurrentClip(clip: Clip | null) {
    this.currentClip = clip;
  }

  setSelected(selected: Selection) {
    this.selected = new Set(selected);
  }

  setPlaylistSelectedClipIds(clipIds: string[]) {
    this.playlistSelectedClipIds = clipIds;
  }

  get selectedClipIds() {
    // if selected IDs are integers, we are in a playlist context so return the explicitly set clip IDs
    // this can be removed later when playlists are simplified to take
    // advantage of the playlist clip uniqueness constraint
    if (
      [...this.selected].some(
        (selectedId: any) => !/^\d+$/.test(selectedId.toString())
      )
    ) {
      return [...this.selected].map((s) => s.toString());
    }
    return this.playlistSelectedClipIds;
  }

  resetMultiSelect() {
    this.selected = new Set();
    this.refToBlur = null;
    this.currentClip = null;
  }

  setAppModalDisclosures(appModalDisclosures: {
    [key in ModalTypes]?: any;
  }) {
    this.appModalDisclosures = appModalDisclosures;
  }

  openModal(modalKey: ModalTypes) {
    this.appModalDisclosures[modalKey]?.onOpen?.();
  }

  setFeatureUpsellConfig(config: { [key: string]: any } | null) {
    this.featureUpsellConfig = config;
  }

  setCurrentUpsellFeature(feature: FeatureKey | null) {
    this.currentUpsellFeature = feature;
  }

  closeModal(modalKey: ModalTypes) {
    this.appModalDisclosures[modalKey]?.onClose?.();
  }

  setConfirmationModalOptions(options: ConfirmationModalOptions) {
    this.confirmationModalOptions = options;
  }

  setDownloadQuotaModalOptions(options: DownloadQuotaModalOptions | null) {
    this.downloadQuotaModalOptions = options;
  }

  clearDownloadQuotaModalOptions() {
    this.downloadQuotaModalOptions = null;
  }

  openCommercialRightsModal(clipId: string, onDownload: () => void) {
    this.setDownloadQuotaModalOptions({ clipId, onDownload });
    this.openModal(ModalTypes.DOWNLOAD_QUOTA);
  }

  setDownloadSuccessModalOptions(options: DownloadSuccessModalOptions | null) {
    this.downloadSuccessModalOptions = options;
  }

  clearDownloadSuccessModalOptions() {
    this.downloadSuccessModalOptions = null;
  }

  openCommercialRightsSuccessModal(options: DownloadSuccessModalOptions) {
    this.setDownloadSuccessModalOptions(options);
    this.openModal(ModalTypes.COMMERCIAL_RIGHTS_SUCCESS);
  }

  openSubscriptionSuccessModal(options: DownloadSuccessModalOptions) {
    this.setDownloadSuccessModalOptions(options);
    this.openModal(ModalTypes.SUBSCRIPTION_SUCCESS);
  }

  openConfirmationModal({
    title,
    renderMessage,
    onConfirmFn,
    onActionFn,
    onCloseFn,
    confirmButtonText,
    actionButtonText,
    actionButtonClassName,
    icon,
  }: {
    title: string;
    renderMessage: () => ReactElement;
    onConfirmFn: () => void;
    onActionFn?: () => void;
    onCloseFn?: () => void;
    confirmButtonText?: string;
    actionButtonText?: string;
    actionButtonClassName?: string;
    icon?: React.FC<React.SVGProps<SVGSVGElement>>;
  }) {
    this.setConfirmationModalOptions({
      actionButtonClassName,
      actionButtonText,
      confirmButtonText,
      onCloseFn,
      onConfirmFn,
      onActionFn,
      renderMessage,
      title,
      icon,
    });
    this.openModal(ModalTypes.GENERIC_CONFIRM);
  }
}
