<script setup lang="tsx">
import { nextTick, reactive, ref } from 'vue';
import type { TableInstance } from 'element-plus';
import { ElButton, ElPopconfirm, ElTag } from 'element-plus';
import dayjs from 'dayjs';
import { useBoolean } from '@sa/hooks';
import { fetchBatchDeletePost, fetchDeletePost, fetchExportPost, fetchGetPostPage } from '@/service/api';
import { useUIPaginatedTable } from '@/hooks/common/table';
import BusinessTableActionCell from '@/components/custom/business-table-action-cell';
import { downloadBlob, getSystemExportFileName } from '@/views/system/shared/export';
import PostOperateDialog from './modules/post-operate-dialog.vue';
import PostSearch from './modules/post-search.vue';

defineOptions({ name: 'PostManage' });

function getInitSearchParams(): Api.SystemManage.PostSearchParams {
  return {
    pageNo: 1,
    pageSize: 10,
    name: undefined,
    code: undefined,
    postType: undefined,
    status: undefined
  };
}

function transformPageResult(response: Awaited<ReturnType<typeof fetchGetPostPage>>, pageNo: number, pageSize: number) {
  if (!response.error) {
    return {
      data: response.data.list,
      pageNum: pageNo,
      pageSize,
      total: response.data.total
    };
  }

  return {
    data: [],
    pageNum: pageNo,
    pageSize,
    total: 0
  };
}

function formatTime(value?: number | null) {
  if (!value) {
    return '--';
  }

  return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
}

function getStatusTagType(status: Api.SystemManage.CommonStatus): UI.ThemeColor {
  return status === 0 ? 'success' : 'warning';
}

function getStatusLabel(status: Api.SystemManage.CommonStatus) {
  return status === 0 ? '启用' : '停用';
}

function getPostTypeLabel(type?: Api.SystemManage.PostType | null) {
  if (!type) {
    return '--';
  }

  const postTypeLabelMap: Record<Api.SystemManage.PostType, string> = {
    management: '管理岗',
    technical: '技术岗',
    business: '业务岗'
  };

  return postTypeLabelMap[type];
}

const searchParams = reactive(getInitSearchParams());
const postTableRef = ref<TableInstance>();
const postCheckedRowKeys = ref<number[]>([]);
const exporting = ref(false);

const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagination } = useUIPaginatedTable({
  paginationProps: {
    currentPage: searchParams.pageNo,
    pageSize: searchParams.pageSize
  },
  api: () => fetchGetPostPage(searchParams),
  transform: response => transformPageResult(response, searchParams.pageNo, searchParams.pageSize),
  onPaginationParamsChange: params => {
    searchParams.pageNo = params.currentPage ?? 1;
    searchParams.pageSize = params.pageSize ?? 10;
  },
  columns: () => [
    { prop: 'selection', type: 'selection', width: 48 },
    { prop: 'index', type: 'index', label: '序号', width: 64 },
    { prop: 'name', label: '岗位名称', minWidth: 200, showOverflowTooltip: true },
    { prop: 'code', label: '岗位编码', minWidth: 330, showOverflowTooltip: true },
    {
      prop: 'postType',
      label: '岗位类型',
      width: 120,
      align: 'center',
      formatter: row => getPostTypeLabel(row.postType)
    },
    {
      prop: 'status',
      label: '岗位状态',
      width: 110,
      align: 'center',
      formatter: row => <ElTag type={getStatusTagType(row.status)}>{getStatusLabel(row.status)}</ElTag>
    },
    {
      prop: 'levelRank',
      label: '岗位职级',
      width: 100,
      align: 'center',
      formatter: row => String(row.levelRank ?? '--')
    },
    { prop: 'sort', label: '排序', width: 90, align: 'center' },
    {
      prop: 'remark',
      label: '备注',
      minWidth: 180,
      showOverflowTooltip: true,
      formatter: row => row.remark || '--'
    },
    {
      prop: 'createTime',
      label: '创建时间',
      minWidth: 170,
      formatter: row => formatTime(row.createTime)
    },
    {
      prop: 'operate',
      label: '操作',
      width: 196,
      align: 'center',
      fixed: 'right',
      formatter: row => (
        <BusinessTableActionCell
          actions={[
            {
              key: 'edit',
              label: '编辑',
              buttonType: 'primary',
              onClick: () => openEdit(row)
            },
            {
              key: 'delete',
              label: '删除',
              buttonType: 'danger',
              onClick: () => handleDeleteAction(row)
            }
          ]}
        />
      )
    }
  ]
});

const { bool: operateVisible, setTrue: openOperateModal, setFalse: closeOperateModal } = useBoolean();
const operateType = ref<UI.TableOperateType>('add');
const editingData = ref<Api.SystemManage.Post | null>(null);

function openAdd() {
  operateType.value = 'add';
  editingData.value = null;
  openOperateModal();
}

function openEdit(item: Api.SystemManage.Post) {
  operateType.value = 'edit';
  editingData.value = item;
  openOperateModal();
}

async function handleDelete(item: Api.SystemManage.Post) {
  const { error } = await fetchDeletePost(item.id);

  if (error) {
    return;
  }

  window.$message?.success('删除成功');

  await reloadPostTable();
}

async function handleDeleteAction(row: Api.SystemManage.Post) {
  try {
    await window.$messageBox?.confirm('确认删除当前岗位吗？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    });
  } catch {
    return;
  }

  await handleDelete(row);
}

async function handleBatchDelete() {
  if (!postCheckedRowKeys.value.length) {
    return;
  }

  const { error } = await fetchBatchDeletePost(postCheckedRowKeys.value);

  if (error) {
    return;
  }

  window.$message?.success('删除成功');
  await reloadPostTable();
}

function handlePostSelectionChange(rows: Api.SystemManage.Post[]) {
  postCheckedRowKeys.value = rows.map(item => item.id);
}

async function reloadPostTable(page = searchParams.pageNo) {
  postCheckedRowKeys.value = [];
  await getDataByPage(page);
  await nextTick();
  postTableRef.value?.clearSelection();
}

async function handleExport() {
  exporting.value = true;
  const { error, data: blob } = await fetchExportPost(searchParams);
  exporting.value = false;

  if (error || !blob) {
    return;
  }

  downloadBlob(blob, getSystemExportFileName('岗位数据'));
}

function resetSearchParams() {
  Object.assign(searchParams, getInitSearchParams());
  reloadPostTable(1);
}

function handleSearch() {
  reloadPostTable(1);
}

function handleSubmitted(postId: number) {
  closeOperateModal();
  reloadPostTable();
}
</script>

<template>
  <div class="flex-col-stretch gap-16px overflow-hidden">
    <PostSearch v-model:model="searchParams" @reset="resetSearchParams" @search="handleSearch" />

    <ElCard class="flex-1-hidden card-wrapper" body-class="post-table-card-body">
      <template #header>
        <div class="flex items-center justify-between gap-12px">
          <div class="flex items-center gap-10px">
            <p>岗位列表</p>
            <ElTag effect="plain">{{ mobilePagination.total || data.length }}</ElTag>
          </div>
          <TableHeaderOperation
            v-model:columns="columnChecks"
            :disabled-delete="true"
            :loading="loading"
            @refresh="reloadPostTable"
          >
            <template #default>
              <ElButton v-auth="'system:post:export'" plain type="primary" :loading="exporting" @click="handleExport">
                <template #icon>
                  <icon-mdi-download class="text-icon" />
                </template>
                导出
              </ElButton>
              <ElButton plain type="primary" @click="openAdd">
                <template #icon>
                  <icon-ic-round-plus class="text-icon" />
                </template>
                新增
              </ElButton>
              <ElPopconfirm title="确认删除选中的岗位吗？" @confirm="handleBatchDelete">
                <template #reference>
                  <ElButton type="danger" plain :disabled="postCheckedRowKeys.length === 0">
                    <template #icon>
                      <icon-ic-round-delete class="text-icon" />
                    </template>
                    批量删除
                  </ElButton>
                </template>
              </ElPopconfirm>
            </template>
          </TableHeaderOperation>
        </div>
      </template>

      <div class="flex-1">
        <ElTable
          ref="postTableRef"
          v-loading="loading"
          height="100%"
          border
          row-key="id"
          :data="data"
          @selection-change="handlePostSelectionChange"
        >
          <ElTableColumn v-for="col in columns" :key="String(col.prop)" v-bind="col" />
        </ElTable>
      </div>

      <div class="mt-20px flex justify-end">
        <ElPagination
          v-if="mobilePagination.total"
          layout="total,prev,pager,next,sizes"
          v-bind="mobilePagination"
          @current-change="mobilePagination['current-change']"
          @size-change="mobilePagination['size-change']"
        />
      </div>
    </ElCard>

    <PostOperateDialog
      v-model:visible="operateVisible"
      :operate-type="operateType"
      :row-data="editingData"
      @submitted="handleSubmitted"
    />
  </div>
</template>

<style lang="scss" scoped>
:deep(.post-table-card-body) {
  height: calc(100% - 56px);
  display: flex;
  flex-direction: column;
}
</style>
