import { action, makeObservable, observable } from 'mobx';
import { loadable } from './Decorators/LoadingDecorator';
import { StorageRecord } from '../types/default';
import { Entity, EntityStore } from './EntityStore';
import { RootStore } from './RootStore';
import { TStorageRecord } from '../pages/StorageDashboard/types';
import request from '../services/request';
import FileDownload from '../services/FileDownload';

type ListRecord = StorageRecord;

export class Storage extends Entity {
  @observable private listRecord: ListRecord;

  constructor(id: string, listRecord: ListRecord) {
    super(id);
    this.listRecord = listRecord;
  }

  get _listRecord(): ListRecord {
    return this.listRecord;
  }

  @action
  setListRecord = (value: ListRecord): void => {
    this.listRecord = value;
  };
}

export class StorageStore extends EntityStore<Storage> {
  // @observable countStorageItem: number | undefined;

  @observable storageRecord: TStorageRecord | undefined;

  @observable nextPage: string | undefined | null;

  @observable previousPage: string | undefined | null;

  constructor(private readonly rootStore: RootStore) {
    super();
    makeObservable(this);
  }

  @loadable
  fetchStorageList(page: number, pageSize: number, sort: string): void {
    request({
      method: 'get',
      url: `store/?page=${page}&page_size=${pageSize}${sort}`,
    }).then(
      action((response: any) => {
        this.entities.clear();
        this.setTotal(response.data.count);
        for (const item of response.data.results) {
          const storage = new Storage(item.id, item);
          storage.setListRecord(item);
          this.entities.set(item.id, storage);
        }
      }),
    );
  }

  @loadable
  fetchStorageRecord(id: number): void {
    request({
      method: 'get',
      url: `store/${id}/`,
    }).then(action((response: any) => (this.storageRecord = response.data)));
  }

  async downloadStorageItem(ids: number[]): Promise<any> {
    const promiseForDownloadItem = (id: number): Promise<number> => {
      return new Promise((resolve, reject) => {
        return request({
          method: 'get',
          url: `store/${id}/download/`,
          responseType: 'blob',
        }).then((res: any) => {
          const regexp = /"(.*?)"/;
          const filename = res.headers['content-disposition'].match(regexp)[1];
          FileDownload(res.data, filename);
          return resolve(id);
        });
      });
    };
    const arrayPromisesForDownload = ids.map((item) => {
      return promiseForDownloadItem(item);
    });

    await Promise.all(arrayPromisesForDownload);
  }

  // Функция для удаления в которой генерируется сначала массив Promise,
  // потом этот массив подставляется в Promise.allSettled() для того,
  // чтобы скачала выполнялись все удаления, а потом уже мы получаем новый список item`ов с бека для таблицы
  @loadable async deleteStorageItem(ids: number[]): Promise<void> {
    const promiseForDeleteItem = (id: number): Promise<number> => {
      return new Promise((resolve, reject) => {
        return request({
          method: 'delete',
          url: `store/${id}/`,
        })
          .then(() => resolve(id))
          .catch(() => reject(id));
      });
    };
    const arrayPromisesForDelete = ids.map((item) => {
      return promiseForDeleteItem(item);
    });

    await Promise.allSettled(arrayPromisesForDelete);
  }
}
