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

import { nextTick, onMounted, reactive, ref } from 'vue';
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(10);

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 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,
  };
  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;
  }
}

/**
 * 更新关键词
 * @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 });
  }
}
</script>

<template>
  <div>
    <el-card v-loading="tableLoading" body-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"
              placeholder="请输入词根"
              clearable
              @change="fetchSearchTermList"
              :prefix-icon="Search"
              style="width: 240px"></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"
              action="#"
              :limit="1"
              :auto-upload="true"
              :on-exceed="handleExceed"
              :http-request="handleCustomUpload">
              <template #trigger>
                <el-button plain round type="warning" :icon="Upload">批量词根上传</el-button>
              </template>
            </el-upload>
          </div>
        </div>
      </el-card>
      <!-- 表格 -->
      <el-card shadow="hover" style="border: none">
        <div style="height: 535px; overflow: auto">
          <el-table :data="tableData" stripe style="width: 100%">
            <el-table-column fixed prop="add_date" label="添加日期" width="180" sortable>
              <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 prop="searchTerm" label="词根" sortable>
              <template #header>
                <el-icon style="top: 2px; right: 2px">
                  <Key />
                </el-icon>
                <span>词根</span>
              </template>
              <template #default="{ row }">
                <el-input ref="searchTermInpRef" v-if="row.isEditing" v-model="row.searchTerm" @change="updateSearchTerm(row)" />
                <span class="font-semibold" v-else>{{ row.searchTerm }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="searchTerm_type" label="词根类型" sortable>
              <template #header>
                <el-icon style="top: 2px; right: 2px">
                  <Coin />
                </el-icon>
                <span>词根类型</span>
              </template>
              <template #default="{ row }">
                <el-popconfirm
                  title="确定修改吗?"
                  @confirm="updateSearchTermType(row)"
                  @cancel="cancelUpdate(row)"
                  :visible="row.popConfirmVisible">
                  <template #reference>
                    <el-select v-model="row.searchTerm_type" @change="showPopConfirm(row)" style="width: 150px">
                      <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 link type="primary" size="small" @click="handleClick(row)" v-if="!row.isEditing"> 编辑</el-button>
                <el-button link type="primary" size="small" @click="handleClick(row)" v-else> 取消</el-button>
                <el-popconfirm title="确定删除吗?" @confirm="handleDelete(row)">
                  <template #reference>
                    <el-button link type="danger" size="small">删除</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="[10, 20, 30, 50]"
            layout="sizes, prev, pager, next"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange" />
        </div>
      </el-card>
    </el-card>
  </div>
  <!-- 添加词根弹窗 -->
  <el-dialog v-model="dialogVisible" title="添加关键词" width="500" :before-close="handleClose">
    <el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" status-icon :rules="rules" label-width="auto">
      <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>
