<script setup lang="ts">
import type { BaseFieldItem, TableFields } from '@/types/Tables/table'
import type { FormInstance, FormRules } from 'element-plus'
import type {
  DialogProps,
  SaveForm,
} from '@/types/Tables/customIndicatorDialog'

import { reactive, ref, watch } from 'vue'
import { useTable } from '@/hooks/useTable'
import { useCustomIndicatorDialog } from '@/hooks/useCustomIndicatorDialog'
import { useDialogDrag } from '@/hooks/useDialogDrag'
import { Search } from '@element-plus/icons-vue'

const { isFixedField } = useTable()
const {
  initSortedTableFieldsInfo,
  validCustomName,
  updateFixedIndicator,
  updateUnfixedIndicator,
  getActivedIndicator,
  updateSortedTableFieldsInfo,
} = useCustomIndicatorDialog()

const props = withDefaults(defineProps<DialogProps>(), {
  SaveFormData: () => {
    return {
      schemeName: '默认',
      isSaveCustom: false,
      saveCustomName: '',
    }
  },
})

const emits = defineEmits(['updateFields'])

const saveForm = reactive<SaveForm>(props.SaveFormData)

const saveFormRules = reactive<FormRules<SaveForm>>({
  saveCustomName: [{ validator: validCustomName, trigger: 'blur' }],
})

// 保存自定义指标表单实例
const saveFormRef = ref<FormInstance>()

// 被排序过后的表格字段信息
const sortedTableFieldsInfo = reactive<Array<TableFields>>([])

// 点击应用后新生成的字段信息
const newTableFieldsInfo = reactive<Array<TableFields>>([])

// 自定义指标的展示状态
const customIndicatorVisible = ref<boolean>(false)

// 每次展开的时候，右侧栏目的排序需要跟表格字段的顺序同步
// 不然会导致表格字段和右侧的栏目的顺序不一致
// 关闭后需要重置这个状态，每次打开都要排一次
const isFirstShow = ref<boolean>(true)

// 自定义指标搜索值
const indicatorSearch = ref<string>('')

// 自定义指标左侧导航选中值
const indicatorNavActive = ref<string>(props.defaultActiveNav)

// 拖拽的容器
const dragContentRef = ref<HTMLElement | null>(null)

// 当前正在被拖拽的元素
const dragingRef = ref<HTMLElement | null>(null)

// 所有需要固定的指标
const fixedIndicator = reactive<TableFields[]>([])

// 所有需要不固定的指标
const unFixedIndicator = reactive<TableFields[]>([])

const { dragStart, dragEnter, dragOver, dragEnd } = useDialogDrag(
  dragingRef,
  dragContentRef,
)

// 当默认值变化的时候，要更新一下，这里主要用在初始化的时候，数据可能还没有获取到
watch(
  () => props.defaultActiveNav,
  (newMenu: string) => {
    indicatorNavActive.value = newMenu
  },
  {
    deep: true,
  },
)

/**
 * @description: 多选框值改变，去更新不固定字段的展示
 * @return {*}
 */
const changeIndicatorChecked = () => {
  updateUnfixedIndicator(
    props.indicatorFields,
    isFirstShow,
    props.tableFieldsInfo,
    unFixedIndicator,
  )
}

/**
 * @description: 填充表单的数据
 * @return {*}
 */
const fillFomrData = () => {
  Object.assign(saveForm, props.SaveFormData)
}

/**
 * @description: 对话框打开
 * @return {*}
 */
const indicatorOpen = () => {
  isFirstShow.value = true // 用于同步表格和右侧栏目的顺序
  console.log(props.SaveFormData)
  if (props.SaveFormData.schemeName !== '默认') {
    fillFomrData()
  }
  // 给不固定框一个初始值
  changeIndicatorChecked()
  updateFixedIndicator(props.indicatorFields, fixedIndicator) // 固定框给初始值
}

/**
 * @description: 对话框关闭
 * @return {*}
 */
const indicatorClose = () => {
  // 重置到第一个锚点
  indicatorNavActive.value = props.indicatorFields[0]?.name
  // isSaveCustom.value = false
  saveForm.isSaveCustom = false
}

/**
 * @description: 跳转到指定的指标区域
 * @param {*} name 标签分段的字段名
 * @return {*}
 */
const goToIndicator = (name: string) => {
  let el = document.querySelector(`div[data-anchor="${name}"]`) as HTMLElement
  if (!el) return
  indicatorNavActive.value = name
  el.scrollIntoView({ behavior: 'smooth' })
}

/**
 * @description: 展示自定义指标弹窗
 * @return {*}
 */
const showCustomIndicator = () => {
  sortedTableFieldsInfo.splice(
    0,
    sortedTableFieldsInfo.length,
    ...JSON.parse(JSON.stringify(props.tableFieldsInfo)),
  )

  customIndicatorVisible.value = true
}

/**
 * @description: 生成新的表格字段信息
 * @return {*}
 */
const generateNewTableField = () => {
  customIndicatorVisible.value = false
  updateSortedTableFieldsInfo(
    sortedTableFieldsInfo,
    dragContentRef,
    unFixedIndicator,
    fixedIndicator,
  ) // 排序
  // 拿到当前激活的所有自定义指标
  let actived = getActivedIndicator(props.indicatorFields)
  // 把目前排好序的字段信息复制给新的字段信息
  newTableFieldsInfo.splice(
    0,
    newTableFieldsInfo.length,
    ...JSON.parse(JSON.stringify(sortedTableFieldsInfo)),
  )
  // 根据当前已经激活的字段name，去吧字段信息中的state改为true
  newTableFieldsInfo.map(item => {
    if (actived.includes(item.name)) {
      item.state = true
    } else {
      item.state = false
    }
  })
}

/**
 * @description: 验证保存自定义指标的表单是否填写正确了
 * @param {FormInstance | undefined} saveFormRef 自定义指标表单实例
 * @return {Promise<boolean>} 验证结果
 */
const validSaveForm = async (
  saveFormRef: FormInstance | undefined,
): Promise<boolean> => {
  if (!saveFormRef) return false
  let result = await saveFormRef.validate()
  return result
}

/**
 * @description: 应用配置的自定义指标
 * @return {*}
 */
const applyCustomIndicator = async (saveFormRef: FormInstance | undefined) => {
  let fileName = null
  // 需要保存自定义指标为常用模板就需要去检查一下这个文件名
  if (saveForm.isSaveCustom) {
    let result = await validSaveForm(saveFormRef)
    if (!result) return
    fileName = saveForm.saveCustomName
  }
  generateNewTableField()
  emits('updateFields', newTableFieldsInfo, fileName)
}

/**
 * @description: 取消已经选中的指标
 * @param {*} name 字段名
 * @return {*}
 */
const cancelSelect = (name: string) => {
  for (let i = 0; i < props.indicatorFields.length; i++) {
    let children = props.indicatorFields[i].children
    let result = children.find(item => item.name === name)
    console.log(props.indicatorFields[i])

    if (result) {
      result.state = false
      props.indicatorFields[i].value = props.indicatorFields[i].value.filter(
        item => item !== result.name,
      )
      changeIndicatorChecked()
      break
    }
  }
}

/**
 * @description: 判断当前是否有跟搜索框的值匹配的指标
 * @param {BaseFieldItem} field 当前指标组
 * @return {boolean} 是否有匹配的指标
 */
const hasMatchIndicator = (field: BaseFieldItem<TableFields>): boolean => {
  let result = field.children.find(item => {
    return item.label.includes(indicatorSearch.value)
  })
  return Boolean(result)
}
initSortedTableFieldsInfo(sortedTableFieldsInfo, props.tableFieldsInfo)

defineExpose({ showCustomIndicator })
</script>

<template>
  <div class="customIndicatorContainer">
    <el-dialog
      v-model="customIndicatorVisible"
      title="自定义指标"
      width="1096"
      :append-to-body="true"
      :align-center="true"
      @open="indicatorOpen"
      @close="indicatorClose"
      class="el-dialog"
      :close-on-click-modal="false"
    >
      <div class="indicatorBox">
        <div class="topWrapper">
          <el-input
            v-model="indicatorSearch"
            style="width: 240px"
            placeholder="输入指标名称搜索"
            :suffix-icon="Search"
          />
        </div>
        <div class="indicatorWrapper">
          <div class="indicatorSider">
            <div v-for="item in indicatorFields">
              <div
                v-show="hasMatchIndicator(item)"
                @click="goToIndicator(item.name)"
                class="indicatorCategory"
                :class="{
                  indicatorCategoryActive: indicatorNavActive === item.name,
                }"
              >
                {{ item.label }}
              </div>
            </div>
          </div>
          <div class="indicatorContent">
            <div
              v-for="field in indicatorFields"
              :data-anchor="field.name"
              class="indicatorBlock"
            >
              <div v-show="hasMatchIndicator(field)">
                <div class="indicatorGroup">
                  <span>{{ field.label }}</span>
                </div>
                <el-row class="indicatorItem">
                  <template v-for="item in field.children">
                    <el-col
                      :span="8"
                      v-show="item.label.includes(indicatorSearch)"
                    >
                      <el-checkbox-group
                        v-model="field.value"
                        @change="changeIndicatorChecked"
                      >
                        <el-checkbox
                          style="margin-bottom: 16px"
                          :value="item.name"
                          :label="item.label"
                          :disabled="isFixedField(props.fixedFields, item)"
                        />
                      </el-checkbox-group>
                    </el-col>
                  </template>
                </el-row>
              </div>
            </div>
          </div>
        </div>
        <div class="dragWrapper">
          <div class="dragHeader">
            <div class="dragTitle">已选指标</div>
            <div class="dragDes">拖拽可自定义指标顺序</div>
            <div class="fixedIndicator">
              <div class="dragBlock notAllow" v-for="item in fixedIndicator">
                {{ item.label }}
              </div>
            </div>
            <div class="dragSepreate">以上指标将横向固定</div>
          </div>
          <div
            class="dragContent"
            ref="dragContentRef"
            @dragstart="dragStart"
            @dragenter="dragEnter"
            @dragover="dragOver"
            @dragend="dragEnd"
          >
            <div
              draggable="true"
              v-for="item in unFixedIndicator"
              class="dragBlock"
              :name="item.name"
            >
              {{ item.label }}
              <el-icon @click="cancelSelect(item.name)" class="closeBtn"
                ><Close
              /></el-icon>
            </div>
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialogFooter">
          <div class="footerTools">
            <el-form
              ref="saveFormRef"
              :model="saveForm"
              :rules="saveFormRules"
              inline
            >
              <el-form-item class="saveFormItem" prop="isSaveCustom">
                <el-checkbox
                  v-model="saveForm.isSaveCustom"
                  label="保存为常用自定义指标"
                  size="default"
                />
              </el-form-item>
              <el-form-item
                v-if="saveForm.isSaveCustom"
                prop="saveCustomName"
                class="saveFormItem"
              >
                <el-input
                  v-model="saveForm.saveCustomName"
                  style="width: 240px"
                  placeholder="请输入自定义指标名"
                />
              </el-form-item>
            </el-form>
          </div>
          <div class="footerBtn">
            <el-button @click="customIndicatorVisible = false">取消</el-button>
            <el-button
              type="primary"
              @click="applyCustomIndicator(saveFormRef)"
            >
              应用
            </el-button>
          </div>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.indicatorBox {
  position: relative;
  width: 100%;
  height: 100%;
}

.topWrapper {
  margin-bottom: 16px;
}

.indicatorWrapper {
  display: flex;
  width: 832px;
  height: 516px;
  border: 1px solid #eaebec;
  border-radius: 4px;
}

.indicatorSider {
  flex-shrink: 0;
  width: 160px;
  overflow: auto;
  border-right: 1px solid #eaebec;
}

.indicatorCategory {
  padding-left: 16px;
  font-size: 14px;
  line-height: 40px;
  color: #333;
  cursor: pointer;
}

.indicatorCategoryActive {
  color: #197afb;
  background-color: #d6eaff;
}

.indicatorContent {
  width: 672px;
  overflow: auto;
  scroll-behavior: smooth;
}

.indicatorGroup {
  color: rgb(51, 51, 51);
  color-scheme: light;
  display: block;
  font-weight: 700;
  font-size: 14px;
  word-break: break-all;
  -webkit-font-smoothing: subpixel-antialiased;
  margin-bottom: 16px;
}

.indicatorBlock {
  width: 100%;
  padding: 16px 0 0 24px;
  border-bottom: 1px solid #eaebec;
  // display: flex;
  // flex-wrap: wrap;
}

.dragWrapper {
  position: absolute;
  top: 0;
  right: 0;
  flex-shrink: 0;
  width: 216px;
  height: 565px;
  padding: 10px 0;
  overflow: auto;
  background-color: #f8f8f9;
}

.dragHeader,
.dragContent {
  padding: 0 16px;
}

.dragTitle {
  font-size: 14px;
  font-weight: 700;
  line-height: 100%;
  color: #333;
}

.dragDes {
  margin: 8px 0;
  font-size: 12px;
  line-height: 100%;
  color: #999;
}

.dragBlock {
  position: relative;
  width: 184px;
  height: 40px;
  padding: 0 30px 0 36px;
  overflow: hidden;
  line-height: 40px;
  text-overflow: ellipsis;
  white-space: nowrap;
  background-color: #fff;
  border-bottom: 1px solid #e8eaec;
  cursor: all-scroll;
  transition: 0.1s all;
}

.dragBlock:hover {
  .closeBtn {
    display: block;
  }
}

.dragMove {
  background-color: white;
  border: 1px solid #197afb;
}

.closeBtn {
  display: none;
  cursor: pointer;
  position: absolute;
  top: 13px;
  right: 8px;
}

// 禁止拖拽
.notAllow {
  cursor: not-allowed;
}

.dragSepreate {
  position: relative;
  margin: 16px 0 0;
  font-size: 12px;
  color: #999;
  text-align: center;
}

.dragWrapper .dragSepreate::before {
  position: absolute;
  top: 9px;
  left: 0;
  width: 32px;
  height: 1px;
  content: '';
  background-color: #e8eaec;
}
.dragWrapper .dragSepreate::after {
  position: absolute;
  top: 9px;
  right: 0;
  width: 32px;
  height: 1px;
  content: '';
  background-color: #e8eaec;
}

.dragWrapper .dragBlock::before {
  position: absolute;
  top: 16px;
  left: 12px;
  width: 16px;
  height: 2px;
  content: '';
  background-color: #999;
}
.dragWrapper .dragBlock::after {
  position: absolute;
  bottom: 16px;
  left: 12px;
  width: 16px;
  height: 2px;
  content: '';
  background-color: #999;
}

.dragContent {
  margin-top: 16px;
  overflow-x: hidden;
  overflow-y: auto;
}

.saveFormItem {
  margin-bottom: 0;
  margin-right: 15px;
  // padding: 0 5px;
}

.dialogFooter {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
</style>
