import { ServiceApi } from '@openapi/registry-service';
import { find } from 'lodash';
import { ActionContext, ActionTree, GetterTree, MutationTree } from 'vuex';

const serviceApi = new ServiceApi();

interface State {
  card: Record<string, string>;
  cardSett: Record<string, string>;
  loading: boolean;
  unsavedChanges: boolean;
  serviceMetaCollection: Record<string, string>;
  stateColorMap: {
    [key: string]: string;
  };
  stateColorMapSet: {
    [key: string]: string;
  };
  goalcolorMap: {
    [key: number]: string;
  };
  canEdit: boolean;
}

export const state: State = {
  card: {},
  cardSett: {},
  loading: false,
  unsavedChanges: false,
  serviceMetaCollection: {},
  stateColorMap: {
    draft: 'grey',
    readyToPublish: 'purple',
    signed: 'secondary',
    published: 'positive',
    inProgress: 'primary',
  },
  stateColorMapSet: {
    DRAFT: 'grey',
    IN_PROCESS: 'purple',
    READY_FOR_PUBLISH: 'positive',
  },
  goalcolorMap: {
    1: 'primary',
    2: 'secondary',
    3: 'grey',
    4: 'orange',
    5: 'purple',
  },
  canEdit: false,
};

export const getters: GetterTree<State, State> = {
  servicesCard(state) {
    return state.card; // Service || {} ?
  },
  stateColorMap(state) {
    return state.stateColorMap;
  },
  stateColorMapSet(state) {
    return state.stateColorMapSet;
  },
  goalColorMap(state) {
    return state.goalcolorMap;
  },
  servicesLoading(state) {
    return state.loading;
  },
  unsavedChanges(state) {
    return state.unsavedChanges;
  },
  findDirectory: (state) => (
    directoryId: string,
    options?: { keyId?: string; typeResult?: 'all' | 'documents' }
  ) => {
    const { dictionaries } = state.card;

    const keyId = options?.keyId || 'id';
    const typeResult = options?.typeResult || 'all';

    if (!dictionaries || !Array.isArray(dictionaries)) {
      return typeResult === 'documents' ? [] : null;
    }

    const findResult = dictionaries.find(
      (directory: any) => directory[keyId] === directoryId
    );
    return typeResult === 'documents'
      ? findResult?.documents || []
      : findResult;
  },
  canEdit(state) {
    return state.canEdit;
  },
  getExtendNumberFlag(state) {
    return state.card.maxExtendNumberFlag;
  },
};

export const mutations: MutationTree<State> = {
  servicesCard(state, card) {
    state.card = card;
  },
  servicesLoading(state, loading) {
    state.loading = loading;
  },
  unsavedChanges(state, changes) {
    state.unsavedChanges = changes;
  },
  // @ts-ignore
  cacheServiceMeta(state, serviceMeta, paramsKey) {
    state.serviceMetaCollection[paramsKey] = serviceMeta;
  },
  setCanEdit(state, canEdit) {
    state.canEdit = canEdit;
  },
  setMaxExtendNumber(state, num) {
    state.card = { ...state.card, maxExtendNumber: num };
  },
  setExtendNumberFlag(state, flag) {
    state.card = { ...state.card, maxExtendNumberFlag: flag };
  },
};

const serviceMetaPromisePool: Record<string, string> = {};

export const actions: ActionTree<State, State> = {
  setCardForJson({ commit }: ActionContext<State, State>, newCard) {
    if (newCard) {
      commit('servicesCard', newCard);
    }
  },
  getServiceMeta(
    { commit, dispatch, state }: any = {},
    { id, opts = {}, useAuth = true } = {}
  ) {
    /*
    !!!
    noCommit
    noExpand
    * */
    const paramsKey = `${id}.${JSON.stringify(opts)}.${useAuth}}`;

    if (state.serviceMetaCollection[paramsKey])
      return state.serviceMetaCollection[paramsKey];
    if (serviceMetaPromisePool[paramsKey])
      return serviceMetaPromisePool[paramsKey];

    const serviceMetaPromise = new Promise((resolve, reject) => {
      const { noExpand, expand, noCommit, ...misc } = opts;
      const options = { ...misc };
      let resultExpand = '';
      if (!noExpand) {
        const defaultExpand = [
          'tables',
          'processes',
          'documents.form',
          'model',
          'form',
          'interagencies',
          'dictionaries',
          'reglament',
          'paymentLinks',
          'formsExtra',
        ];

        resultExpand = [...defaultExpand, ...(expand || [])].join(',');
      }
      commit('servicesLoading', true);

      serviceApi
        .getService(id, resultExpand, options)
        .then(({ error, data }: any) => {
          if (!error) {
            const expandsFields = {
              state: 'inProgress',
              authority: {},
            };

            const serviceMeta = Object.assign({}, expandsFields, data);

            if (!noCommit) {
              commit('servicesCard', serviceMeta);
              commit('cacheServiceMeta', serviceMeta, paramsKey);
            }

            const dictionaries = data?.dictionaries;

            if (dictionaries) {
              for (const dict of dictionaries) {
                dispatch(
                  'registryService/referenceBooks/convertReferenceBookFromRegistry',
                  { referenceBook: dict },
                  { root: true }
                ).then((referenceBook: string) =>
                  commit(
                    'registryService/referenceBooks/addReferenceBook',
                    { referenceBook, id: dict.name },
                    { root: true }
                  )
                );
              }
            }

            return resolve(serviceMeta);
          }
          return reject(error);
        });
    }).finally(() => {
      delete serviceMetaPromisePool[paramsKey];
      commit('servicesLoading', false);
    });

    // @ts-ignore
    serviceMetaPromisePool[paramsKey] = serviceMetaPromise;

    return serviceMetaPromise;
  },
};
