<template>
  <a-modal v-model="settingVisible" title="自定义" :width="1400" destroy-on-close>
    <template slot="footer">
      <a-button :loading="vLoading" @click="validate">模拟验证</a-button>
      <a-button @click="settingVisible = false">
        取消
      </a-button>
      <a-button type="primary" @click="settingOK">
        确定
      </a-button>
    </template>
    <div :class="$style.custom">
      <a-form-item label="条件关系" :label-col="{ span: 3 }">
        <div :class="$style.relation">
          <a-radio-group v-model="form.op" :options="relationsOptions"></a-radio-group>
          <div>
            <a-button type="link" @click="openDocs('权限说明', '自定义权限数值填写规范')"
              >填写规范<a-icon type="question-circle"
            /></a-button>
            <a-button type="primary" icon="plus" :class="$style.add" @click="add"></a-button>
          </div>
        </div>
      </a-form-item>
      <a-row v-for="(rule, index) in form.rules" :key="index">
        <a-col :span="4">
          <a-select
            v-model="rule.field"
            show-search
            :filter-option="filterOption"
            @change="(value) => fieldChange(value, rule)"
          >
            <a-select-opt-group>
              <span slot="label">表单字段</span>
              <a-select-option
                v-for="(item, findex) in fieldOptions"
                :key="findex"
                :value="item.value"
              >
                {{ item.label }}
              </a-select-option>
            </a-select-opt-group>
            <a-select-opt-group>
              <span slot="label">系统字段</span>
              <a-select-option
                v-for="(item, findex) in sysFieldOptions"
                :key="findex"
                :value="item.value"
              >
                {{ item.label }}
              </a-select-option>
            </a-select-opt-group>
          </a-select>
        </a-col>
        <a-col :span="2">
          <a-select v-model="rule.op" :options="rule.operateOptions"></a-select>
        </a-col>
        <a-col :span="3">
          <a-select
            v-model="rule.valueType"
            @change="
              () => {
                rule.selectedGroup = []
                rule.value = ''
              }
            "
          >
            <a-select-option value="assign">
              指定值
            </a-select-option>
            <a-select-option value="extend">
              扩展权限项
            </a-select-option>
          </a-select>
        </a-col>

        <a-col :span="14">
          <div v-if="rule.valueType === 'extend'">
            <a-select v-model="rule.value" :options="rule.extendOptions"></a-select>
          </div>
          <div v-else>
            <div
              v-if="
                rule.belongTo === 'sys' || ['selectgroup', 'selectuser'].includes(rule.dataType)
              "
              :class="[
                $style.sysSelect,
                {
                  [$style.personSys]: rule.dataType === 'selectuser',
                },
              ]"
            >
              <a-radio-group v-model="rule.classify">
                <a-radio value="SCOPE">
                  {{ rule.dataType === 'selectuser' ? '动态用户值' : '登录人所属部门' }}
                  <a-tooltip>
                    <template v-slot:title>
                      {{
                        rule.dataType === 'selectuser'
                          ? '指根据表单实际选择的用户值计算数据权限，例如用户字段选择了“A、B”，则A\B有查看此数据权限'
                          : '假设用户A属于慧点科技-西安分公司-西安产品部，则选中此项时，右式值为西安产品部'
                      }}
                    </template>
                    <a-icon type="question-circle-o" />
                  </a-tooltip>
                </a-radio>
                <a-radio v-if="rule.dataType === 'selectgroup'" value="SUPER"
                  >登录人所属部门及上级部门
                  <a-tooltip>
                    <template v-slot:title>
                      假设用户A属于慧点科技-西安分公司-西安产品部，则选中此项时，右式值为西安产品部、慧点分公司和慧点科技的合集
                    </template>
                    <a-icon type="question-circle-o" /> </a-tooltip
                ></a-radio>
                <a-radio :value="rule.dataType === 'selectuser' ? 'USER' : 'ORG'">
                  {{ rule.dataType === 'selectuser' ? '指定用户' : '指定部门' }}
                </a-radio>
              </a-radio-group>
              <div v-if="['USER', 'ORG'].includes(rule.classify)" :class="$style.zd">
                <sd-user-picker
                  v-if="rule.dataType === 'selectuser'"
                  v-model="rule.selectedGroup"
                />
                <div v-else>
                  <sd-group-picker v-model="rule.selectedGroup" :class="$style.selectGroup" />
                  <a-checkbox :key="info.key" v-model="rule.includeLower">含下级</a-checkbox>
                </div>
              </div>
            </div>
            <a-date-picker
              v-else-if="rule.dataType === 'date'"
              :show-time="sdGet(rule, 'attr?.showTime') === 'true'"
              v-bind="{ value: rule.value ? moment(rule.value) : null }"
              @change="(value) => dateChange(value, rule)"
            ></a-date-picker>
            <a-input v-else v-model="rule.value"></a-input>
          </div>
        </a-col>
        <a-col :span="1">
          <a-icon type="close-circle" :class="$style.closeIcon" @click="remove(rule)" />
        </a-col>
      </a-row>
    </div>
    <a-modal v-model="validateVisible" title="模拟验证">
      <a-button slot="footer" type="primary" @click="validateVisible = false">知道了</a-button>
      <div :class="$style.validateTitle">
        <span :class="$style.result">运行结果:</span>
        <!-- <span :class="[$style.tag, $style.success]">验证通过</span> -->
        <a-tag :color="validateMes.success ? 'green' : 'red'" :class="$style.tag">{{
          validateMes.success ? '验证通过' : '运行失败'
        }}</a-tag>
      </div>
      <div :class="[$style.mesarea, { [$style.fail]: !validateMes.success }]">
        <span v-if="validateMes.success">
          {{ validateMes.data }}
        </span>
        <div v-else :class="$style.err">
          <div>
            <span>错误编码: </span>
            <span>{{ validateMes.message }}</span>
          </div>
          <div>
            <span>错误信息: </span>
            <span>{{ validateMes.data }}</span>
          </div>
        </div>
      </div>
    </a-modal>
  </a-modal>
</template>

<script>
import moment from 'moment'
import storeMixin from '@/common/store-mixin'
import { openDocs } from '@/common/docs/docs-tool'
import axios from '@/common/services/axios-instance'
import { message } from 'ant-design-vue'
import components from './_import-components/sd-perm-custom-setting-import'

export default {
  name: 'SdPermCustomSetting',
  metaInfo: {
    title: 'SdPermCustomSetting',
  },
  components,
  mixins: [storeMixin],
  data() {
    return {
      validateVisible: false,
      vLoading: false,
      settingVisible: false,
      relationsOptions: [
        { label: '并且', value: 'and' },
        { label: '或者', value: 'or' },
      ],
      defaultOperates: [],
      customForm: {},
      grantTypeOptions: [],
      fieldOptions: [],
      sysFieldOptions: [],
      info: {},
      rangeOptions: [],
      form: {},
      validateMes: {},
    }
  },
  methods: {
    moment,
    filterOption(input, option) {
      return option.componentOptions.children[0]?.text?.indexOf(input) >= 0
    },
    dateChange(value, rule) {
      rule.value = value.valueOf()
    },
    open(form, info) {
      this.sysFieldOptions = []
      this.fieldOptions = []
      this.customForm = form
      this.info = info
      this.form = {
        rules: [
          {
            field: '',
            dataType: '',
            op: '',
            selectedGroup: [],
            value: '',
            classify: 'FREE',
            includeLower: false,
            id: Date.now(),
            belongTo: '',
            valueType: 'assign',
          },
        ],
        op: 'and',
        code: 'CUSTOM',
      }
      if (info.customValue) {
        const customValue = JSON.parse(info.customValue)
        if (customValue.rules.length) {
          this.form = {
            rules: customValue.rules.map((info, index) => {
              info.selectedGroup = ['ORG', 'USER'].includes(info.classify)
                ? info.value?.split(',').map((value) => {
                    const valueArr = value.split('|')
                    info.includeLower = valueArr[3] === '1'
                    return {
                      type: 'Group',
                      code: valueArr[0],
                      name: valueArr[1],
                    }
                  })
                : []
              info.belongTo = [
                'creatorAccount',
                'createDeptId',
                'CREATOR_ACCOUNT',
                'CREATE_DEPT_ID',
              ].includes(info.field)
                ? 'sys'
                : 'default'
              info.id = Date.now() + index
              info.valueType = info.value.indexOf('#EXT_') > -1 ? 'extend' : 'assign'
              return info
            }),
            ...customValue,
          }
        }
      }
      this.rangeOptions = info.dataRules
        .map((rule) => {
          return {
            label: rule.ruleName,
            value: rule.ruleCode,
          }
        })
        .filter((f) => f.value !== 'CUSTOM')
      Promise.all([
        axios.get(
          `api/framework/v1/we-app-form-list/showForPerm?appModuleId=${this.customForm.moduleId}`
        ),
        axios.get(`api/framework/v1/sec-perm-manage/getPermExtendList/${this.info.formId}`),
      ])
        .then((res) => {
          const extendRes = res[1]?.data?.data
          res[0].data.onlListColumnDefs?.forEach((item) => {
            if (
              ['CREATOR_ACCOUNT', 'CREATE_DEPT_ID', 'creatorAccount', 'createDeptId'].includes(
                item.fieldId
              )
            ) {
              item.belongTo = 'sys'
              this.sysFieldOptions.push({
                label: `{${item.fieldName}}`,
                value: item.columnName,
                dataType: this.getDataType(item),
                type: item.fieldType,
                belongTo: 'sys',
                extendOptions: this.getExtendOptions(extendRes, item),
              })
            } else {
              this.fieldOptions.push({
                label: item.fieldName,
                value: item.columnName,
                dataType: this.getDataType(item),
                attr: item.fieldAttr || {},
                belongTo: 'default',
                extendOptions: this.getExtendOptions(extendRes, item),
              })
            }
          })
          return extendRes
        })
        .then((res) => {
          this.form.rules.forEach((rule) => {
            this.formatRule(rule.field, rule)
          })
        })
        .finally(() => {
          this.settingVisible = true
        })

      // 获取自定义权限所用操作
      axios.get('api/framework/v1/sec-perm-manage/getOperateData').then((res) => {
        this.defaultOperates = res.data.data?.map((item) => {
          return {
            label: item.name,
            value: item.code,
          }
        })
      })
      // 获取自定义权限所用授权类型
      axios.get('api/framework/v1/sec-perm-manage/getGrantType').then((res) => {
        this.grantTypeOptions = res.data.data?.map((item) => {
          return {
            label: item.name,
            value: item.code,
          }
        })
      })
    },
    getExtendOptions(extendRes, item) {
      if (!extendRes.length) return []
      return extendRes
        .find((e) => e.dataType === item.fieldType)
        ?.extendInfos?.map((info) => ({ label: info.name, value: info.code }))
    },
    getDataType(item) {
      if (item.fieldType === 'selectperson') {
        return item.fieldAttr?.selectionType === 'GROUP' ? 'selectgroup' : 'selectuser'
      }
      if (item.belongTo === 'sys') {
        return item.fieldType === 'string' ? 'selectuser' : 'selectgroup'
      }
      return item.fieldType
    },
    fieldChange(value, rule) {
      rule.selectedGroup = []
      rule.value = ''
      rule.classify = 'FREE'
      rule.op = ''
      rule.valueType = 'assign'
      this.formatRule(value, rule)
    },
    formatRule(value, rule) {
      const node = [...this.sysFieldOptions, ...this.fieldOptions].find((f) => f.value === value)
      if (node) {
        Object.assign(rule, {
          belongTo: node.belongTo,
          dataType: node.dataType,
          type: node.type,
          attr: node.attr,
          extendOptions: node.extendOptions,
        })
        if (
          node.belongTo === 'sys' ||
          ['long', 'selectgroup', 'selectuser', 'selectlist'].includes(node.dataType)
        ) {
          rule.operateOptions = this.defaultOperates.filter((d) =>
            ['属于', '不属于'].includes(d.label)
          )
        } else if (['title', 'string'].includes(node.dataType)) {
          rule.operateOptions = this.defaultOperates.filter(
            (d) => !['大于', '小于'].includes(d.label)
          )
        } else if (node.dataType === 'number') {
          rule.operateOptions = this.defaultOperates.filter((d) => !['包含'].includes(d.label))
        } else if (node.dataType === 'date') {
          rule.operateOptions = this.defaultOperates.filter(
            (d) => !['包含', '属于', '不属于'].includes(d.label)
          )
        } else {
          rule.operateOptions = this.defaultOperates.filter(
            (d) => !['包含', '大于', '小于'].includes(d.label)
          )
        }
      }
    },
    add() {
      this.form.rules.unshift({
        field: '',
        dataType: '',
        op: '',
        value: '',
        classify: 'FREE',
        includeLower: false,
        id: Date.now(),
        selectedGroup: [],
        belongTo: '',
        valueType: 'assign',
      })
    },
    remove(rule) {
      this.form.rules = this.form.rules.filter((item) => item.id !== rule.id)
    },
    getRuleValue() {
      const ruleValue = {
        ...this.form,
        rules: this.form.rules.map((rule) => {
          const newValue = rule.selectedGroup
            .map((group) => {
              return `${group.code}|${group.name}|${rule.includeLower ? 1 : 0}`
            })
            .join()
          const scopeValue = rule.dataType === 'selectuser' ? 'MYSELF' : 'MYDEPT'
          const value =
            ['ORG', 'USER'].includes(rule.classify) && rule.selectedGroup.length
              ? newValue
              : ['SUB', 'SUPER', 'SCOPE'].includes(rule.classify)
              ? scopeValue
              : rule.value
          return {
            field: rule.field,
            dataType: [
              'creatorAccount',
              'createDeptId',
              'CREATOR_ACCOUNT',
              'CREATE_DEPT_ID',
            ].includes(rule.field)
              ? this.sysFieldOptions.find((option) => option.value === rule.field)?.type
              : this.fieldOptions.find((option) => option.value === rule.field)?.dataType,
            op: rule.op,
            value,
            classify: rule.classify,
          }
        }),
      }
      return ruleValue
    },
    settingOK() {
      const ruleValue = this.getRuleValue()
      this.info.dataRules.forEach((item) => {
        if (item.ruleCode === 'CUSTOM') {
          item.ruleValue = JSON.stringify(ruleValue)
        }
      })
      this.info.customValue = JSON.stringify(ruleValue)
      this.$emit('customOK')
      this.settingVisible = false
    },
    validate() {
      if (this.form.rules.length) {
        this.vLoading = true
        const ruleValue = this.getRuleValue()
        const params = {
          account: this.userInfo.account,
          origin: this.info.origin,
          formId: this.info.formId,
          businessTypeId: this.info.businessId,
          ruleCode: 'CUSTOM',
          ruleValue: JSON.stringify(ruleValue),
        }
        // 模拟验证
        axios.post('api/framework/v1/sec-perm-manage/preExecution', params).then((res) => {
          this.validateMes = res.data
          this.validateVisible = true
          this.vLoading = false
        })
      } else message.warn('请先设置自定义内容')
    },
    openDocs,
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
$icon-size: 20px;
$tag-size: 14px;
.custom {
  .add {
    margin: 0 0 5px 5px;
  }
  :global(.ant-row) {
    padding: 5px 0;
    margin: 0;

    :global(.ant-col) {
      padding: 0 5px;
      :global(.ant-select) {
        width: 100%;
        padding: 0;
      }
      .group-range {
        width: 80px;
        margin-left: 5px;
      }
    }
    .close-icon {
      font-size: $icon-size;
    }
  }
  .custom-select {
    .select-group {
      width: 67%;
      margin-right: 10px;
    }
  }
}
.relation {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.validate-title {
  .result {
    font-size: $icon-size;
  }
  .tag {
    width: 90px;
    margin-left: 20px;
    font-size: $tag-size;
    text-align: center;
    border-radius: 45px;
  }
}
.mesarea {
  width: 100%;
  min-height: 150px;
  padding: 10px;
  margin-top: 20px;
  border: 2px solid $success-color;
  &.fail {
    background: $red-1;
    border: 2px solid $red-4;
  }
  .err {
    color: $red-4;
  }
}
.sys-select {
  display: flex;
  :global(.ant-radio-group) {
    width: 70%;
  }
  .zd {
    width: 30%;
    .select-group {
      width: 61%;
      margin-right: 10px;
    }
  }
  &.person-sys {
    :global(.ant-radio-group) {
      width: 35%;
    }
    .zd {
      width: 65%;
    }
  }
}
</style>
