import { Component, Prop } from 'vue-property-decorator';
import { mixins } from 'vue-class-component';
import ReturnToParentView from '@/mixins/ReturnToParentView';
import { BaseCardCommon } from '@/interfaces';
import { Tab } from '@interfaces/base/BaseTabs';
import { DocumentType, PersonalAccountApi } from '@openapi/personal-accounts';
import { notifyError, notifySuccess } from '@/utils/notify';
import { USER_SCOPES } from '@constants/entities/Scope';
import { Schema } from '@devsun/eva-models';
import isEmpty from 'lodash/isEmpty';
import cloneDeep from 'lodash/cloneDeep';
import FormGeneratorWrapper from '@/components/common/node-generator/FormGeneratorWrapper.vue';
import {
  createDictionaryMapFromSchema,
  Dictionary,
  DictionaryMap,
} from '@/utils/dict-map-utils';
import type { ExtendedPerson } from '@interfaces/services/personal-accounts';
import { AxiosResponse } from 'axios';
import set from 'lodash/set';
import { deletePersonalAccounts } from '@/services/personal-accounts';

const personalAccountApi = new PersonalAccountApi();
const PERSONAL_ACCOUNT_BASE = '7cf5a965-4a5e-466b-808c-94a82d1ce61f';

@Component({
  components: {
    FormGeneratorWrapper,
  },
  inheritAttrs: false,
})
export default class PersonalAccountsCard extends mixins(ReturnToParentView) {
  @Prop({}) private common?: BaseCardCommon;
  @Prop({}) private model?: ExtendedPerson;

  private USER_SCOPES = USER_SCOPES;

  loading: false;

  get currentTab(): string {
    return this.common?.active || '';
  }

  get tabList(): Tab[] {
    return this.$AC.scopesSift([
      {
        data: {
          name: this.$t('personalAccounts.personalInformation'),
          path: 'personal',
          visible: true,
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.statementsAndResolutions'),
          path: 'statements',
          visible: this.$AC.haveOneOfScope([
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
          ]),
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.paymentData.tab'),
          path: 'payment-data',
          visible:
            this.$AC.haveScope(USER_SCOPES.COMPENSATION_OBSERVER) &&
            this.$AC.haveOneOfScope([
              USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
              USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
            ]),
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.personDetailedRelations'),
          path: 'person-detailed-relations',
          visible: this.$AC.haveOneOfScope([
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
          ]),
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.personCriteria'),
          path: 'person-criteria',
          visible: this.$AC.haveOneOfScope([
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
          ]),
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.socialSupportMeasure'),
          path: 'social-support-measure',
          visible: this.$AC.haveOneOfScope([
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
          ]),
        },
      },
      {
        data: {
          name: this.$t('personalAccounts.recipientCategory'),
          path: 'recipient-category',
          visible: this.$AC.haveOneOfScope([
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
            USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
          ]),
        },
      },
    ]);
  }

  get pageTitle(): string {
    if (this.isAllowedToEnter) {
      return this.model?.fullName || '';
    }
    return this.$t('personalAccounts.youDoNotAllowedToEnter').toString();
  }

  private goBack(): void {
    this.returnToParentViews('personal-accounts', 'cards/personal-accounts');
  }

  private setTotalModel(model: ExtendedPerson): void {
    this.$store.commit('utils/cards/addModel', {
      model,
      path: this.common?.path,
    });
  }

  schema: Schema.MetaClassSchemaRaw | null = null;

  async initSchema(): Promise<void> {
    try {
      let schema = this.$store.getters['utils/cards/getSchemaByPath'](
        'personalAccountBase'
      );

      if (isEmpty(schema)) {
        schema = await this.$store.dispatch(
          'personalAccounts/forms/loadSchema',
          'PersonalAccountMainDisplay'
        );

        this.$store.commit('utils/cards/addSchema', {
          schema,
          path: 'personalAccountBase',
        });
      }
      this.schema = cloneDeep(schema);
    } catch (error) {
      console.error(error);
      console.warn(
        `[perconal-accounts/personal] Couldn't get schema ${PERSONAL_ACCOUNT_BASE} `
      );
    }
  }

  async init(): Promise<void> {
    const id = this.common?.id;
    if (!id) return;
    await this.initDocumentTypes();
    await this.initSchema();
    if (this.schema) await this.initDictionaries(this.schema);
    try {
      let { data } = ((await personalAccountApi.getPerson(
        id,
        'contactdata,paymentdata,personaddress,personapplication,persondocument,personrelation,personsocialsupportmeasure'
      )) as unknown) as AxiosResponse<ExtendedPerson>;
      data = this.setDocumentTypes(data);
      data = await this.setValuesFromDictionaries(data);
      this.setTotalModel(data);
    } catch (error) {
      if (error instanceof Error) notifyError(error.message);
    }
  }

  confirmDeletetionPersonalAccount(): void {
    this.$q
      .dialog({
        title: this.$t('personalAccounts.deletePersonalAccount') as string,
        message: this.$t(
          'personalAccounts.doYouWantToDeletePersonalAccount'
        ) as string,
        cancel: true,
      })
      .onOk(() => {
        this.deletePersonalAccount();
      });
  }

  async deletePersonalAccount(): Promise<void> {
    const id = this.common?.id;
    if (!id) return;
    try {
      const responce = await deletePersonalAccounts([id]);
      if (responce[0].success) {
        notifySuccess(
          this.$t('personalAccounts.personalAccountDeleted').toString()
        );
        this.$router.back();
      }
    } catch (error) {
      if (error instanceof Error) notifyError(error.message);
    }
  }

  async editPersonalAccount(): Promise<void> {
    this.$router.push({
      name: 'personalAccountsEdit',
      params: { id: this.model?.id || '' },
    });
  }

  dictionaryMap: DictionaryMap = {};

  async initDictionaries(schema: Schema.MetaClassSchemaRaw): Promise<void> {
    this.dictionaryMap = createDictionaryMapFromSchema(schema);
    if (!Object.keys(this.dictionaryMap).length) return;

    const dicts = new Set(Object.values(this.dictionaryMap));
    return this.$store.dispatch(
      'registryService/referenceBooks/initReferenceBooks',
      [...dicts].map((id) => {
        return { id };
      })
    );
  }

  async setValuesFromDictionaries<T extends ExtendedPerson>(
    data: T
  ): Promise<T> {
    const dict: Dictionary = await this.$store.dispatch(
      'registryService/referenceBooks/fetchReferenceBook',
      { id: 'personal-account-service_PersonInfoStatus' }
    );
    const result = { ...data };

    result.contactdata?.forEach((contact) => {
      if (contact.status) {
        set(contact, 'status', dict[contact.status]?.value);
        set(contact, 'displayStatus', dict[contact.status]?.value);
      }
    });
    result.personaddress?.forEach((address) => {
      if (address.status) {
        set(address, 'status', dict[address.status]?.value);
        set(address, 'displayStatus', dict[address.status]?.value);
      }
    });

    return result;
  }

  documentTypes: DocumentType[] = [];

  async initDocumentTypes(): Promise<void> {
    this.documentTypes = await this.$store.dispatch(
      'personalAccounts/documentTypes/initDictionary'
    );
  }

  setDocumentTypes(model: ExtendedPerson): ExtendedPerson {
    return this.$store.getters[
      'personalAccounts/documentTypes/applyDictionaris'
    ](model);
  }

  created(): void {
    this.init();
  }

  get isAdmin(): boolean {
    return this.$AC.haveScope(USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN);
  }

  get isAllowedToEnter(): boolean {
    return this.$AC.haveOneOfScope([
      USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_ADMIN,
      USER_SCOPES.SOCIAL_PERSONAL_ACCOUNT_OPERATOR,
    ]);
  }
}
