<template>
  <a-layout :class="$style.webform">
    <sd-header>
      <div slot="left" :class="$style.title">{{ formData.pageTitle }}</div>
      <sd-webflow-buttons
        v-for="button in btns"
        :key="button.buttonId"
        :button="button"
        :icons="buttonIconsInternal"
        type="link"
        :loading="busyButtons[button.buttonId]"
        :title="button.buttonName"
        @click="btnClick"
      />
    </sd-header>
    <a-layout-content :class="$style.layoutContent">
      <a-card size="small">
        <sd-form
          ref="form"
          :key="key"
          v-sd-watermark="waterMark"
          :init-values="formData.pageFormData.pageFieldInfos"
          :read-only="readOnly"
          :class="['sd-full-page-form']"
          :form-relations="sdGet(formData, 'pageFormData.attr?.formRelations')"
        >
          <template v-slot="scope">
            <!--
          @slot 详情表单内容
          @binding {scope} model 整个表单的数据，可用于 v-model 绑定
          @binding {scope} fields 后台返回的字段定义
          @binding {scope} formData 整个表单上下文信息
        -->
            <slot v-bind="{ ...scope, formData }" />
          </template>
        </sd-form>
      </a-card>
      <sd-card-collapse
        v-if="showRevisionHistory"
        v-model="modifyLogVisiable"
        title="修改记录"
        :class="$style.cardcollapse"
      >
        <sd-modify-log />
      </sd-card-collapse>
    </a-layout-content>
    <component :is="actionComponent" ref="actionComponent">
      <template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope">
        <slot :name="slot" v-bind="scope" />
      </template>
    </component>
  </a-layout>
</template>

<script>
import cloneDeep from 'lodash.clonedeep'
import sdFormPublicMethodsNew from '@/common/components/sd-form/sd-form-public-methods-new'
import sdWebflowButtons from '@/webflow/sd-webflow-button.vue'
import sdCardCollapse from '@/webflow/sd-card-collapse.vue'
import sdModifyLog from '@/webflow/sd-modify-log.vue'
import systemManage from '@/system-manage/system-manage'
import buttonHandlers from './button-handlers/index'
import components from './_import-components/sd-webform-import'
import formService from './form-service'

/**
 * 详情表单
 * @displayName SdWebform 详情表单
 */
export default {
  name: 'SdWebform',
  components: {
    ...components,
    sdWebflowButtons,
    sdCardCollapse,
    sdModifyLog,
  },
  mixins: [sdFormPublicMethodsNew],
  props: {
    /**
     * 整个表单是否只读
     */
    readOnly: {
      type: Boolean,
      default: false,
    },
    /**
     * 指定按钮的图标，用于顶部区域按钮的显示
     */
    buttonIcons: {
      type: Object,
      default: () => ({}),
    },
    /**
     * 水印
     * @since 8.1.0.28
     */
    waterMark: {
      type: String,
      default: systemManage.getFormWaterMark(),
    },
  },
  data() {
    return {
      busyButtons: {},
      actionComponent: undefined,
      formData: undefined,
      key: 1,
      modifyLogVisiable: false,
      log: {},
    }
  },
  inject: ['formDataPanel', 'updateFormPanel'],
  provide() {
    return {
      webform: this,
    }
  },
  computed: {
    FormData() {
      return Object.assign(this.formData, this.log)
    },
    recordId() {
      return (this.formData?.pageFormData?.pageFieldInfos || []).find((_) => _.name === 'id')?.value
    },
    btns() {
      return this.formData.operationButtons.length > 0 && !this.readOnly
        ? this.formData.operationButtons
        : [{ buttonId: 'close', buttonName: '退出' }]
    },
    buttonIconsInternal() {
      // 默认图标配置 + 用户自定义配置
      return {
        save: 'save',
        close: 'close-circle',
        ...this.buttonIcons,
      }
    },
    showRevisionHistory() {
      return !!this.formData?.attrs?.revisionHistory
    },
  },
  created() {
    this.formData = cloneDeep(this.formDataPanel)
  },
  methods: {
    getLog(type, forceUpdate = false) {
      // 获取记录
      if (this.FormData[type + 'LogInfo'] && !forceUpdate) {
        // 已经请求过数据了，就用已经有的值
        return Promise.resolve()
      }
      if (this.recordId) {
        if (type === 'operation') {
          return formService
            .getOperationLog({
              beanId: this.FormData.pageFormData?.beanId,
              formId: this.FormData.pageFormData?.formId,
            })
            .then((log) => {
              this.$set(this.log, type + 'LogInfo', log)
            })
        }
      }
      return Promise.resolve()
    },
    btnClick(btn) {
      this.busyButtons = { ...this.busyButtons, [btn.buttonId]: true }
      // 内部按钮状态，等待外部的actionBtnClick事件返回的结果
      this.sdEmit('actionBtnClick', btn, {
        form: this.$refs.form,
        recordId: this.recordId,
      })
        .then((evt) => {
          if (evt.defaultPrevented) {
            // actionBtnClick阻止了默认的行为，返回
            return
          }
          return this.doAction(btn)
        })
        // 最终通知内部按钮，所有处理已完成
        .finally(() => {
          this.busyButtons = { ...this.busyButtons, [btn.buttonId]: false }
        })
      return

      // 为了生成文档
      /**
       * 操作按钮点击时触发
       *
       * @property {event} evt 事件对象，可以用来取消默认操作等
       * @property {object} btn 点击的按钮
       * @property {object} context 上下文信息，其中包括：
       * form：表单对象(可使用SdForm组件中的api进行字段操作)
       * recordId：当前记录ID
       */
      // eslint-disable-next-line no-unreachable
      this.$emit('actionBtnClick', {}, btn, {
        form: this.$refs.form,
        recordId: this.recordId,
      })
    },
    doAction(button) {
      const id = button.buttonId.toLowerCase().replace(/\$|-|_/g, '')
      const serviceJs = buttonHandlers.js[id]
      const serviceVue = buttonHandlers.vue['sd' + id]
      if (serviceVue) {
        // vue组件
        this.actionComponent = serviceVue
        return serviceVue()
          .then(() => {
            return this.$nextTick()
          })
          .then(() => {
            return this.$refs.actionComponent.run({ button })
          })
      } else if (serviceJs) {
        return serviceJs().then((f) => {
          return f.default.bind(this)({ button })
        })
      } else {
        return Promise.resolve()
      }
    },
    updateForm() {
      return this.updateFormPanel().then(() => {
        this.formData = cloneDeep(this.formDataPanel)
        this.key++

        // 显示了修改记录，则更新
        if (this.log.operationLogInfo) {
          this.getLog('operation', true)
        }
      })
    },
    close() {
      window.opener = window
      const win = window.open('', '_self')
      win.close()
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.webform {
  z-index: 1;
  height: 100vh;
  .title {
    font-size: $font-size-lg;
  }
  .layout-content {
    flex: 1;
    height: 100%;
    overflow: auto;
    background: $white;
  }
  .cardcollapse {
    padding: 0 $padding-md $padding-md;
  }
}
</style>
