import { Component, Mixins } from 'vue-property-decorator';
import Centered1280Box from '@/recruits/components/common/centered-1280-box.vue';
import WhiteCard from '@/recruits/components/common/white-card.vue';
import SortBar from '@/recruits/components/common/sort-bar.vue';
import ReTable from '@/recruits/components/common/r-table/index.vue';
import UrlIntegratedSearch from '@/recruits/mixins/url-integrated-search';
import { RTableColumn } from '@/interfaces';
import { UrlQueryParams } from '@/recruits/models';
import { prepareApiParams } from '@/recruits/utils/prepare-api-params';
import { SSOServiceApi, AccountsSessionCountBodyV1 } from '@openapi/sso';
import { notifyError } from '@utils/notify';
import LinkCell from '@/recruits/components/common/cells/link.vue';
import RolesModal from './components/RolesModal.vue';
import CreateModal from './components/CreateModal.vue';
import accountsSearchBar from './components/SearchBar/index.vue';
import { AccountsSearchFilter } from './components/SearchBar/accounts-search-filter';
import {
  AccountApi,
  PagingRequestAccountSearchDTO,
  SortedFieldOrderEnum,
  AccountSearchRecordDTO,
  AccountAdminSearchFilterDTO,
} from '@openapi/idm';
import { AccountSearchRecord } from './utils/types';

const accountApi = new AccountApi();
const ssoServiceApi = new SSOServiceApi();

@Component({
  components: {
    SortBar,
    ReTable,
    accountsSearchBar,
    Centered1280Box,
    WhiteCard,
    LinkCell,
    RolesModal,
    CreateModal,
  },
})
export default class Accounts extends Mixins(UrlIntegratedSearch) {
  private sortByDefault = 'modified';

  get isSecurityAdmin(): boolean {
    return this.$AC.haveScope(this.$AC.scopes.SECURITY_ADMINISTRATOR);
  }

  get handler(): 'adminTable' | 'domainTable' {
    if (this.isSecurityAdmin) {
      return 'adminTable';
    }
    return 'domainTable';
  }

  showModalCreate = false;

  private create() {
    this.showModalCreate = true;
  }

  public data: AccountSearchRecord[] | undefined = [];
  public filter = new AccountsSearchFilter();

  public sortButtons: Array<{ label: string; value: string }> = [
    { label: 'По ФИО', value: 'surname' },
  ];

  private async getAdminAccounts(
    query: UrlQueryParams
  ): Promise<{ data: AccountSearchRecordDTO[]; totalRows: number }> {
    const params = prepareApiParams(query);
    const searchFilter: AccountAdminSearchFilterDTO = {};
    if (this.filter.search) {
      searchFilter.personFioFullTextFilter = this.filter.search;
    }
    if (this.filter.organizationId) {
      searchFilter.domainId = this.filter.organizationId;
    }
    if (this.filter.departmentId) {
      searchFilter.domainId = this.filter.departmentId;
    }
    if (this.filter.roleId) {
      searchFilter.roleId = this.filter.roleId;
    }
    const requestSettings: PagingRequestAccountSearchDTO = {
      searchFilter,
      page: params.pagination.page,
      perPage: params.pagination.rowsPerPage,
      sort: [
        {
          fieldName: params.pagination.sortBy || this.sortByDefault,
          order:
            params.pagination.descending === 'false'
              ? SortedFieldOrderEnum.Asc
              : SortedFieldOrderEnum.Desc,
        },
      ],
    };
    const { data } = await accountApi.searchAccountsWithFilterV1(
      requestSettings
    );
    return { data: data?.data || [], totalRows: data?.totalRows || 0 };
  }

  private async getDomainAccounts(
    query: UrlQueryParams
  ): Promise<{ data: AccountSearchRecordDTO[]; totalRows: number }> {
    const currentUser = this.$store.getters['oidcClient/currentUser'];
    if (!currentUser?.domain_id) {
      notifyError('Не удается получить организацию пользователя');
      return new Promise((resolve) => resolve({ data: [], totalRows: 0 }));
    }

    const params = prepareApiParams(query);

    const searchText = this.filter.search
      ? `surname=like=*${this.filter.search}*`
      : '';

    const { data } = await accountApi.findAccountsByOrganizationIdWithPerson(
      currentUser.domain_id,
      params.pagination.page,
      params.pagination.rowsPerPage,
      `${params.pagination.descending === 'false' ? '+' : '-'}${
        params.pagination.sortBy || this.sortByDefault
      }`,
      searchText
    );

    const convertedData: AccountSearchRecordDTO[] =
      data.records?.map((record) => {
        const obj: AccountSearchRecordDTO = {};
        if (record.id) {
          obj.accountId = record.id;
        }
        if (record.person?.fio) {
          obj.accountFullName = record.person.fio;
        }
        if (record.domainFullName) {
          obj.domainName = record.domainFullName;
        }
        if (record.enabled) {
          obj.enabled = record.enabled;
        }
        if (record.blocked) {
          obj.blocked = record.blocked;
        }
        return obj;
      }) || [];

    return { data: convertedData, totalRows: data?.totalRows || 0 };
  }

  public async fetchData(
    query: UrlQueryParams
  ): Promise<{ totalRows: number | undefined }> {
    try {
      let accountsResponse: {
        data: AccountSearchRecordDTO[];
        totalRows: number;
      } = { data: [], totalRows: 0 };
      if (this.handler === 'adminTable') {
        accountsResponse = await this.getAdminAccounts(query);
      } else {
        accountsResponse = await this.getDomainAccounts(query);
      }

      // получаем список id аккаунтов
      const accountIds: string[] = accountsResponse.data.map(
        (account) => account.accountId || ''
      );

      // объект хранящий соотношения id аккаунта к кол-ву сессий
      const sessions: Record<string, number> = {};

      if (accountIds.length) {
        // получаем список соотношения id аккаунта к кол-ву сессий
        const sessionsResponse: AccountsSessionCountBodyV1 = await new Promise(
          (resolve) => {
            ssoServiceApi
              .getAccountsSessionCountV1({ accountIdList: accountIds })
              .then((sessionsResponse) => {
                resolve(sessionsResponse.data);
              })
              .catch(() => {
                resolve({ accountIdList: [] });
              });
          }
        );

        // преобразуем список соотношения id аккаунта к кол-ву сессий в объект
        sessionsResponse.accountIdList?.forEach((accountWithSession) => {
          if (accountWithSession?.accountId) {
            sessions[accountWithSession.accountId] =
              accountWithSession?.count || 0;
          }
        });
      }

      // добавляем кол-во сессий к общей информации аккаунта
      this.data = accountsResponse.data.map((account) => {
        const sessionsCount = account?.accountId
          ? sessions[account.accountId] || 0
          : 0;
        return { ...account, sessionsCount };
      });

      return { totalRows: accountsResponse.totalRows };
    } catch (e: any) {
      notifyError(e.toString());
      return { totalRows: undefined };
    }
  }

  get columns(): RTableColumn<Array<AccountSearchRecord>>[] {
    const defaultColumns: RTableColumn<Array<AccountSearchRecord>>[] = [
      {
        label: 'ФИО',
        name: 'account',
        field: 'account',
      },
      {
        name: 'enabled',
        label: 'Активность',
        field: 'enabled',
        componentPath: 'icon',
        componentOptions: {
          icon: 'block',
          align: 'center',
          iconColor: 'black',
        },
        format: (val) => (val ? '' : 'icon'),
        width: '110px',
      },
      {
        name: 'blocked',
        label: 'Блокировка',
        field: 'blocked',
        componentPath: 'icon',
        componentOptions: {
          icon: 'lock',
          align: 'center',
          iconColor: 'black',
        },
        format: (val) => (val ? 'icon' : ''),
        width: '110px',
      },
      {
        name: 'sessionsCount',
        label: 'Кол-во сессий',
        field: 'sessionsCount',
        width: '120px',
      },
      {
        name: 'roles',
        label: 'Роли',
        field: 'roles',
        width: '120px',
      },
    ];
    if (this.handler === 'adminTable') {
      defaultColumns.splice(1, 0, {
        name: 'domainName',
        label: 'Организация',
        field: 'domainName',
        width: '2fr',
        format: (val) => this.formatingDomainName(val.toString()),
      });
    }
    return defaultColumns;
  }

  formatingDomainName(domainName: string): string {
    if (domainName.length > 50) {
      return domainName.substring(0, 50) + '...';
    } else {
      return domainName;
    }
  }

  // блок для работы модального окна
  private openedAccount: AccountSearchRecord | null = null;

  showModalRoles(row: AccountSearchRecord): void {
    this.openedAccount = row;
  }

  closeRoles(): void {
    this.openedAccount = null;
  }
}
