import { action, makeObservable, observable } from 'mobx';

import {
  AccountRecord,
  AccountRecordFromPost,
  AccountRecordResponse,
  IReadManyResponse,
} from '../types/default';
import { loadable, loadableCard } from './Decorators/LoadingDecorator';
import { Entity, EntityStore } from './EntityStore';
import { RootStore } from './RootStore';
import request from '../services/request';
import { environment } from '../enviroments/enviroments';

type ListRecord = AccountRecordResponse;

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

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

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

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

export class AccountsStore extends EntityStore<Account> {
  @observable selectedAccount:
    | AccountRecord
    | AccountRecordResponse
    | undefined
    | null = null;

  @observable selectedAccountId: number | undefined = undefined;

  nextAccountList: string | null = null;

  previousAccountList: string | null = null;

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

  @action setSelectedAccount = (
    value: AccountRecord | AccountRecordResponse | null | undefined,
  ): void => {
    switch (value) {
      case undefined:
        this.selectedAccount = {
          user: {
            username: '',
            first_name: '',
            email: '',
            password: '',
            is_active: false,
          },
          comment: '',
          timezone: 'Europe/Moscow',
          expire_date: '',
          modified: '',
        };
        break;

      case null:
        this.selectedAccount = null;
        break;

      default:
        this.selectedAccount = value;

        break;
    }
  };

  @loadable
  fetchAccountsList(page: string, pageSize: number, sorter: string): void {
    request({
      method: 'get',
      url:
        page && pageSize
          ? `${environment.endPoints.accounts.users}?page=${page}&page_size=${pageSize}${sorter}`
          : `${environment.endPoints.accounts.users}`,
    }).then(
      //IReqestResponce
      action((response: any) => {
        this.entities.clear();
        for (const item of response.data.results) {
          const account = new Account(item.user.id, item);
          account.setListRecord(item);
          this.entities.set(item.user.id, account);
        }
        this.setTotal(response.data.count);
        this.nextAccountList = response.data.next;
        this.previousAccountList = response.dataprevious;
      }),
    );
  }

  @loadableCard
  async fetchAccountRecord(id: number): Promise<void> {
    await request({
      method: 'get',
      url: `${environment.endPoints.accounts.users}${id}/`,
    }).then(
      action((response: any) => {
        this.setSelectedAccount(response.data);
      }),
    );
  }

  @loadable
  async postAccountRecord(data: AccountRecordFromPost): Promise<void> {
    await request({
      method: 'post',
      url: `${environment.endPoints.accounts.users}`,
      data,
    }).then(
      //ListRecord
      action((response: any) => {
        const account = new Account(response.data.user.id, response);
        account.setListRecord(response.data);
        this.entities.set(response.data.user.id, account);
        this.selectedAccount = null;
      }),
    );
  }

  @loadable
  async patchAccountRecord(
    data: AccountRecordFromPost,
    id: number,
    page: string,
  ): Promise<void> {
    await request({
      method: 'patch',
      url: `${environment.endPoints.accounts.users}${id}/`,
      data,
    }).then(
      action((response: any) => {
        const newRecord = new Account(response.data.user.id, response.data);
        this.entities.set(newRecord.id as any, newRecord);
        this.selectedAccount = page === 'usersTable' ? null : response.data;
      }),
    );
  }

  @loadable async deleteAccountsRecord(id: number[]): Promise<void> {
    const myPromise = (idd: number): Promise<number> => {
      return new Promise((resolve, reject) => {
        return request({
          method: 'delete',
          url: `${environment.endPoints.accounts.users}${idd}/`,
        })
          .then(() => resolve(idd))
          .catch(() => reject(idd));
      });
    };

    const mas = id.map((item) => {
      return myPromise(item);
    });

    await Promise.allSettled(mas);
  }
}
