<template>
  <operation-dialog
    persistent
    sign
    ref="dialogDepartmentDelete"
    :title="departmentName"
    sub="Архивирование подразделения"
    v-model="opened"
    @hide="close"
    class="DeleteModalForm"
  >
    <q-form @submit="submit">
      <div>
        <div>Текущая структура</div>
        <q-tree :nodes="departments" node-key="id" accordion default-expand-all>
          <template #header-bold="prop">
            <div class="DeleteModalForm__SelectDepartment">
              {{ prop.node.label }}
            </div>
          </template>
        </q-tree>
      </div>
      <div>
        <q-field
          :disable="!departments.length"
          filled
          label="Подразделения, должности и сотрудники будут перенесены в:"
          stack-label
        >
          <template>
            <div tabindex="0" class="DeleteModalForm__SelectLabel">
              {{ label || 'Не выбрано' }}
            </div>
          </template>
          <template #append>
            <q-icon name="arrow_drop_down" />
          </template>
          <q-menu fit auto-close>
            <q-tree
              :nodes="selectDepartments"
              :selected.sync="selectedId"
              node-key="id"
              accordion
              default-expand-all
            />
          </q-menu>
        </q-field>
      </div>
    </q-form>
    <template #process>
      <result-block
        header="Удаление организации"
        icon="pgs-document"
        type="info"
      />
    </template>
    <template #result>
      <result-block :header="resultMessage" :type="resultType" />
    </template>
    <template #left-actions-panel>
      <r-btn
        outline
        :label="isFinishStep ? 'Закрыть' : 'Отмена'"
        positive
        @click="close"
      />
    </template>
    <template #right-actions-panel>
      <r-btn
        v-if="!isFinishStep"
        :disabled="!selectedId"
        outline
        label="Подтверждение"
        negative
        @click="submit"
      />
    </template>
  </operation-dialog>
</template>

<script lang="ts">
import { Component, Prop, Mixins, Watch, Ref } from 'vue-property-decorator';
import get from 'lodash/get';
import ProcessStarter from '@/mixins/ProcessStarter';
import OperationDialog from '@/components/common/operation-dialog/index.vue';
import { DepartmentWithParent } from '@/models/DepartmentWithParent';
import { DomainApi, NodeTO } from '@openapi/idm';

const domainApi = new DomainApi();

interface itemNodeTO {
  disabled?: boolean;
  header?: 'bold';
  id: string;
  label: string;
  children: itemNodeTO[];
}

@Component({})
export default class DeleteDepartmentModal extends Mixins(ProcessStarter) {
  @Prop({ default: null }) department: DepartmentWithParent | null;
  @Prop({ default: 'milBaseDeleteDepartmentProcess' })
  declare processKey: string;

  @Ref('dialogDepartmentDelete') operationDialog: OperationDialog;

  opened = false;
  isFinishStep = false;

  get departmentName(): string {
    return (
      this.department?.fullname ||
      this.department?.shortname ||
      this.department?.name ||
      'Подразделение'
    );
  }

  resultType: 'positive' | 'negative' | '' = '';
  resultMessage = '';

  label = '';
  selectedId = '';
  selectDepartments: itemNodeTO[] = [];
  departments: itemNodeTO[] = [];

  @Watch('department')
  private async departmentHandler(): Promise<void> {
    // departmentHandler приходит null - значит надо закрыть окно
    this.opened = false;
    this.isFinishStep = false;
    this.resultType = '';

    this.operationDialog.reset();
    if (!this.department?.id) return;

    const { data } = await domainApi.getDomainChildrenTreeV1(
      this.department.parent.id,
      1,
      ['Department']
    );
    this.convertedData(data);

    this.opened = true;
  }

  initLabel(): void {
    const node = this.getNodeByKeyRecursive(this.departments);

    this.label = node ? node.label : '';
  }

  getNodeByKeyRecursive(nodes: itemNodeTO[]): itemNodeTO | null {
    let targetNode = null;

    if (this.selectedId && nodes.length) {
      for (const node of nodes) {
        if (node.id === this.selectedId) {
          targetNode = node;
        } else if (node.children.length) {
          targetNode = this.getNodeByKeyRecursive(node.children);
        }

        if (targetNode) break;
      }
    }
    return targetNode;
  }

  convertedData(val: NodeTO): void {
    if (val) {
      let organizationId = '';
      let organizationName = '';

      if (val?.value) {
        // использую get т.к. в NodeTO нет fullname, однако
        // запрос возвращает NodeTO по департаментам/орагнизации,
        // и в них это поле есть
        organizationName = get(val, 'value.fullname', '');
        organizationId = val.value.id;
        this.selectedId = val.value.id;
      }

      const getTreeStructure = (item: NodeTO, needDisabled: boolean) => {
        // использую get т.к. в NodeTO нет value.fullname || value.id, однако
        // запрос возвращает NodeTO по департаментам/орагнизации,
        // и в них это поле есть
        const itemId = get(item, 'value.id', '');
        const itemLabel =
          get(item, 'value.fullname', '') || get(item, 'value.name', '');

        const returnObj: itemNodeTO = {
          id: itemId,
          label: itemLabel,
          disabled: false,
          children: [],
        };

        if (itemId && itemId === this.department?.id) {
          returnObj.header = 'bold';
          if (needDisabled) {
            returnObj.disabled = true;
          }
        }

        if (item.leafs && item.leafs instanceof Array) {
          returnObj.children = item.leafs.map((itemLeaf: NodeTO) => {
            return getTreeStructure(itemLeaf, needDisabled);
          });
        }

        return returnObj;
      };

      if (val?.leafs) {
        this.selectDepartments = [
          {
            id: organizationId,
            label: organizationName,
            children: val.leafs.map((item: NodeTO) => {
              return getTreeStructure(item, true);
            }),
          },
        ];
        this.departments = [
          {
            id: organizationId,
            label: organizationName,
            children: val.leafs.map((item: NodeTO) => {
              return getTreeStructure(item, false);
            }),
          },
        ];
      }
    }
  }

  @Watch('selectedId')
  private selectedIdHandler(): void {
    this.initLabel();
  }

  close(): void {
    if (this.isFinishStep) {
      this.$emit('finish');
    } else {
      this.$emit('close');
    }
  }

  async submit(): Promise<void> {
    if (!this.department?.id || !this.department?.parent?.id) {
      return;
    }
    try {
      const traceId = await this.startProcess({
        orgId: this.department.parent.id,
        departmentId: this.department.id,
        destination: this.selectedId,
      });

      this.isFinishStep = true;

      this.registerListener((message, removeListener) => {
        if (traceId !== message.traceId) return;
        if (message?.body?.type === 'finish') {
          this.resultType = 'positive';
          this.resultMessage = 'Подразделение удалено';
          removeListener();
        }

        if (message?.body?.type === 'error') {
          this.resultType = 'negative';
          // get т.к. message может быть Task | PushMessage, а в Task нет поля msg
          this.resultMessage = get(
            message,
            'body.msg.message',
            'Произошла непредвиденная ошибка'
          );
          removeListener();
        }
        this.operationDialog.toResult();
      });
    } catch (error: any) {
      this.resultType = 'negative';
      this.$q.notify({
        message: error.message,
        color: 'negative',
      });
    } finally {
      this.operationDialog.toResult();
    }
  }
}
</script>

<style lang="scss" scoped>
.DeleteModalForm {
  &__SelectDepartment {
    color: #1491cf;
    font-weight: 700;
  }
  &__SelectLabel {
    color: #000000;
  }
  &__Field {
    &::v-deep {
      .q-field--with-bottom {
        padding-bottom: 0;
      }

      .q-field--auto-height .q-field__control {
        background: #e5edf5;
        border-bottom: 1px solid rgba(1, 72, 116, 0.18);
      }

      .q-field--filled.q-field--highlighted .q-field__control:before {
        opacity: 0;
      }

      .q-field--filled .q-field__control:after {
        height: 0;
      }

      .q-field--focused {
        &.q-field--filled .q-field__control {
          background: white;
          border: 1px solid #0148742e;
        }
      }

      .q-field--filled .q-field__control {
        background: #e5edf5;
        // border-bottom: 1px solid rgba(1, 72, 116, 0.18);
      }
    }
  }
}
</style>
