<i18n>
{
  "en": {
    "PaymentEdit": {
      "title": "Edit document",
      "createTitle": "Create document",
      "regionCode": "region code",
      "KBK": "Kbk",
      "billFor": "bill for",
      "value": "Value",
      "totalAmount": "Total amount",
      "amountMultiplier": "Factor",
      "discountType": "Discount type",
      "discountSizePercent": "Discount size percent",
      "discountSize": "Discount size",
      "discountValue": "Discount value {type}",
      "goal": "goal",
      "applicationStatusForWaitPayment": "Application status for wait payment",
      "applicationStatusForCharge": "Application status for charge",
      "applicationStatusForRegister": "Application status for register",
      "expiryPlusDays": "Expiry plus Days",
      "executionPeriodInDays": "Execution period in days",
      "expiryPlusDaysHint": "If the value is 0, the discount on accrual is unlimited in terms of validity",
      "notifyInHours": "Notify in hours",
      "jsonEditorMode": "Json editor mode",
      "formMode": "Form mode"
    }
  },
  "ru": {
    "PaymentEdit": {
      "title": "Редактирование платежа",
      "createTitle": "Создание платежа",
      "regionCode": "Код региона",
      "Kbk": "КБК платежа",
      "totalAmount": "Cумма платежа в руб.",
      "amountMultiplier": "Множитель",
      "billFor": "Назначение платежа",
      "discountType": "Тип скидки",
      "discountSizePercent": "Условия оплаты со скидкой",
      "discountSize": "Условия оплаты с фиксированной суммой скидки",
      "discountValue": "Скидка {type}",
      "goal": "Цель",
      "applicationStatusForCharge": "Cтатус для формирования начисления",
      "applicationStatusForWaitPayment": "Cтатус для ожидания оплаты начисления",
      "applicationStatusForRegister": "Cтатус для регистрации начисления",
      "expiryPlusDays": "Kоличество дней действия скидки, с даты выставления начисления",
      "expiryPlusDaysHint": "При значении 0 скидка на начисление неограниченна по сроку действия",
      "jsonEditorMode": "Режим редактора json",
      "formMode": "Режим формы"
    }
  }
}
</i18n>

<template>
  <q-dialog v-model="dialogOpen" @hide="clearModel">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-card-section>
        <div class="text-h6">
          {{
            isEditForm ? $t('PaymentEdit.title') : $t('PaymentEdit.createTitle')
          }}
        </div>
      </q-card-section>

      <q-card-section class="q-pb-md q-gutter-y-md">
        <q-btn-toggle
          v-if="isEditForm && state === 'inProgress'"
          v-model="jsoneditorMode"
          toggle-color="primary"
          :options="toggleBtnOptions"
        />
        <v-json-editor
          v-if="jsoneditorMode"
          ref="jsoneditor"
          v-model="dialogData"
          :options="{ mode: 'code' }"
          height="400px"
        />
        <q-form
          v-if="dialogData && !jsoneditorMode"
          ref="form"
          class="q-gutter-y-md"
        >
          <q-input
            v-model="dialogData.regionCode"
            :label="$t('PaymentEdit.regionCode')"
            :readonly="stateRegionReadonly.includes(state)"
            filled
            :rules="[noEmptyValueRule]"
            mask="###"
          />

          <q-input
            v-model="dialogData.billFor"
            :label="$t('PaymentEdit.billFor')"
            :rules="[noEmptyValueRule, maxNumOfChars(210)]"
            filled
          />

          <q-input
            v-model="dialogData.KBK"
            :label="$t('PaymentEdit.Kbk')"
            filled
            mask="### #### ##### ##### ###"
            unmasked-value
            :rules="[noEmptyValueRule]"
            fill-mask="X"
          />

          <q-input
            v-model.number="dialogData.totalAmount"
            type="number"
            :rules="[noEmptyValueRule]"
            :label="$t('PaymentEdit.totalAmount')"
            filled
          />
          <q-input
            v-model.number="dialogData.totalAmountMultiplier"
            type="number"
            disable
            :label="$t('PaymentEdit.amountMultiplier')"
            filled
          />
          <q-select
            v-model="dialogData.discountType"
            filled
            emit-value
            map-options
            :options="discountType"
            :label="$t('PaymentEdit.discountType')"
            @input="resetValidation"
          />

          <q-input
            v-model.number="dialogData.discountValue"
            ref="discountValue"
            type="number"
            min="0"
            max="100"
            :rules="[discountValueRuleHandler]"
            :label="
              $t('PaymentEdit.discountValue', { type: discountValueType })
            "
            filled
          />

          <q-input
            v-model.number="dialogData.expiryPlusDays"
            type="number"
            :label="$t('PaymentEdit.expiryPlusDays')"
            :hint="$t('PaymentEdit.expiryPlusDaysHint')"
            filled
            min="0"
            :rules="[
              (val) =>
                !val ||
                val >= 0 ||
                'Поле не может иметь отрицательное значение',
            ]"
          />

          <q-select
            v-if="dictionaryGoals"
            v-model="dialogData.goal"
            filled
            emit-value
            map-options
            :rules="[noEmptyValueRule]"
            :options="dictionaryGoals"
            :label="$t('PaymentEdit.goal')"
          />

          <q-select
            v-model="dialogData.applicationStatusForCharge"
            filled
            emit-value
            map-options
            :options="applicationStatusType"
            :label="$t('PaymentEdit.applicationStatusForCharge')"
            :rules="[noEmptyValueRule]"
          />

          <q-select
            v-model="dialogData.applicationStatusForRegister"
            filled
            emit-value
            map-options
            :options="applicationStatusType"
            :label="$t('PaymentEdit.applicationStatusForRegister')"
            :rules="[noEmptyValueRule]"
          />

          <q-select
            v-model="dialogData.applicationStatusForWaitPayment"
            filled
            emit-value
            map-options
            :options="applicationStatusType"
            :label="$t('PaymentEdit.applicationStatusForWaitPayment')"
            :rules="[noEmptyValueRule]"
          />
        </q-form>
      </q-card-section>
      <q-card-actions align="right">
        <q-btn
          v-if="isEditForm"
          label="Cохранить"
          unelevated
          color="primary"
          @click="edit"
        />
        <q-btn
          v-else
          label="Создать"
          unelevated
          color="primary"
          @click="create"
        />

        <q-btn
          label="Закрыть"
          color="white"
          text-color="primary"
          outline
          @click="clearModel"
        />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>
<script lang="ts">
// @ts-ignore
import VJsonEditor from 'v-jsoneditor';
import { ModifyResponse, Payment, PaymentApi } from '@openapi/registry-service';
import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { BaseCardCommon } from '@/interfaces';
import { DialogMode } from '@constants/models/Card';
import { ServiceExpanded } from '@models/ServiceExpanded';
import { notifyError } from '@utils/notify';
import { QForm } from 'quasar';
import { noEmptyValueRule, maxNumOfChars } from '@utils/field-validation/basic';

const paymentApi = new PaymentApi();

const DIVISION_OPERATION = 'division';
const OPERATION_MULTIPLICATION = 'multiplication';

@Component({
  components: {
    VJsonEditor,
  },
  methods: {
    noEmptyValueRule,
    maxNumOfChars,
  },
})
export default class PaymentDialog extends Vue {
  @Prop() common: BaseCardCommon;

  dialogData: Payment | null = null;
  schemaName = 'Payment';
  loading = false;
  mode = DialogMode.EDIT;
  defaultAmountMultiplier = 100;
  dialogOpen = false;
  jsoneditorMode = false;
  discountType = [
    {
      label: this.$t('PaymentEdit.discountSize'),
      value: 'discountSize',
    },
    {
      label: this.$t('PaymentEdit.discountSizePercent'),
      value: 'discountSizePercent',
    },
  ];

  // todo Dict
  applicationStatusType = [
    {
      label: 'После регистрации заявления',
      value: '02',
    },
    {
      label: 'После подготовки проекта решения',
      value: '09.4',
    },
    {
      label: 'Принятие решения о приеме документов',
      value: '01.3',
    },    
  ];

  toggleBtnOptions = [
    {
      label: this.$t('PaymentEdit.jsonEditorMode'),
      value: true,
    },
    {
      label: this.$t('PaymentEdit.formMode'),
      value: false,
    },
  ];

  stateRegionReadonly = ['signed', 'readyToPublish', 'published'];

  $refs!: {
    form: QForm;
    discountValue: QForm;
  };

  get isEditForm(): boolean {
    return this.mode === DialogMode.EDIT;
  }

  get card(): ServiceExpanded {
    return this.$store.getters['registryService/services/servicesCard'];
  }

  get dictionaryGoals() {
    // @ts-ignore TODO OPENAPI goalsList
    return this.card?.goalsList;
  }

  get state() {
    return this.card.state;
  }

  @Watch('common.models.paymentDialog.mode', {
    immediate: true,
  })
  handler(mode: DialogMode) {
    if (mode) {
      this.dialogOpen = true;
      this.dialogData = {
        // @ts-ignore todo paymentDialog.data type ?  smthng extends Payment?
        ...this.common.models.paymentDialog.data,
        totalAmountMultiplier: this.defaultAmountMultiplier,
      };
      this.discountValueFormat(DIVISION_OPERATION);
      this.mode = mode;
    }
  }

  destroyed() {
    this.clearModel();
  }

  get discountValueType(): string {
    return this.dialogData?.discountType === 'discountSizePercent'
      ? '%'
      : 'руб.';
  }

  async edit() {
    const isValid = this.$refs.form?.validate();

    if (this.dialogData === null || !isValid) return;

    try {
      this.loading = true;
      const { data: result } = await paymentApi.updatePayment([
        this.dialogData,
      ]);
      this.discountValueFormat(OPERATION_MULTIPLICATION);
      this.dialogData.modified = result.modified;
      const card: ServiceExpanded = cloneDeep(
        this.$store.getters['registryService/services/servicesCard']
      );
      card.paymentLinks = (card.paymentLinks || []).map((i) =>
        i.id === this.dialogData?.id ? Object.assign({}, i, this.dialogData) : i
      );
      this.$store.dispatch('registryService/services/setCardForJson', card);
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.dialogOpen = false;
    }
  }

  async create() {
    const isValid = await this.$refs.form.validate();

    if (this.dialogData === null || !isValid) return;

    try {
      this.loading = true;
      const {
        data: docResult,
      }: { data: ModifyResponse } = await paymentApi.createPayment([
        this.dialogData,
      ]);

      this.dialogData.id = get(docResult, 'objectIds[0]');
      this.dialogData.schema = this.schemaName;
      this.discountValueFormat(OPERATION_MULTIPLICATION);
      const card = cloneDeep(
        this.$store.getters['registryService/services/servicesCard']
      );

      const payments = card.paymentLinks || [];
      payments.push(this.dialogData);
      card.paymentLinks = payments;
      this.$store.dispatch('registryService/services/setCardForJson', card);
    } catch (e) {
      notifyError(e.message.toString());
    } finally {
      this.dialogOpen = false;
    }
  }

  discountValueRuleHandler(val: number) {
    if (this.dialogData?.discountType === 'discountSize') {
      return true;
    }
    return !val || (val <= 100 && val >= 0) || 'Введите значение от 0 до 100';
  }

  discountValueFormat(operator: string) {
    if (
      this.dialogData?.discountType === 'discountSize' &&
      !!this.dialogData?.discountValue
    ) {
      // @ts-ignore TODO OPENAPI discountValue is an object. wtf??
      this.dialogData.discountValue =
        operator === DIVISION_OPERATION
          ? // @ts-ignore
            this.dialogData.discountValue / this.defaultAmountMultiplier
          : operator === OPERATION_MULTIPLICATION
          ? // @ts-ignore
            this.dialogData.discountValue * this.defaultAmountMultiplier
          : this.dialogData.discountValue;
    }
  }

  resetValidation() {
    this.$refs.discountValue.resetValidation();
  }

  clearModel() {
    this.$emit('commonModels', {
      paymentDialog: null,
    });
    this.jsoneditorMode = false;
    this.dialogOpen = false;
  }
}
</script>
