<template>
  <div style="height: 82vh; margin: 0; background-color: #fff">
    <vxe-grid ref="tableRef" :row-config="{ isCurrent: true, isHover: true }" @filter-change="filterChangeEvent" v-bind="gridOptions">
      <template #toolbar_buttons>
        <a-space wrap v-if="curProject">
          <a-button type="link" block @click="handleChangeLeftWidth">
            <menuUnfoldOutlined v-if="collapsed" class="trigger" />
            <MenuFoldOutlined v-else class="trigger" />
          </a-button>
          <vxe-button mode="text" status="primary" @click="handleAddCheckMethod()"> 新增</vxe-button>
          <vxe-button mode="text" status="primary" @click="handleAddFromLib()">从标准库添加</vxe-button>
          <vxe-button mode="text" status="primary" @click="deleteProjectCheck()"> 删除</vxe-button>
        </a-space>
        <div style="margin-left: 80px">
          <span style="line-height: 20px">全表搜索：</span>
          <vxe-input v-model="searchText" placeholder="搜索" style="width: 300px" />
          <vxe-button mode="text" status="primary" @click="searchEvent()">搜索</vxe-button>
          <vxe-button mode="text" status="primary" @click="refreshEvent()">刷新</vxe-button>
        </div>
        <div style="margin-left: 80px">
          <vxe-button mode="text" status="primary" @click="showProject()">返回项目列表</vxe-button>
        </div>
      </template>

      <template #item_slots="{ row }">
        <vxe-button mode="text" status="primary" @click="handleShowDrawer(row)">
          <div class="cell-content" v-html="row.item"></div>
        </vxe-button>
      </template>
      <template #isPublic="{ row }">
        <span v-if="row.isPublic">公有</span>
        <span v-else>私有</span>
      </template>

      <template #caName_slots="{ row }">
        <template v-for="(item, ind) in row.actNames?.split(',')" :key="ind">
          <div v-html="item" @click="searchEventByAct(item)"></div>
        </template>
      </template>

      <template #cgrpPath_slots="{ row }">
        <template v-for="(item, ind) in row.cgrpPath?.split('/')" :key="ind">
          <div v-html="item"></div>
        </template>
      </template>

      <template #fileName_slots="{ row }">
        <vxe-button mode="text" size="small" status="primary" @click="showFileContent(row)">
          <span class="cell-content" v-html="row.fileName"></span>
        </vxe-button>
      </template>

      <template #operate="{ row }">
        <div>
          <vxe-button mode="text" status="primary" @click="setProjectItem(row)">方法</vxe-button>
          <vxe-button mode="text" status="primary" :disabled="!row.isPublic" @click="editCheckMethod(row)">编辑</vxe-button>
        </div>
      </template>
      <template #pager>
        <vxe-pager
          v-show="gridOptions.pagerConfig.enabled"
          :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
          v-model:current-page="tablePage.currentPage"
          v-model:page-size="tablePage.pageSize"
          v-model:page-sizes="tablePage.pageSizes"
          :total="tablePage.total"
          @page-change="handlePageChange"
        />
      </template>
    </vxe-grid>
    <a-drawer
      title="详情"
      placement="bottom"
      height="60%"
      :visible="showDrawer"
      :get-container="false"
      @close="closeDrawer"
      :style="{ position: 'absolute' }"
    >
      <a-descriptions title="" bordered :column="1" :labelStyle="{ minWidth: '100px' }">
        <a-descriptions-item label="条目">{{ desData?.item }}</a-descriptions-item>
        <a-descriptions-item label="内容">{{ desData?.content }}</a-descriptions-item>
        <a-descriptions-item label="控制项">
          <template v-for="(item, ind) in desData?.actNames?.split(',')" :key="ind">
            <div v-html="item"></div>
          </template>
        </a-descriptions-item>
        <a-descriptions-item label="参考文件">
          <a @click="showFileContent(desData)">{{ desData?.fileName }}</a>
        </a-descriptions-item>
      </a-descriptions>
    </a-drawer>
  </div>
  <FileViewerModal @register="registerShowFileContentModal" :useStaticPrefixForDocx="true" />
</template>
<script setup lang="ts">
  import { ref, reactive, nextTick } from 'vue';
  import { VxeGridProps, VXETable } from 'vxe-table';
  import { defHttp } from '/@/utils/http/axios';
  import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
  import FileViewerModal from '/@/components/onlinePreview/FileViewerModal.vue';
  import { useModal } from '/@/components/Modal';

  const getProjectChecks = '/audit/auditProject/getProjectChecks';
  const deleteProjectTaskUrl = '/audit/auditTask/deleteTaskBatch';

  const [registerShowFileContentModal, { openModal: openFileContentModel }] = useModal();

  const desData = ref();
  const tableRef = ref();
  const collapsed = ref(false);
  const curProject = ref();
  const fileList = ref([]);
  const tableData = ref([]);
  const oldData = ref([]);
  const showDrawer = ref(false);
  const searchText = ref('');
  const cgrpList = ref([]);
  const actList = ref([]);

  const emit = defineEmits(['callback', 'setLeftWidth', 'addProjectCheck', 'addCheckFromLib', 'setFileList', 'showProject']);

  const nameFilterRender = {
    name: 'VxeInput',
  };

  const tablePage = reactive({
    total: 0,
    currentPage: 1,
    pageSize: 10,
    pageSizes: [10, 30, 50, 100, 300, 500, 1000],
  });

  const fileFilterMethod = ({ value, row }) => row['fileId'] === value;

  const isPublicFilterMethod = ({ value, row }) => {
    return row['isPublic'] === value;
  };

  const cgrpPathFilterMethod = ({ value, row }) => row['cgrp'] === value;

  function textFilterMethod({ option, row, column }) {
    if (option.data) {
      return String(row[column.field]).includes(option.data);
    }
    return true;
  }

  const gridOptions = reactive<VxeGridProps>({
    border: true,
    stripe: true,
    showFooter: true,
    height: 'auto',
    tooltipConfig: {},
    menuConfig: {},
    columnConfig: {
      resizable: true,
      useKey: true,
    },
    rowConfig: {
      resizable: true,
      useKey: true,
    },
    checkboxConfig: {
      highlight: true,
      checkStrictly: false,
    },
    toolbarConfig: {
      zoom: true,
      custom: true,
      slots: {
        buttons: 'toolbar_buttons',
      },
    },
    pagerConfig: {
      enabled: true,
      pageSize: 10,
    },
    columns: [
      { type: 'checkbox', visible: true, width: '50', showOverflow: false },
      {
        field: 'content',
        title: '检查项',
        sortable: true,
        filters: [{ data: '' }],
        filterMethod: textFilterMethod,
        filterRender: nameFilterRender,
        type: 'html',
      },
      {
        field: 'actNames',
        title: '控制项',
        width: '15%',
        visible: true,
        slots: { default: 'caName_slots' },
        filters: [{ data: '' }],
        filterMethod: textFilterMethod,
        filterRender: nameFilterRender,
        type: 'html',
      },
      {
        field: 'item',
        title: '合规条目',
        showOverflow: 'title',
        sortable: true,
        filters: [{ data: '' }],
        filterMethod: textFilterMethod,
        filterRender: nameFilterRender,
        width: '13%',
        visible: true,
        type: 'html',
        slots: { default: 'item_slots' },
      },
      {
        field: 'fileName',
        title: '参考文件',
        showOverflow: 'title',
        sortable: true,
        width: '13%',
        visible: true,
        filters: [],
        filterMethod: fileFilterMethod,
        filterMultiple: true,
        type: 'html',
        slots: { default: 'fileName_slots' },
      },
      {
        field: 'cgrpPath',
        title: '分组',
        sortable: true,
        width: '12%',
        visible: true,
        type: 'html',
        filters: [],
        //slots: { default: 'cgrpPath_slots' },
        filterMethod: cgrpPathFilterMethod,
        filterMultiple: true,
      },
      {
        field: 'des',
        title: '说明',
        width: '8%',
        filters: [{ data: '' }],
        filterMethod: textFilterMethod,
        filterRender: nameFilterRender,
        visible: true,
        type: 'html',
      },
      {
        field: 'isPublic',
        title: '公有',
        filters: [
          { value: 1, label: '公有' },
          { value: 0, label: '私有' },
        ],
        filterMethod: isPublicFilterMethod,
        filterMultiple: true,
        width: '6%',
        visible: true,
        slots: { default: 'isPublic' },
      },
      { title: '操作', align: 'center', width: '140', visible: true, fixed: 'right', slots: { default: 'operate' } },
    ],
    data: [],
  });

  function setProjectItem(row) {
    emit('callback', row);
  }

  function handleChangeLeftWidth() {
    collapsed.value = !collapsed.value;
    emit('setLeftWidth', collapsed.value);
  }

  const refreshEvent = async () => {
    await iniData(curProject.value, null);
  };

  function handleAddCheckMethod() {
    emit('addProjectCheck');
  }

  function handleAddFromLib() {
    const ids = oldData.value.map((item) => item.checkid);
    emit('addCheckFromLib', ids);
  }

  function editCheckMethod(row) {
    emit('addProjectCheck', row);
  }

  async function deleteProjectCheck() {
    const type = await VXETable.modal.confirm('您确定要删除该数据?');
    const $grid = tableRef.value;
    if ($grid) {
      let { ids, checkids } = await getSelectIds();
      if (ids.length === 0) {
        VXETable.modal.message({ content: '请选择记录', status: 'warning' });
        return;
      }
      if (type === 'confirm') {
        let params = { ids: ids, checkids: checkids, projectid: curProject.value.id };
        try {
          await defHttp.delete({ url: deleteProjectTaskUrl, data: params }, { joinParamsToUrl: true });
          iniData(curProject.value);
        } catch (error) {
          console.error('Delete operation failed:', error);
        }
      }
    }
  }

  async function getSelectIds() {
    let ids = [];
    let checkids = [];
    const $table = tableRef.value;
    if ($table) {
      const selRecords = $table.getCheckboxRecords();
      selRecords.forEach((ele) => {
        ids.push(ele.id);
        checkids.push(ele.checkid);
      });
    }
    return { ids, checkids };
  }

  const handlePageChange = ({ currentPage, pageSize }) => {
    tablePage.currentPage = currentPage || 1;
    tablePage.pageSize = pageSize || 10;
    tablePage.total = tableData.value.length;
    let start = (tablePage.currentPage - 1) * tablePage.pageSize;
    let end = start + tablePage.pageSize;
    gridOptions.data = tableData.value.slice(start, end);
  };

  async function iniData(project, srhName) {
    curProject.value = project;
    gridOptions.data = [];
    gridOptions.loading = true;
    searchText.value = '';
    const $table = tableRef.value;
    $table?.clearFilter();
    try {
      oldData.value = tableData.value = await defHttp.get({ url: getProjectChecks, params: { id: project.id, itemName: srhName } });
      gridOptions.loading = false;
      await Promise.all([setCgrpList(), setFileList(), updatePage(), setActList()]);
      emit('setFileList', fileList.value, actList.value);
      const $table = tableRef.value;
      if ($table) {
        $table.setFilter('fileName', fileList.value);
      }
    } catch (error) {
      console.error('Data initialization failed:', error);
    }
  }

  async function setFileList() {
    const uniqueFileList = Array.from(
      new Map(tableData.value.map((item) => [item.fileId, { value: item.fileId, label: item.fileName, filePath: item.filePath }])).values()
    );
    fileList.value = uniqueFileList;
  }

  const searchEvent = async () => {
    const filterSrhTxt = searchText.value.trim().toLowerCase();
    if (filterSrhTxt) {
      const filterRE = new RegExp(filterSrhTxt, 'gi');
      const searchProps = ['content', 'fileName', 'item', 'cgrpPath', 'complineContent', 'actNames', 'des'];
      tableData.value = oldData.value
        .filter((item) =>
          searchProps.some((key) => {
            if (item[key]) {
              return String(item[key]).toLowerCase().includes(filterSrhTxt);
            }
            return false;
          })
        )
        .map((row) => {
          const item = { ...row };
          searchProps.forEach((key) => {
            const value = item[key] ? String(item[key]) : '';
            item[key] = value.replace(filterRE, (match) => `<span class="keyword-lighten" style="color:red">${match}</span>`);
          });
          return item;
        });
    } else {
      tableData.value = [...oldData.value];
    }
    await handlePageChange({ currentPage: 1, pageSize: tablePage.pageSize });
  };

  const showFileData = async (fileData) => {
    const $table = tableRef.value;
    if ($table) {
      const column = $table.getColumnByField('fileName');
      if (column) {
        column.filters.forEach((element) => {
          element.checked = false;
        });
        const option = column.filters.find((item) => item.value === fileData.value);
        if (option) {
          option.checked = true;
          await filterChangeEvent({ field: 'fileName', datas: [], values: [fileData.value] });
        }
      }
    }
  };

  const showActData = async (data) => {
    const $table = tableRef.value;
    if ($table) {
      const column = $table.getColumnByField('actNames');
      if (column) {
        column.filters[0].data = data.name; // set to first filter option
        column.filters[0].checked = true;
        await $table.updateData();
        await filterChangeEvent({ field: 'actNames', datas: [data.name], values: [] });
      }
    }
  };

  async function filterChangeEvent({ field, values, datas }) {
    if (values.length == 0 && datas.length === 0) {
      gridOptions.data = tableData.value = oldData.value;
      await updatePage();
      return;
    }

    field = field === 'cgrpPath' ? 'cgrp' : field === 'fileName' ? 'fileId' : field;

    if (field == 'fileId' || field == 'cgrp' || field == 'isPublic') {
      tableData.value = oldData.value.filter((item) => values.includes(item[field]));
    } else {
      tableData.value = oldData.value.filter((item) =>
        datas.some((data) => {
          const itemField = item[field];
          return itemField && typeof itemField === 'string' ? itemField.includes(data) : itemField === null && data === null;
        })
      );
    }

    const promises = [updatePage()];
    if (field === 'fileId') {
      promises.push(setCgrpList());
    }

    await Promise.all(promises);
  }

  async function updatePage() {
    await handlePageChange({ currentPage: 1, pageSize: tablePage.pageSize });
  }

  async function setCgrpList() {
    cgrpList.value = [...new Set(tableData.value.map((item) => item.cgrp))].map((cgrp) => ({
      value: cgrp,
      label: tableData.value.find((item) => item.cgrp === cgrp)?.cgrpPath, // Use optional chaining
    }));
    const $table = tableRef.value;
    if ($table) {
      $table.setFilter('cgrpPath', cgrpList.value);
    }
  }

  const setActList = async () => {
    const actMap = {};
    actList.value = [];
    tableData.value.forEach((item) => {
      if (item.actIds && item.actNames) {
        const ids = item.actIds.split(',').map((id) => id.trim());
        const names = item.actNames.split(',').map((name) => name.trim());
        ids.forEach((id, index) => {
          const name = names[index];
          if (!actMap[id]) {
            actMap[id] = true;
            actList.value.push({ id, name });
          }
        });
      }
    });
  };

  function handleShowDrawer(row) {
    desData.value = {
      item: row.item,
      content: row.complineContent,
      actNames: row.actNames,
      fileName: row.fileName,
      filePath: row.filePath,
      fileId: row.fileId,
      fileTp: row.fileTp,
    };
    showDrawer.value = true;
  }

  function closeDrawer() {
    showDrawer.value = false;
  }

  function showProject() {
    fileList.value = [];
    actList.value = [];
    emit('showProject', true);
  }

  async function searchEventByAct(actName) {
    const textOnly = actName.replace(/<[^>]*>/g, '');
    searchText.value = textOnly;
    await searchEvent();
  }

  async function showFileContent(row) {
    if (row.fileId) {
      openFileContentModel(true, {
        record: { fileId: row.fileId },
        isUpdate: false,
        showFooter: true,
      });
    }
  }

  const clearFilter = async () => {
    try {
      searchText.value = '';
      const $table = tableRef.value;
      if ($table) {
        await $table.clearFilter();
      }
      gridOptions.data = tableData.value = oldData.value || [];
      await updatePage();
    } catch (error) {
      console.error('Error during clearing filter: ', error);
    }
  };

  const deleteProjectCheckByIds = async (checkids) => {
    let params = { ids: '', checkids: checkids, projectid: curProject.value.id };
    try {
      await defHttp.delete({ url: deleteProjectTaskUrl, data: params }, { joinParamsToUrl: true });
    } catch (error) {
      console.error('Delete operation failed:', error);
    }
  };

  const searchByItemName = async (srhName) => {
    await iniData(curProject.value, srhName);
  };

  defineExpose({
    iniData,
    getSelectIds,
    showFileData,
    showActData,
    clearFilter,
    deleteProjectCheckByIds,
    searchByItemName,
  });
</script>

<style scope>
  .cell-content {
    text-align: left;
    white-space: normal;
    overflow-wrap: break-word;
    max-width: 100%;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
  }
</style>
