<template>
  <el-container>
    <el-header>
      <el-button :disabled="!emrConfig.editor" type="success" icon="CircleCheck" @click="clickSaveData">保存</el-button>
      <el-button :disabled="!emrConfig.editor" icon="Delete" type="danger" @click="clickDelete">删除</el-button>
      <el-button style="margin-left: 5px" @click="clickToSubmitTheMedicalRecord"
                 :disabled="!documentId || !emrConfig.editor">提交病历
      </el-button>
      <el-button-group>
        <el-button type="primary" icon="Printer" @click="frontEndPrinting">页面打印</el-button>
        <el-button type="primary" icon="Printer" @click="servicePrint">服务打印</el-button>
      </el-button-group>
      <el-button style="margin-left: 5px" type="primary" @click="openAssistant.dialog = true">
        病历助手
      </el-button>
      <el-button-group>
        <el-button icon="RefreshLeft" @click="clickUndo('undo')">撤销</el-button>
        <el-button icon="RefreshRight" @click="clickUndo('redo')">重做</el-button>
      </el-button-group>

      <el-button @click="drgIntelligentGrouping" type="primary">DRG智能分组</el-button>

      <emr-assistant :data="openAssistant" :to-fill-in-data="clickToFillInData"/>
      <el-switch v-model="reviewMode"
                 active-color="#ff4949"
                 active-text="关闭审阅"
                 :active-value="0"
                 inactive-color="#13ce66"
                 @change="isRevisionMode"
                 inactive-text="开启审阅"
                 :inactive-value="1"/>

    </el-header>
    <el-container>
      <el-aside style="background-color: white">
        <emr-sidebar @nodeClick="nodeClick" ref="emrSidebarRef"
                     :max-height="maxHeight"
                     :huan-zhe-xin-xi="props.huanZheXinXi"/>
      </el-aside>
      <el-main v-loading="loaded">
        <el-row>
          <el-col :span="20">
            <div class="emr-iframe">
              <iframe
                  ref="emrRef"
                  :height="maxHeight - 80 + 'px' "
                  :src="caseHistoryUrl"/>
            </div>
          </el-col>
          <el-col :span="4" style="background-color: white">
            <emr-snippet @node-click="clickSnippet"
                         ref="emrSnippetRef"
                         :max-height="maxHeight"
                         :patientData="patientData"/>
          </el-col>
        </el-row>
      </el-main>
    </el-container>

    <xc-dialog-v2 v-model="drgData.dialog" title="DRG预分组" :maximize="true">
      <iframe :src="drgData.url" :height="800" v-if="drgData.dialog"/>
    </xc-dialog-v2>

  </el-container>
</template>

<script setup name="emr">
import {getEmrInpatientData} from "@/api/dictionary/emr-data-maintenance-api";
import EmrSidebar from "@/components/zhu-yuan-yi-sheng/emr/EmrSidebar.vue";
import {EMRInteractive, emrConfig} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-init";
import {ElMessage, ElMessageBox} from "element-plus";
import {BizException, ExceptionEnum} from "@/utils/BizException";
import EmrSnippet from "@/components/zhu-yuan-yi-sheng/emr/EmrSnippet.vue";
import store from "@/store";
import {onBeforeRouteLeave} from "vue-router";
import {getUuid} from "@/api/public-api";
import {
  deletePatientEmrByDocumentId,
  getDrgIntelligentGrouping, getExtractDataElement, insertEmrData,
  submitMedicalRecord
} from "@/api/zhu-yuan-yi-sheng/emr-patient";
import {useDocumentVisibility} from "@vueuse/core";
import EmrAssistant from "@/components/zhu-yuan-yi-sheng/emr/EmrAssistant.vue";
import XcDialogV2 from "@/components/xiao-chan/dialog/XcDialogV2.vue";
import {getWardsApi} from "@/api/login";
import {xcMessage} from "@/utils/xiaochan-element-plus";

const props = defineProps({
  huanZheXinXi: {
    type: Object,
  },
  maxHeight: {
    type: Number
  },
  visitor: {
    type: Boolean
  }
})

const currentEmr = ref(null)
const emrRef = ref(null)


let categoryCode = $ref('')
// 文档 id 唯一值
let documentId = $ref('')
let patientId = $ref('')
let categoryId = $ref('')
let templateName = $ref('')
let caseHistoryUrl = $ref('')
let openAssistant = $ref({
  data: {},
  dialog: false
})
// 患者数据
let patientData = {}
// 编辑器
let editor = null
// 侧边栏
const emrSidebarRef = ref(null)
// 片段预览
const emrSnippetRef = ref(null)
// 是否加载完成了
let loaded = $ref(false)
// 是否 改变了数据
let isEditorChange = $ref(false)

// 是否开启审阅模式
let reviewMode = $ref(0)
// 跳转定位
let jumpPositioning = {
  value: '',
  // 这里是业务编码
  code: null
}
let wardList = []
// 创建人 id
let createId = null;
// 获取提取到的数据。
let extractData = {}

// 点击保存病历
const clickSaveData = async () => {
  // 只读模式无法保存数据
  if (readonlyPattern()) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "无法保存病历。");
  }
  waitForLoadingToComplete()
  let data = {
    // 这个是 唯一 id 调用服务的雪花算法
    emrDocumentId: documentId ? documentId : await getUuid(),
    emrCategoryCode: categoryCode,
    patNo: props.huanZheXinXi.inpatientNo,
    times: props.huanZheXinXi.admissTimes,
    emrName: templateName,
    categoryId: categoryId
  }
  objectValuesCannotBeNull(data)
  data.emrDataElement = editor.getDataElements('business')
  ElMessageBox.prompt('请输入保存的名称', '提示', {
    inputErrorMessage: '长度为2 - 20 个,汉字',
    inputPattern: /^\S{2,20}$/,
    inputValue: templateName
  }).then(async ({value}) => {
    data.name = value
    // 检验是否必填项目
    let validator = editor.getValidator();
    let valid = validator.valid();
    if (valid) {
      BizException(ExceptionEnum.MESSAGE_ERROR, "有必填项不能为空,请仔细检查,红色输入框.")
    }
    let res = await insertEmrData(data)
    currentEmr.value.saveDocument(data).then(emrRes => {
      // 把提取到的数据放到 patientData 中.
      extractData = res
      Object.assign(patientData, res)
      isEditorChange = false
      emrSidebarRef.value.queryData()
      // 如果是第一次创建就需要跳转
      if (createId == null) {
        let temp = {
          documentId: data.emrDocumentId,
          categoryCode: data.emrCategoryCode,
          name: data.name,
          categoryId: data.categoryId
        };
        createId = userData.code
        updateCaseHistoryUrl(temp)
      }
      xcMessage.success('保存成功')
    }).catch(() => {
      xcMessage.error('保存失败请重新保存')
    })

  }).catch(() => {

  })
}

// 添加片段
const clickToFillInData = (value) => {
  if (!readonlyPattern()) {
    editor.setValues(value)
  }
}

const waitForLoadingToComplete = () => {
  if (loaded) {
    BizException(ExceptionEnum.MESSAGE_ERROR, "请等待加载成功。")
  }
}

const objectValuesCannotBeNull = (object) => {
  if (!object.emrCategoryCode) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "请先选择模板")
  }
  if (!object.patNo) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "请先选择患者")
  }
  if (object.times == null || object.times === 0) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "住院次数为空")
  }
}

// 前端打印
const frontEndPrinting = () => {
  waitForLoadingToComplete()
  editor.execute("print", {
    value: {
      showPreview: true,
    }
  })
}

// 服务打印
const servicePrint = () => {
  waitForLoadingToComplete()
  editor.execute("print", {
    value: {
      showPreview: true,
      mode: 'backend'
    }
  })
}

/**
 * 点击删除数据
 */
const clickDelete = () => {
  if (readonlyPattern()) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "无法删除病历。");
  }
  waitForLoadingToComplete()
  whetherThereIsAMedicalRecordId()
  if (createId !== userData.code) {
    BizException(ExceptionEnum.LOGICAL_ERROR, "创建人不是您，无法删除。");
  }
  ElMessageBox.alert('是否要删除该模板。', '提示', {
    type: 'warning'
  }).then(async () => {
    // 本院删除
    let res = await deletePatientEmrByDocumentId(documentId)
    // 电子病历删除
    await currentEmr.value.deleteDocument(documentId)
    if (res.length > 0) {
      for (let i = 0; i < res.length; i++) {
        let item = res[i]
        // 删除提取到的数据源
        delete patientData[item]
        // 删除提取到的数据
        delete extractData[item]
      }
    }
    isEditorChange = false
    emrSidebarRef.value.queryData()
    emptyEditor()

  });
}

const whetherThereIsAMedicalRecordId = () => {
  if (!documentId) {
    BizException(ExceptionEnum.MESSAGE_ERROR, "请先选择患者的病历。")
  }
}

const checkEmrChange = (cb) => {
  if (isEditorChange) {
    ElMessageBox.confirm("您改变了数据是否要保存，不保存可能会丢失数据。", '提示', {
      type: "warning",
      cancelButtonText: '放弃修改',
      confirmButtonText: '保存病历',
      distinguishCancelAndClose: true,
    }).then(() => {
      clickSaveData()
    }).catch((action) => {
      if (action === 'cancel') {
        isEditorChange = false
        cb()
      }
    })
  } else {
    isEditorChange = false
    cb()
  }
}

const nodeClick = (val, jumpOrNot, templateType) => {
  createId = val.createId
  if (jumpOrNot) {
    if (val.documentId === documentId) {
      positioningTime(val.value, val.code)
    } else {
      updateCaseHistoryUrl(val);
      jumpPositioning = {
        value: val.value,
        code: val.code,
      }
    }
  } else {
    checkEmrChange(() => {
      updateCaseHistoryUrl(val);
    })
  }
}

const updateCaseHistoryUrl = async (val) => {
  loaded = true
  isEditorChange = false
  documentId = val.documentId;
  categoryCode = val.categoryCode
  templateName = val.name
  categoryId = val.categoryId
  caseHistoryUrl = `/emr/runtime/?documentId=${documentId}&categoryCode=${categoryCode}&categoryId=${categoryId}&patientId=${patientId}#/`
}

// 空的编辑器
const emptyEditor = () => {
  isEditorChange = false
  documentId = ''
  categoryCode = ''
  templateName = ''
  categoryId = ''
  caseHistoryUrl = `/emr/runtime/#/editor`
}

/**
 * 跳转到指定的地方
 * @param val 值
 * @param code 业务编码/内部编码/组件编码
 */
const positioningTime = (val, code) => {
  let componentView = currentEmr.value.callMethod('getElementByValue', code, val);
  if (componentView) {
    componentView.focusEnter();
    currentEmr.value.callMethod('scrollToCursor')
    currentEmr.value.callMethod('highlight', componentView, 1500)
    currentEmr.value.callMethod('scrollToCursor', true)
  }
}


const monitorPageRefresh = (event) => {
  if (isEditorChange) {
    event.preventDefault();
    return event.returnValue = "是否确实要退出？还有未保存的数据。";
  }
}

/**
 * 点击插入片段
 * @param content
 * @param styles
 */
const clickSnippet = ({content, styles}) => {
  if (!readonlyPattern()) {
    currentEmr.value.callMethod('setCursor', 'AREA_END')
    currentEmr.value.insertSnippet(content, styles, patientData)
  }
}

// 用户信息
let userData = store.state.user.info
/**
 * 获取当前用户的信息
 * @param data
 */
const getCurrentPersonnelInformation = (data) => {
  patientData['编辑者'] = [{code: userData.code, name: userData.name}]
  patientData['编辑者编码'] = userData.code
  patientData['编辑者姓名'] = userData.name

  patientData['编辑者科室'] = [{code: userData.deptCode, name: userData.deptName}]
  patientData['编辑者科室编码'] = userData.deptCode
  patientData['编辑者科室名称'] = userData.deptName

  patientData.user_token = userData.token
}

const emrEvent = {
  'loaded': async (event) => {
    editor = currentEmr.value.getEditor()
    loaded = false
    setEditorModeFun()
    courseSegmentLocking()
    setTheProgressAnchor()
    deleteDataElement()
    reQueryPatientInformation()
    isRevisionMode()
  },

  'contentchange': (event) => {
    if (!readonlyPattern()) {
      // 如果是空的编辑器就不触发了
      if (!emrRef.value.src.includes('/emr/runtime/#/editor')) {
        // 判断内容是否改变
        isEditorChange = true
        emrSidebarRef.value.changeTemplateType(2)
      }
    }
  },

}

// 设置编辑器的模式
const setEditorModeFun = () => {
  // 判断是不是编辑模式
  if (emrConfig.value.editor) {
    // 设置成编辑模式
    currentEmr.value.callMethod('setEditorMode', 'free')
    // 如果不是首次病程记录就需要执行下面的代码
    if (!categoryCode.includes('shoucibingchengjilu')) {
      if (createId === null) {
        return
      }
      // 创建人不是自己就只能看
      if (doctorLevel === 1 && createId !== userData.code) {
        currentEmr.value.callMethod('setEditorMode', 'readonly');
      }
      if (doctorLevel === 2) {
        // 不能修改三级医生写的病历
        if (createId === extractFields('主任医生编码')) {
          currentEmr.value.callMethod('setEditorMode', 'readonly');
        } else {
          currentEmr.value.callMethod('setEditorMode', 'free');
        }
      }
      // 医生等级 3 没有限制
      if (doctorLevel === 3) {
        currentEmr.value.callMethod('setEditorMode', 'free');
      }
    }

    // 如果创建人不是自己就要开启审阅
    if (createId === userData.code) {
      editor.setRevisionMode('off')
    } else if (createId != null) {
      xcMessage.warning('当前病历创建人不是您，你的操作将会留痕。')
      editor.setRevisionMode('on')
    }

  } else {
    currentEmr.value.callMethod('setEditorMode', 'readonly')
  }
}

/**
 * 设置跳转锚点
 */
const setTheProgressAnchor = () => {
  if (jumpPositioning.code) {
    positioningTime(jumpPositioning.value, jumpPositioning.code)
    jumpPositioning.code = null
  }
}

/**
 * 病程记录专用，
 * 设置段落锁定，和设置跳转锚点
 */
const courseSegmentLocking = () => {
  if (!categoryCode.includes('shoucibingchengjilu')) {
    return
  }
  let root = currentEmr.value.getRoot()
  if (documentId) {
    let courseTitles = []
    let loginUserCode = userData.code
    let modelService = editor.ModelService
    let walker, values
    for (let node of root.getChildren()) {
      if (node.view && node.type === 'area') {
        if (!walker) {
          walker = modelService.createTreeWalker(node);
        } else {
          modelService.setWalkerRoot(walker, node);
        }
        values = modelService.getElementsDataFromWalker(walker, '编辑者');
        // node.view.el.firstElementChild.textContent 如果title不是数据元
        // values['查房标题'].value 如果title是数据元
        courseTitles.push({
          code: '查房时间',
          name: values['查房标题']?.value,
          value: values['查房时间']?.value,
          emrDocumentId: documentId,
          emrCategoryCode: categoryCode,
          jump: true
        })
        if (emrConfig.value.editor) {
          let editorCode = values['编辑者']?.value[0]?.code;
          if (editorCode) {
            if (doctorLevel === 1) {
              if (editorCode !== loginUserCode) {
                node.view.setReadonly(true);
                node.view.setDeletable(false);
              } else {
                node.view.setReadonly(false);
                node.view.setDeletable(true);
              }
            }
            if (doctorLevel === 2) {
              if (editorCode === extractFields('主任医生编码')) {
                node.view.setReadonly(true);
                node.view.setDeletable(false);
              } else {
                node.view.setReadonly(false);
                node.view.setDeletable(true);
              }
            }
            if (doctorLevel === 3) {
              node.view.setReadonly(false);
              node.view.setDeletable(true);
            }
          }
        } else {
          node.view.setReadonly(true);
          node.view.setDeletable(false);
        }
      }
    }
    emrSidebarRef.value.diseaseDurationRecordTime(documentId, courseTitles)
  } else {
    for (let node of root.getChildren()) {
      if (node.view && node.type === 'area') {
        node.view.setAttribute('userInfo', {code: userData.code, name: userData.name})
      }
    }
  }
}

/**
 * 删除数据元,
 * 根据男性女性删除 月经史 数据元
 */
const deleteDataElement = () => {
  if (patientData['性别名称'] === '男') {
    currentEmr.value.deleteElement(['月经史'])
  }
}

// 重新设置提取的数据, 这里是强制替换
const reQueryPatientInformation = () => {
  // 如果不是是编辑状态
  if (!emrConfig.value.editor) return
  // 如果是只读模式就不触发这个
  if (!readonlyPattern()) {
    // 如果没有文档 id 就说明是
    if (documentId) {
      editor.setValues(extractData)
    }
  }
}

/**
 *  撤销或者重做
 */
const clickUndo = (val) => {
  editor.execute(val)
}

/**
 * 单击“提交病历”
 */
const clickToSubmitTheMedicalRecord = () => {
  if (!documentId) {
    return ElMessage.error('请先打开病历')
  }
  submitMedicalRecord(documentId)
}

const visibility = useDocumentVisibility()

watch(() => visibility.value, () => {
  if (visibility.value === 'hidden' && isEditorChange) {
    document.title = `患者【${props.huanZheXinXi.name}】，未保存数据`
  } else {
    document.title = `电子病历-正在编辑【${props.huanZheXinXi.name}】`
  }
}, {immediate: true})

/**
 * 查询患者信息
 * @returns {Promise<void>}
 */
const queryingBasicPatientInformation = async () => {
  patientData = await getEmrInpatientData({
    patNo: props.huanZheXinXi.inpatientNo,
    times: props.huanZheXinXi.admissTimes
  })
  getCurrentPersonnelInformation(patientData)
  openAssistant.data = patientData
}

// DRG 智能分组
const drgData = $ref({
  dialog: false,
  url: ''
})
// 点击查看 drg 分组 通过打开 dialog 的方式， 后续可以使用打开新的页面
const drgIntelligentGrouping = () => {
  getDrgIntelligentGrouping(props.huanZheXinXi.inpatientNo, props.huanZheXinXi.admissTimes).then(async (res) => {
    drgData.dialog = true
    drgData.url = res
  })
}

// true 是只读 false 不是只读
const readonlyPattern = () => {
  return editor !== null && editor.getEditorMode() === 'readonly';
}

// 判断 一级 二级 三级医生
let doctorLevel = 1;
const doctorLevelFunc = () => {
  if (extractFields('管床医生编码') === userData.code) {
    doctorLevel = 1
  } else if (extractFields('主治医生编码') === userData.code) {
    doctorLevel = 2
  } else if (extractFields('主任医生编码') === userData.code) {
    doctorLevel = 3
  }
}

// 提取字段
const extractFields = (val) => {
  if (patientData[val] === null) {
    return ''
  } else {
    return patientData[val]
  }
}

const isRevisionMode = () => {
  editor.setRevisionShowMode(reviewMode)
}

onMounted(() => {
  getExtractDataElement(props.huanZheXinXi.inpatientNo, props.huanZheXinXi.admissTimes).then((res) => {
    extractData = res
  })
  nextTick(async () => {
    emrSidebarRef.value.queryData()
    patientId = props.huanZheXinXi.inpatientNo
    await queryingBasicPatientInformation()
    currentEmr.value = new EMRInteractive(patientData, emrEvent);
    if (emrConfig.value.editor) {
      emrSnippetRef.value.setPatientData(patientData)
    }
    doctorLevelFunc()

    emrRef.value.parentElement.emr = currentEmr.value
    window.addEventListener('beforeunload', monitorPageRefresh, {capture: true})
  })
  getWardsApi().then((res) => {
    if (res.length > 0) {
      for (let i = 0, len = res.length; i < len; i++) {
        wardList.push(res[i].code)
      }
    }
  })
})

onDeactivated(() => {
  window.removeEventListener('beforeunload', monitorPageRefresh, {capture: true})
})


onBeforeRouteLeave((to, from, next) => {
  checkEmrChange(() => {
    next();
  })
})


</script>

<style scoped>
.emr-iframe, iframe {
  width: 100%;
}
</style>
