<script lang="ts" setup>
/**
 * @Name: root-word-manage-table.vue
 * @Description: 词根管理表格
 * @Author: Cheney
 */

import { Plus, Search, Upload } from '@element-plus/icons-vue';
import * as api from '../api';
import type { UploadInstance, UploadRawFile } from 'element-plus';
import { ElMessage, FormInstance, FormRules, genFileId } from 'element-plus';
import { SUCCESS_CODE, WARNING_CODE } from '/@/utils/requestCode';


interface DataItem {
  id: number;
  modifier_name: string;
  creator_name: string;
  create_datetime: string;
  update_datetime: string;
  description: string | null;
  modifier: string;
  searchTerm: string;
  searchTerm_type: string;
  add_date: string;
  creator: number;
  isEditing: boolean; // 添加isEditing字段
  popConfirmVisible: boolean; // 添加popConfirmVisible字段
  tempSearchTermType: string; // 添加tempSearchTermType字段
}

const currentDate = new Date().toISOString().split('T')[0];

const tableLoading = ref(false);
const tableData = ref<DataItem[]>([]);
const total = ref(0);
const currentPage = ref(1);
const pageSize = ref(20);

const searchTermInpRef = ref();

const dialogVisible = ref(false);
const formSearchTermInpRef = ref();
const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive({
  searchTerm: '',
  searchTermType: 'positive'
});
const rules = reactive<FormRules<typeof ruleForm>>({
  searchTerm: [ { required: true, validator: checkSearchTerm, trigger: 'blur' } ],
  searchTermType: [ { required: true, validator: checkSearchTermType, trigger: 'blur' } ]
});

const searchTermTypeFilter = ref('all');
const searchTermFilter = ref('');
const sortFields = ref('');
const isAscending = ref(false);
const upload = ref<UploadInstance>();

onMounted(() => {
  fetchSearchTermList();
});

/**
 * 添加关键词
 */
async function addSearchTerm() {
  const body = {
    searchTerm: ruleForm.searchTerm,
    searchTerm_type: ruleForm.searchTermType,
    add_date: currentDate // 使用当前日期代替硬编码日期
  };
  try {
    const response = await api.postCreateSearchTerm(body);
    handleResponse(response);
    if (response.code === SUCCESS_CODE) await fetchSearchTermList();
  } catch (error) {
    console.error('==Error==', error);
  }
}

/**
 * 删除行数据
 * @param row 行数据
 */
async function handleDelete(row: any) {
  try {
    const response = await api.deleteSearchTerm(row.id);
    handleResponse(response);
    if (response.code === SUCCESS_CODE) {
      tableData.value = tableData.value.filter((item) => item.id !== row.id);
      await fetchSearchTermList();
    } else {
      ElMessage.error('删除失败');
    }
  } catch (error) {
    console.error('==Error==', error);
  }
}

/**
 * 获取关键词列表数据
 */
async function fetchSearchTermList() {
  tableLoading.value = true;
  const query = {
    page: currentPage.value,
    limit: pageSize.value,
    searchTerm: searchTermFilter.value,
    searchTerm_type: searchTermTypeFilter.value,
    sort_fields: sortFields.value,
    isAscending: isAscending.value,
  };
  try {
    const response = await api.getSearchTermList(query);
    total.value = response.total;
    const responseData: DataItem[] = response.data;
    tableData.value = responseData.map((item) => ({
      ...item,
      isEditing: false,
      popConfirmVisible: false,
      tempSearchTermType: item.searchTerm_type
    }));
  } catch (error) {
    console.error('==Error==', error);
  } finally {
    tableLoading.value = false;
    await nextTick();
    window.dispatchEvent(new Event('resize'));
  }
}

/**
 * 更新关键词
 * @param row 修改行数据
 */
async function updateSearchTerm(row: any) {
  row.isEditing = false;
  const data = {
    searchTerm: row.searchTerm,
    searchTerm_type: row.searchTerm_type
  };
  try {
    const response = await api.postUpdateSearchTerm({ data, id: row.id });
    handleResponse(response);
    if (response.code === SUCCESS_CODE) {
      await fetchSearchTermList();
    } else {
      ElMessage.error('更新失败');
    }
  } catch (error) {
    console.error('==Error==', error);
  }
}

/**
 * 更新搜索词类型
 * @param row
 */
async function updateSearchTermType(row: any) {
  const data = {
    searchTerm: row.searchTerm,
    searchTerm_type: row.searchTerm_type
  };
  try {
    const response = await api.postUpdateSearchTerm({ data, id: row.id });
    handleResponse(response);
    if (response.code === SUCCESS_CODE) {
      await fetchSearchTermList();
    } else {
      ElMessage.error('更新失败');
    }
  } catch (error) {
    console.error('==Error==', error);
  } finally {
    row.popConfirmVisible = false;
  }
}

function showPopConfirm(row: any) {
  row.popConfirmVisible = true;
}

/**
 * 取消修改, 并恢复搜索词类型的值
 * @param row 行数据
 */
function cancelUpdate(row: any) {
  row.popConfirmVisible = false;
  row.searchTerm_type = row.tempSearchTermType;
  ElMessage.warning({ message: '修改已取消', plain: true });
}

/**
 * 切换编辑状态, 并自动获取焦点
 * @param row 行数据
 */
function handleClick(row: any) {
  row.isEditing = !row.isEditing;
  nextTick(() => {
    searchTermInpRef.value.focus();
  });
}

/**
 * 切换页码
 * @param newPage 新页码
 */
async function handleCurrentChange(newPage: number) {
  currentPage.value = newPage;
  await fetchSearchTermList();
}

/**
 * 切换每页条数
 * @param newSize 新每页条数
 */
async function handleSizeChange(newSize: number) {
  currentPage.value = 1;
  pageSize.value = newSize;
  await fetchSearchTermList();
}

/**
 * 关闭对话框时清空表单
 * @param done
 */
function handleClose(done: Function) {
  if (ruleFormRef.value) ruleFormRef.value.resetFields();
  done();
}

/**
 * 打开对话框, 并自动获取焦点
 */
function handleDialogVisible() {
  dialogVisible.value = true;
  setTimeout(() => {
    formSearchTermInpRef.value.focus();
  }, 100);
}

function checkSearchTerm(rule: any, value: any, callback: any) {
  if (!value) {
    return callback(new Error('请输入关键词'));
  } else {
    callback();
  }
}

function checkSearchTermType(rule: any, value: any, callback: any) {
  if (!value) {
    callback(new Error('请选择关键词类型'));
  } else {
    callback();
  }
}

function submitForm(formEl: FormInstance | undefined) {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (valid) dialogVisible.value = false;
    addSearchTerm();
    formEl.resetFields();
  });
}

function resetForm(formEl: FormInstance | undefined) {
  if (!formEl) return;
  formEl.resetFields();
  dialogVisible.value = false;
}

/**
 * 上传文件
 * @param uploadRequest 上传请求
 */
async function handleCustomUpload(uploadRequest: any) {
  try {
    const { file } = uploadRequest;
    const response = await api.uploadFile(file);
    handleResponse(response);
    uploadRequest.onSuccess(response); // 通知 el-upload 上传成功
  } catch (error) {
    console.log('==Error==', error);
    uploadRequest.onError(error);
  }
}

/**
 * @description 替换文件并上传
 * @param files 文件列表
 */
function handleExceed(files: any) {
  upload.value!.clearFiles();
  const file = files[0] as UploadRawFile;
  file.uid = genFileId();
  upload.value!.handleStart(file);
  upload.value!.submit();
}

/**
 * 统一处理响应
 * @param response 后端返回的响应
 */
function handleResponse(response: any) {
  if (response.code === SUCCESS_CODE) {
    ElMessage.success({ message: response.msg, plain: true });
  } else if (response.code === WARNING_CODE) {
    ElMessage.warning({ message: response.msg, plain: true });
  } else {
    ElMessage.error({ message: response.msg, plain: true });
  }
}

function handleSort(col: any) {
  sortFields.value = col.prop;
  isAscending.value = col.order === 'ascending';
  fetchSearchTermList();
}
</script>

<template>
  <div v-loading="tableLoading" class="p-2.5" style="background-color: #f7f7f7">
    <!-- 筛选 -->
    <el-card body-class="flex justify-between gap-3.5" shadow="hover" style="border: none; margin-bottom: 10px">
      <div class="flex gap-7">
        <div>
          <span class="font-bold mr-2" style="color: #303133">词根:</span>
          <el-input
              v-model="searchTermFilter"
              :prefix-icon="Search"
              clearable
              placeholder="请输入词根"
              style="width: 240px"
              @change="fetchSearchTermList"></el-input>
        </div>
        <div>
          <span class="font-bold mr-2" style="color: #303133">词根类型:</span>
          <el-select v-model="searchTermTypeFilter" style="width: 200px" @change="fetchSearchTermList">
            <el-option label="全部" value="all"/>
            <el-option label="positive" value="positive"/>
            <el-option label="negative" value="negative"/>
            <el-option label="无词根类型" value="typeless"/>
          </el-select>
        </div>
      </div>
      <div class="flex gap-3.5">
        <el-button plain type="primary" @click="handleDialogVisible">
          <el-icon>
            <Plus/>
          </el-icon>
          添加词根
        </el-button>
        <!-- 想要不页面不跳动可以加72的高度 -->
        <div>
          <el-upload
              ref="upload"
              :auto-upload="true"
              :http-request="handleCustomUpload"
              :limit="1"
              :on-exceed="handleExceed"
              action="#">
            <template #trigger>
              <el-button :icon="Upload" plain round type="warning">批量词根上传</el-button>
            </template>
          </el-upload>
        </div>
      </div>
    </el-card>
    <!-- 表格 -->
    <el-card shadow="hover" style="border: none">
      <div>
        <el-table :data="tableData" @sort-change="handleSort" height="600" stripe style="width: 100%">
          <el-table-column align="center" type="index" width="60">
            <template #header>
              <span>序号</span>
            </template>
          </el-table-column>
          <el-table-column align="center" label="添加日期" prop="add_date" sortable="custom">
            <template #header>
              <el-icon style="top: 2px; margin-right: 3px">
                <Calendar/>
              </el-icon>
              <span>添加日期</span>
            </template>
            <template #default="{ row }">
              <span class="font-medium">{{ row.add_date }}</span>
            </template>
          </el-table-column>
          <el-table-column label="词根" prop="searchTerm" sortable="custom">
            <template #header>
              <el-icon style="top: 2px; right: 2px">
                <Key/>
              </el-icon>
              <span>词根</span>
            </template>
            <template #default="{ row }">
              <el-input v-if="row.isEditing" ref="searchTermInpRef" v-model="row.searchTerm" @change="updateSearchTerm(row)"/>
              <span v-else class="font-semibold">{{ row.searchTerm }}</span>
            </template>
          </el-table-column>
          <el-table-column label="词根类型" prop="searchTerm_type" sortable="custom">
            <template #header>
              <el-icon style="top: 2px; right: 2px">
                <Coin/>
              </el-icon>
              <span>词根类型</span>
            </template>
            <template #default="{ row }">
              <el-popconfirm
                  :visible="row.popConfirmVisible"
                  title="确定修改吗?"
                  @cancel="cancelUpdate(row)"
                  @confirm="updateSearchTermType(row)">
                <template #reference>
                  <el-select v-model="row.searchTerm_type" style="width: 150px" @change="showPopConfirm(row)">
                    <el-option label="positive" value="positive"/>
                    <el-option label="negative" value="negative"/>
                  </el-select>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" width="120">
            <template #header>
              <el-icon style="top: 2px; margin-right: 5px">
                <EditPen/>
              </el-icon>
              <span>操作</span>
            </template>
            <template #default="{ row }">
              <el-button v-if="!row.isEditing" link size="small" type="primary" @click="handleClick(row)"> 编辑</el-button>
              <el-button v-else link size="small" type="primary" @click="handleClick(row)"> 取消</el-button>
              <el-popconfirm title="确定删除吗?" @confirm="handleDelete(row)">
                <template #reference>
                  <el-button link size="small" type="danger">删除</el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="mt-3.5 flex justify-end">
        <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[20, 40, 50, 100]"
            :total="total"
            layout="prev, pager, next, sizes, total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"/>
      </div>
    </el-card>
  </div>

  <!-- 添加词根弹窗 -->
  <el-dialog v-model="dialogVisible" :before-close="handleClose" title="添加关键词" width="500">
    <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="auto" status-icon style="max-width: 600px">
      <el-form-item label="关键词" prop="searchTerm">
        <el-input ref="formSearchTermInpRef" v-model="ruleForm.searchTerm"/>
      </el-form-item>
      <el-form-item label="关键词类型" prop="searchTermType">
        <el-select v-model="ruleForm.searchTermType">
          <el-option label="positive" value="positive"/>
          <el-option label="negative" value="negative"/>
        </el-select>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="resetForm(ruleFormRef)">取消</el-button>
        <el-button type="primary" @click="submitForm(ruleFormRef)"> 确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped></style>
