<script setup lang="tsx">
import { reactive } from 'vue';
import { ElButton, ElTag } from 'element-plus';
import type { FlatResponseData } from '@sa/axios';
import { utils, writeFile } from 'xlsx';
import { commonStatusRecord, userGenderRecord } from '@/constants/business';
import { fetchGetUserList } from '@/service/api';
import { useUIPaginatedTable } from '@/hooks/common/table';
import { $t } from '@/locales';

defineOptions({ name: 'ExcelPage' });

const searchParams: Api.SystemManage.UserSearchParams = reactive({
  pageNo: 1,
  pageSize: 10,
  status: undefined,
  username: undefined,
  mobile: undefined,
  deptId: undefined,
  roleId: undefined
});

const { columns, data, loading } = useUIPaginatedTable<
  FlatResponseData<any, Api.SystemManage.UserList>,
  Api.SystemManage.User
>({
  api: () => fetchGetUserList(searchParams),
  transform: response => {
    if (!response.error) {
      return {
        data: response.data.list,
        pageNum: searchParams.pageNo ?? 1,
        pageSize: searchParams.pageSize ?? 10,
        total: response.data.total
      };
    }

    return {
      data: [],
      pageNum: 1,
      pageSize: 10,
      total: 0
    };
  },
  onPaginationParamsChange: params => {
    searchParams.pageNo = params.currentPage;
    searchParams.pageSize = params.pageSize;
  },
  columns: () => [
    { type: 'selection', width: 48 },
    { type: 'index', label: $t('common.index'), width: 64 },
    { prop: 'username', label: $t('page.system.user.userName'), minWidth: 100 },
    {
      prop: 'sex',
      label: $t('page.system.user.userGender'),
      width: 100,
      formatter: row => {
        const tagMap: Record<Api.SystemManage.UserGender, UI.ThemeColor> = {
          0: 'info',
          1: 'primary',
          2: 'danger'
        };
        const value = row.sex ?? 0;

        const label = $t(userGenderRecord[value]);

        return <ElTag type={tagMap[value]}>{label}</ElTag>;
      }
    },
    { prop: 'nickname', label: $t('page.system.user.nickName'), minWidth: 100 },
    { prop: 'mobile', label: $t('page.system.user.userPhone'), width: 120 },
    { prop: 'email', label: $t('page.system.user.userEmail'), minWidth: 200 },
    {
      prop: 'status',
      label: $t('page.system.user.userStatus'),
      width: 100,
      formatter: row => {
        const tagMap: Record<Api.SystemManage.CommonStatus, UI.ThemeColor> = {
          0: 'success',
          1: 'warning'
        };

        const label = $t(commonStatusRecord[row.status]);

        return <ElTag type={tagMap[row.status]}>{label}</ElTag>;
      }
    }
  ]
});

function exportExcel() {
  const exportColumns = columns.value.slice(2);

  const excelList = data.value.map(item => exportColumns.map(col => getTableValue(col, item)));

  const titleList = exportColumns.map(col => (isTableColumnHasTitle(col) && col.label) || undefined);

  excelList.unshift(titleList);

  const workBook = utils.book_new();

  const workSheet = utils.aoa_to_sheet(excelList);

  workSheet['!cols'] = exportColumns.map(item => ({
    width: Math.round(Number(item.width) / 10 || 20)
  }));

  utils.book_append_sheet(workBook, workSheet, '用户列表');

  writeFile(workBook, '用户数据.xlsx');
}

function getTableValue(col: UI.TableColumn<Api.SystemManage.User>, item: Api.SystemManage.User) {
  if (!isTableColumnHasKey(col)) {
    return '';
  }

  const { prop } = col;

  if (prop === 'operate' || prop === undefined) {
    return '';
  }

  if (prop === 'status') {
    return $t(commonStatusRecord[item.status]);
  }

  if (prop === 'sex') {
    return $t(userGenderRecord[item.sex ?? 0]);
  }

  if (prop in item) {
    return item[prop as keyof Api.SystemManage.User];
  }

  return '';
}

function isTableColumnHasKey<T>(column: UI.TableColumn<T>): boolean {
  return Boolean((column as UI.TableColumnWithKey<T>).prop);
}

function isTableColumnHasTitle<T>(column: UI.TableColumn<T>): boolean {
  return Boolean((column as UI.TableColumnWithKey<T>).label);
}
</script>

<template>
  <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
    <ElCard class="card-wrapper sm:flex-1-hidden">
      <template #header>
        <div class="flex items-center justify-between">
          <p>Excel导出</p>
          <ElButton plain type="primary" @click="exportExcel">
            <template #icon>
              <icon-file-icons:microsoft-excel class="text-icon" />
            </template>
            导出excel
          </ElButton>
        </div>
      </template>
      <div class="h-[calc(100%-50px)]">
        <ElTable v-loading="loading" height="100%" border class="sm:h-full" :data="data" row-key="id">
          <ElTableColumn v-for="col in columns" :key="col.prop" v-bind="col" />
        </ElTable>
      </div>
    </ElCard>
  </div>
</template>

<style scoped></style>
