<template>
  <div :class="prefixCls" class="m-5 bg-white">
    <header class="p-3">
      <AButton type="primary" size="small" @click="toggleModal('add')">添加目录</AButton>
      <AButton type="primary" class="ml-2" size="small" @click="toggleModal('edit')">编辑</AButton>
      <AButton type="primary" class="ml-2" size="small" @click="handleTreeOpreate('upSerial')"
        >上移</AButton
      >
      <AButton type="primary" class="ml-2" size="small" @click="handleTreeOpreate('downSerial')"
        >下移</AButton
      >
    </header>
    <section class="p-3">
      <ATable
        v-if="treeData.length"
        :data-source="treeData"
        :columns="columns"
        size="small"
        row-key="id"
        :pagination="false"
        :defaultExpandAllRows="true"
        :custom-row="customRow"
        :row-class-name="rowClassName"
      >
        <template #name="{ text, record }">
          <div class="editable-cell">
            <div v-if="editableData[record.id]" class="editable-cell-input-wrapper">
              <a-input
                v-model:value="editableData[record.id].name"
                @pressEnter="onSave(record.id)"
              />
              <check-outlined class="editable-cell-icon-check" @click="onSave(record.id)" />

              <CloseOutlined
                class="editable-cell-icon-check"
                :style="{ right: '-24px' }"
                @click="onCancel(record.id)"
              />
            </div>
            <div v-else class="editable-cell-text-wrapper">
              {{ text || ' ' }}
              <edit-outlined class="editable-cell-icon" @click="onEdit(record.id, record)" />
            </div>
          </div>
        </template>
        <template #operation="{ record }">
          <a-popconfirm v-if="treeData.length" title="确认删除?" @confirm="onDelete(record.id)">
            <a>删除</a>
          </a-popconfirm>
        </template>
      </ATable>
    </section>
    <AModal
      :title="modalTitle"
      :visible="visible"
      @cancel="hideModal"
      @ok="onConfirm"
      :ok-button-props="{ size: 'small' }"
      :cancel-button-props="{ size: 'small' }"
    >
      <div class="p-3">
        <a-form :model="formState" :rules="rules" layout="vertical" ref="formRef">
          <a-form-item name="name" required label="名称">
            <a-input v-model:value="formState.name" autocomplete="off" class="w-6" />
          </a-form-item>
          <a-form-item
            name="id"
            required
            :label="treeSelectLabel"
            :hidden="type === 'edit' ? true : false"
          >
            <a-tree-select
              v-model:value="formState.id"
              :treeData="treeSelectData"
              :replace-fields="replaceFields"
              :tree-default-expand-all="true"
              :dropdown-style="{ height: '20rem' }"
            />
          </a-form-item>
          <a-form-item name="code2" label="图标编码">
            <a-input v-model:value="formState.code2" autocomplete="off" />
          </a-form-item>
        </a-form>
      </div>
    </AModal>
  </div>
</template>
<script lang="ts">
  import { computed, defineComponent, reactive, ref, toRaw, toRefs, unref, UnwrapRef } from 'vue'
  import { useDesign } from '/@/hooks/web/useDesign'
  import { Table, Modal, Form, Input, TreeSelect, Popconfirm, message } from 'ant-design-vue'
  import { CheckOutlined, EditOutlined, CloseOutlined } from '@ant-design/icons-vue'
  import {
    delSectionApi,
    sectionAddApi,
    sectionAllApi,
    sectionUpdateApi,
    treeResfulApi
  } from '/@/api/sys/tree'
  import { TreeResultModel } from '/@/api/model/tree'
  import { TreeRow } from '/#/tree'
  import { useMessage } from '/@/hooks/web/useMessage'

  interface FormState {
    id: string
    name: string
    code2: string
  }
  enum ModalType {
    ADD = 'add',
    EDIT = 'edit'
  }
  export default defineComponent({
    name: 'Management',
    components: {
      ATable: Table,
      AModal: Modal,
      AForm: Form,
      AInput: Input,
      ATreeSelect: TreeSelect,
      AFormItem: Form.Item,
      CheckOutlined,
      EditOutlined,
      CloseOutlined,
      APopconfirm: Popconfirm
    },
    setup() {
      const formRef = ref()
      const { prefixCls } = useDesign('management')
      const treeData = ref<TreeResultModel[]>([])
      const editableData: UnwrapRef<Record<string, TreeRow>> = reactive({})

      const row = ref<TreeRow>({
        name: '',
        code: '',
        id: '',
        parentId: '',
        depth: 0,
        serial: 0,
        attribution: '',
        contractId: '',
        createTime: '',
        code2: ''
      })
      const modal = reactive({
        visible: false,
        type: ''
      })
      const formState: UnwrapRef<FormState> = reactive({
        id: '',
        name: '',
        code2: ''
      })

      // 目录操作相关
      const toggleModal = (type?: string) => {
        // 要打开form弹窗了, 设置当前的表单值
        if (!modal.visible) {
          if (row.value.id && type) {
            const unRow = unref(row)
            if (type === ModalType.ADD) {
              formState.id = unRow.depth === 3 ? unRow.parentId : unRow.id
            } else {
              formState.id = unRow.id
              formState.name = unRow.name
              formState.code2 = unRow.code2
            }
          } else {
            const { createMessage } = useMessage()
            return createMessage.warning('请先选择节点再进行操作')
          }
        }
        modal.visible = !modal.visible
        type && (modal.type = type)
      }
      const hideModal = () => (modal.visible = false)
      const onSubmit = async () => {
        const values = await formRef.value.validate()

        const { type } = toRaw(modal)

        if (type === ModalType.ADD) {
          await sectionAddApi(values)
        } else {
          await sectionUpdateApi(values)
        }
      }

      const onConfirm = async () => {
        try {
          await onSubmit()
          await initData()
          toggleModal()
        } catch (error) {}
      }
      async function initData() {
        const result = await sectionAllApi()
        treeData.value = result.children
      }
      initData()

      const handleTreeOpreate = async (operation: 'upSerial' | 'downSerial') => {
        const id = row.value.id
        if (!id) {
          return message.error('请先选中节点')
        }
        await treeResfulApi({ id, type: 'serial', operation })
        await initData()
      }

      const modalTitle = computed(() => {
        let title = ''
        switch (modal.type) {
          case ModalType.ADD:
            title = '添加目录'
            break
          case ModalType.EDIT:
            title = '编辑'
            break

          default:
            break
        }
        return title
      })
      const columns = [
        {
          title: '名称',
          dataIndex: 'name',
          key: 'name',
          slots: { customRender: 'name' }
        },
        {
          title: '图表编码',
          dataIndex: 'code2',
          key: 'code2',
          slots: { customRender: 'code2' }
        },
        {
          title: '操作',
          dataIndex: 'operation',
          slots: { customRender: 'operation' }
        }
      ]
      const customRow = (record: TreeRow) => {
        return {
          onClick: () => {
            row.value = record
          }
        }
      }

      const rowClassName = (record: TreeRow) => {
        return record.id === row.value.id ? 'row-active' : ''
      }

      const onEdit = (key: string, record: TreeRow) => {
        editableData[key] = record
      }

      const onSave = async (key: string) => {
        const { id, name, code2 } = toRaw(editableData[key])
        await sectionUpdateApi({ id, name, code2 })
        // 执行保存请求 后初始化数据
        delete editableData[key]
        initData()
      }

      const onCancel = async (key: string) => {
        delete editableData[key]
      }
      const onDelete = async (key: string) => {
        try {
          await delSectionApi({ id: key })
          await initData()
        } catch (error) {}
      }

      const rules = {
        name: [{ required: true, message: '请输入名称' }],
        id: [
          { required: true, message: modal.type === ModalType.ADD ? '请选择父节点' : '请选择节点' }
        ]
      }

      const replaceFields = { children: 'children', title: 'name', value: 'id' }

      const treeSelectData = computed(() => {
        if (modal.type === ModalType.ADD) {
          return treeData.value.map(item => {
            const newItem = { ...item }
            if (item.children && item.children.length) {
              newItem.children = item.children.map(item => ({ ...item, children: [] }))
            }
            return newItem
          })
        }
        return treeData.value
      })

      const treeSelectLabel = computed(() => (modal.type === ModalType.ADD ? '父级目录' : '节点'))
      return {
        ...toRefs(modal),
        prefixCls,
        treeData,
        columns,
        toggleModal,
        formRef,
        hideModal,
        onConfirm,
        modalTitle,
        customRow,
        rowClassName,
        formState,
        rules,
        replaceFields,
        editableData,
        onEdit,
        onSave,
        onDelete,
        handleTreeOpreate,
        treeSelectData,
        treeSelectLabel,
        onCancel
      }
    }
  })
</script>
<style lang="less" scoped>
  @prefix-cls: ~'@{namespace}-management';

  .@{prefix-cls} {
    width: calc(100% - 2.5rem);
    height: calc(100% - 2.5rem);
    ::v-deep(.ant-table-row.row-active) {
      background: #cdefff;
    }
    ::v-deep(.ant-table-row > td:first-of-type) {
      display: flex;
      align-items: center;
    }
    .editable-cell {
      position: relative;
      width: 50%;
      .editable-cell-input-wrapper,
      .editable-cell-text-wrapper {
        padding-right: 24px;
      }
      .editable-cell-text-wrapper {
        padding: 5px 24px 5px 5px;
      }
      .editable-cell-icon,
      .editable-cell-icon-check {
        position: absolute;
        right: 0;
        width: 20px;
        cursor: pointer;
      }
      .editable-cell-icon {
        display: none;
        margin-top: 4px;
      }
      .editable-cell-icon-check {
        line-height: 28px;
      }
      .editable-cell-icon:hover,
      .editable-cell-icon-check:hover {
        color: #108ee9;
      }
      .editable-add-btn {
        margin-bottom: 8px;
      }
    }
    .editable-cell:hover .editable-cell-icon {
      display: inline-block;
    }
  }
</style>
