<script setup lang="tsx">
import { computed, nextTick, onActivated, reactive, ref } from 'vue';
import type { TableInstance } from 'element-plus';
import { ElTag } from 'element-plus';
import { useBoolean } from '@sa/hooks';
import { OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE } from '@/constants/dict';
import {
  fetchBatchDeleteObjectStatusModel,
  fetchDeleteObjectStatusModel,
  fetchGetObjectStatusModelPage
} from '@/service/api';
import { useAuth } from '@/hooks/business/auth';
import { useDict } from '@/hooks/business/dict';
import { useUIPaginatedTable } from '@/hooks/common/table';
import BusinessTableActionCell, { type BusinessTableAction } from '@/components/custom/business-table-action-cell';
import StateMachineOperateDialog from './modules/state-machine-operate-dialog.vue';
import StateMachineSearch from './modules/state-machine-search.vue';
import StateTransitionDialog from './modules/state-transition-dialog.vue';
import { formatDateTime, getBooleanLabel, getBooleanTagType, getStatusLabel, getStatusTagType } from './shared';

defineOptions({ name: 'StateMachineManage' });

function getInitSearchParams(): Api.Infra.ObjectStatusModelSearchParams {
  return {
    pageNo: 1,
    pageSize: 10,
    keyword: undefined,
    objectType: undefined,
    status: undefined,
    initialFlag: undefined,
    terminalFlag: undefined
  };
}

function transformPageResult(
  response: Awaited<ReturnType<typeof fetchGetObjectStatusModelPage>>,
  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
  };
}

const searchParams = reactive(getInitSearchParams());
const stateTableRef = ref<TableInstance>();
const checkedRowKeys = ref<string[]>([]);
const { getLabel: getObjectTypeLabel } = useDict(OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE);
const { hasAuth } = useAuth();

const canDeleteStateMachine = computed(() => hasAuth('infra:state-machine:delete'));
const canUpdateStateMachine = computed(() => hasAuth('infra:state-machine:update'));
const canManageStateTransition = computed(() => hasAuth('infra:state-transition:manage'));

function getStatusModelActions(row: Api.Infra.ObjectStatusModel): BusinessTableAction[] {
  const actions: BusinessTableAction[] = [];

  if (canManageStateTransition.value) {
    actions.push({
      key: 'transition',
      label: '状态流转',
      buttonType: 'primary',
      onClick: () => openTransitionDialog(row)
    });
  }

  if (canUpdateStateMachine.value) {
    actions.push({
      key: 'edit',
      label: '编辑',
      buttonType: 'primary',
      onClick: () => openEdit(row)
    });
  }

  if (canDeleteStateMachine.value) {
    actions.push({
      key: 'delete',
      label: '删除',
      buttonType: 'danger',
      onClick: () => handleDeleteAction(row)
    });
  }

  return actions;
}

const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagination } = useUIPaginatedTable({
  paginationProps: {
    currentPage: searchParams.pageNo,
    pageSize: searchParams.pageSize
  },
  api: () => fetchGetObjectStatusModelPage(searchParams),
  transform: response => transformPageResult(response, searchParams.pageNo ?? 1, searchParams.pageSize ?? 10),
  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: 'objectType',
      label: '对象类型',
      minWidth: 130,
      formatter: row => getObjectTypeLabel(row.objectType)
    },
    { prop: 'statusName', label: '状态名称', minWidth: 140, showOverflowTooltip: true },
    { prop: 'statusCode', label: '状态编码', minWidth: 160, showOverflowTooltip: true },
    {
      prop: 'status',
      label: '配置状态',
      width: 110,
      align: 'center',
      formatter: row => <ElTag type={getStatusTagType(row.status)}>{getStatusLabel(row.status)}</ElTag>
    },
    {
      prop: 'initialFlag',
      label: '初始状态',
      width: 110,
      align: 'center',
      formatter: row => <ElTag type={getBooleanTagType(row.initialFlag)}>{getBooleanLabel(row.initialFlag)}</ElTag>
    },
    {
      prop: 'terminalFlag',
      label: '终态',
      width: 90,
      align: 'center',
      formatter: row => <ElTag type={getBooleanTagType(row.terminalFlag)}>{getBooleanLabel(row.terminalFlag)}</ElTag>
    },
    {
      prop: 'allowEdit',
      label: '允许编辑主数据',
      width: 140,
      align: 'center',
      formatter: row => <ElTag type={getBooleanTagType(row.allowEdit)}>{getBooleanLabel(row.allowEdit)}</ElTag>
    },
    {
      prop: 'progressExcludedFlag',
      label: '不参与上层进度统计',
      width: 160,
      align: 'center',
      formatter: row => (
        <ElTag type={getBooleanTagType(row.progressExcludedFlag)}>{getBooleanLabel(row.progressExcludedFlag)}</ElTag>
      )
    },
    {
      prop: 'allowCreateProject',
      label: '允许新建项目',
      width: 130,
      align: 'center',
      formatter: row => (
        <ElTag type={getBooleanTagType(row.allowCreateProject)}>{getBooleanLabel(row.allowCreateProject)}</ElTag>
      )
    },
    {
      prop: 'allowCreateRequirement',
      label: '允许新增需求',
      width: 130,
      align: 'center',
      formatter: row => (
        <ElTag type={getBooleanTagType(row.allowCreateRequirement)}>
          {getBooleanLabel(row.allowCreateRequirement)}
        </ElTag>
      )
    },
    { 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 => formatDateTime(row.createTime)
    },
    {
      prop: 'operate',
      label: '操作',
      width: 220,
      align: 'center',
      fixed: 'right',
      formatter: row => {
        const actions = getStatusModelActions(row);

        if (!actions.length) {
          return <span>--</span>;
        }

        return <BusinessTableActionCell actions={actions} />;
      }
    }
  ]
});

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

const { bool: transitionVisible, setTrue: openTransitionModal, setFalse: closeTransitionModal } = useBoolean();
const transitionRow = ref<Api.Infra.ObjectStatusModel | null>(null);

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

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

function openTransitionDialog(item: Api.Infra.ObjectStatusModel) {
  transitionRow.value = item;
  openTransitionModal();
}

async function handleDelete(item: Api.Infra.ObjectStatusModel) {
  const { error } = await fetchDeleteObjectStatusModel(item.id);

  if (error) {
    return;
  }

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

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

  await handleDelete(row);
}

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

  const { error } = await fetchBatchDeleteObjectStatusModel(checkedRowKeys.value);

  if (error) {
    return;
  }

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

function handleSelectionChange(rows: Api.Infra.ObjectStatusModel[]) {
  checkedRowKeys.value = rows.map(item => item.id);
}

async function reloadStatusTable(page = searchParams.pageNo) {
  checkedRowKeys.value = [];
  await getDataByPage(page);
  await nextTick();
  stateTableRef.value?.clearSelection();
}

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

function handleSearch() {
  reloadStatusTable(1);
}

function handleSubmitted() {
  closeOperateModal();
  reloadStatusTable();
}

onActivated(() => {
  resetSearchParams();
});
</script>

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

    <ElCard class="flex-1-hidden card-wrapper" body-class="business-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="checkedRowKeys.length === 0"
            :loading="loading"
            @refresh="getData"
          >
            <template #default>
              <ElButton v-auth="'infra:state-machine:create'" plain type="primary" @click="openAdd">
                <template #icon>
                  <icon-ic-round-plus class="text-icon" />
                </template>
                新增
              </ElButton>
              <ElPopconfirm
                v-if="canDeleteStateMachine"
                title="确认删除选中的状态模型吗？"
                @confirm="handleBatchDelete"
              >
                <template #reference>
                  <ElButton type="danger" plain :disabled="checkedRowKeys.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="stateTableRef"
          v-loading="loading"
          height="100%"
          border
          row-key="id"
          :data="data"
          @selection-change="handleSelectionChange"
        >
          <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>

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

    <StateTransitionDialog
      v-model:visible="transitionVisible"
      :current-status="transitionRow"
      @update:visible="value => !value && closeTransitionModal()"
    />
  </div>
</template>

<style scoped></style>
