<script setup lang="tsx">
import { computed, markRaw, onMounted, reactive, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import type { TableInstance } from 'element-plus';
import { ElButton, ElTag, ElTooltip } from 'element-plus';
import dayjs from 'dayjs';
import {
  RDMS_REQ_CAN_DELETE_STATUS_DICT_CODE,
  RDMS_REQ_CATEGORY_DICT_CODE,
  RDMS_REQ_PRIORITY_DICT_CODE
} from '@/constants/dict';
import { getStatusTagType } from '@/constants/status-tag';
import {
  fetchChangeRequirementStatus,
  fetchDeleteRequirement,
  fetchGetProductMembers,
  fetchGetProductRequirementDashboard,
  fetchGetProjectListByProductId,
  fetchGetRequirementAllowedTransitionsBatch,
  fetchGetRequirementStatusDict,
  fetchGetRequirementTree,
  fetchHasDispatchedProjectRequirementBatch
} from '@/service/api';
import { useAuth } from '@/hooks/business/auth';
import { useDict } from '@/hooks/business/dict';
import DictTag from '@/components/custom/dict-tag.vue';
import { useCurrentProduct } from '../shared/use-current-product';
import {
  ACTION_ICON_MAP,
  ACTION_TYPE_MAP,
  type RequirementStatusActionCode,
  getRequirementActionDisplayName,
  isRequirementActionNeedProject,
  isRequirementActionNeedReviewChoice,
  isRequirementActionTerminal
} from './shared/requirement-master-data';
import RequirementModuleTree from './modules/requirement-module-tree.vue';
import RequirementSearch from './modules/requirement-search.vue';
import RequirementCreateDialog from './modules/requirement-create-dialog.vue';
import RequirementDetailDialog from './modules/requirement-detail-dialog.vue';
import RequirementSplitDialog from './modules/requirement-split-dialog.vue';
import RequirementActionDialog from './modules/requirement-action-dialog.vue';
import RequirementReviewDialog from './modules/requirement-review-dialog.vue';
import RequirementReviewRecordDialog from './modules/requirement-review-record-dialog.vue';
import IconMdiSync from '~icons/mdi/sync';
import IconMdiEyeOutline from '~icons/mdi/eye-outline';
import IconMdiPencilOutline from '~icons/mdi/pencil-outline';

defineOptions({ name: 'ProductRequirement' });

const router = useRouter();
const { currentObjectId } = useCurrentProduct();
const { hasObjectAuth } = useAuth();

const statusDict = ref<Api.Product.RequirementStatusDict[]>([]);
const projectOptions = ref<Api.Project.Project[]>([]);

const statusOptions = computed(() => {
  return statusDict.value.map(item => ({
    label: item.statusName,
    value: item.statusCode
  }));
});

const statusMetaMap = computed(() => {
  return new Map(statusDict.value.map(item => [item.statusCode, item]));
});

const projectNameMap = computed(() => {
  return new Map(projectOptions.value.map(item => [item.id, item.projectName]));
});

const { hasValue: canDeleteStatusHasValue } = useDict(RDMS_REQ_CAN_DELETE_STATUS_DICT_CODE);

async function loadStatusOptions() {
  const { error, data } = await fetchGetRequirementStatusDict();

  if (error || !data) {
    statusDict.value = [];
    return;
  }

  statusDict.value = data;
}

async function loadProjectOptions() {
  if (!currentObjectId.value) {
    projectOptions.value = [];
    return;
  }

  const { error, data } = await fetchGetProjectListByProductId(currentObjectId.value);

  if (error || !data) {
    projectOptions.value = [];
    return;
  }

  projectOptions.value = data;
}

function getStatusLabel(statusCode: string) {
  const item = statusOptions.value.find(opt => opt.value === statusCode);
  return item ? item.label : statusCode;
}

const hasDispatchedMap = ref<Record<string, boolean>>({});

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

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

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

  return dayjs(value).format('YYYY-MM-DD');
}

function isTerminalStatus(statusCode: string) {
  return Boolean(statusMetaMap.value.get(statusCode)?.terminalFlag);
}

function canEditRequirement(row: Api.Product.Requirement) {
  return Boolean(statusMetaMap.value.get(row.statusCode)?.allowEdit);
}

function isReviewAction(row: Api.Product.Requirement, action: Api.Product.RequirementLifecycleAction) {
  return row.statusCode === 'pending_review' && ['pass_review', 'reject_review'].includes(action.actionCode);
}

function isReviewTransitionAction(actionCode: string) {
  return ['pass_review', 'reject_review'].includes(actionCode);
}

function canViewReviewRecord(row: Api.Product.Requirement) {
  return row.reviewRequired === 1 && !['pending_claim', 'pending_review'].includes(row.statusCode);
}

function canSplitRequirement(row: Api.Product.Requirement) {
  if (row.implementProjectId) {
    return false;
  }
  const hasDispatched = hasDispatchedMap.value[row.id];
  if (hasDispatched) {
    return false;
  }
  return ['pending_dispatch', 'reviewed', 'implementing'].includes(row.statusCode);
}

function canDeleteRequirement(row: Api.Product.Requirement) {
  const isStatusAllowed = canDeleteStatusHasValue(row.statusCode);
  const hasNoChildren = !row.children || row.children.length === 0;
  return isStatusAllowed && hasNoChildren;
}

const selectedModuleId = ref<string | undefined>('');
const memberOptions = ref<Api.Product.ProductMember[]>([]);
const requirementTableRef = ref<TableInstance>();
const loading = ref(false);
const treeData = ref<Api.Product.Requirement[]>([]);
const requirementDisplayTotal = ref(0);
const pagination = reactive({
  pageNo: 1,
  pageSize: 10,
  total: 0
});

const allowedTransitionsMap = ref<Map<string, Api.Product.RequirementLifecycleAction[]>>(new Map());

const searchParams = reactive({
  title: undefined as string | undefined,
  category: undefined as string | undefined,
  priority: undefined as Api.Product.RequirementPriority | undefined,
  statusCode: undefined as Api.Product.RequirementStatusCode | undefined,
  currentHandlerUserId: undefined as string | undefined,
  sourceBizCode: undefined as string | undefined
});

const createVisible = ref(false);
const detailVisible = ref(false);
const detailMode = ref<'view' | 'edit'>('view');
const selectedRequirement = ref<Api.Product.Requirement | null>(null);
const splitVisible = ref(false);
const splitParentRequirement = ref<Api.Product.Requirement | null>(null);

const actionVisible = ref(false);
const actionRequirement = ref<Api.Product.Requirement | null>(null);
const currentAction = ref<Api.Product.RequirementLifecycleAction | null>(null);
const reviewVisible = ref(false);
const reviewRequirement = ref<Api.Product.Requirement | null>(null);
const reviewRecordVisible = ref(false);
const reviewRecordRequirement = ref<Api.Product.Requirement | null>(null);

interface MemberUserOption {
  id: string;
  nickname: string;
  roleName: string;
}

const memberUserOptions = computed<MemberUserOption[]>(() => {
  return memberOptions.value
    .filter(m => m.status === 0)
    .map(m => ({
      id: m.userId,
      nickname: m.userNickname,
      roleName: m.roleName
    }));
});

const memberLabelMap = computed(() => {
  return new Map(memberUserOptions.value.map(item => [String(item.id), item.nickname]));
});

function getMemberLabel(userId?: string | null) {
  if (!userId) {
    return '--';
  }

  return memberLabelMap.value.get(String(userId)) || String(userId);
}

function flattenTree(nodes: Api.Product.Requirement[]): Api.Product.Requirement[] {
  const result: Api.Product.Requirement[] = [];
  for (const node of nodes) {
    result.push(node);
    if (node.children?.length) {
      result.push(...flattenTree(node.children));
    }
  }
  return result;
}

function collectRequirementIdsForActions(nodes: Api.Product.Requirement[]): string[] {
  const ids: string[] = [];
  for (const node of nodes) {
    const isTerminal = isTerminalStatus(node.statusCode);
    const hasDispatched = Boolean(node.implementProjectId);
    if (!isTerminal && !hasDispatched) {
      ids.push(node.id);
    }
    if (node.children?.length) {
      ids.push(...collectRequirementIdsForActions(node.children));
    }
  }
  return ids;
}

function collectRequirementIdsForSplitCheck(nodes: Api.Product.Requirement[]): string[] {
  const ids: string[] = [];
  for (const node of nodes) {
    if (!node.implementProjectId) {
      ids.push(node.id);
    }
    if (node.children?.length) {
      ids.push(...collectRequirementIdsForSplitCheck(node.children));
    }
  }
  return ids;
}

async function loadAllowedTransitionsForAll() {
  if (!currentObjectId.value) {
    allowedTransitionsMap.value = new Map();
    return;
  }

  const idsToQuery = collectRequirementIdsForActions(treeData.value);
  const newMap = new Map<string, Api.Product.RequirementLifecycleAction[]>();

  if (idsToQuery.length === 0) {
    allowedTransitionsMap.value = newMap;
    return;
  }

  const { error, data } = await fetchGetRequirementAllowedTransitionsBatch({
    productId: currentObjectId.value,
    requirementIds: idsToQuery
  });

  if (error || !data) {
    allowedTransitionsMap.value = newMap;
    return;
  }

  for (const item of data) {
    newMap.set(item.requirementId, item.transitions || []);
  }

  allowedTransitionsMap.value = newMap;
}

async function loadHasDispatchedForAll() {
  if (!currentObjectId.value) {
    hasDispatchedMap.value = {};
    return;
  }

  const idsToQuery = collectRequirementIdsForSplitCheck(treeData.value);
  const newMap: Record<string, boolean> = {};

  if (idsToQuery.length === 0) {
    hasDispatchedMap.value = newMap;
    return;
  }

  const { error, data } = await fetchHasDispatchedProjectRequirementBatch({
    productId: currentObjectId.value,
    requirementIds: idsToQuery
  });

  if (error || !data) {
    hasDispatchedMap.value = newMap;
    return;
  }

  for (const item of data) {
    newMap[item.requirementId] = Boolean(item.hasDispatched);
  }

  hasDispatchedMap.value = newMap;
}

function getRowActions(row: Api.Product.Requirement): Api.Product.RequirementLifecycleAction[] {
  return allowedTransitionsMap.value.get(row.id) || [];
}

const columns = computed(() => [
  {
    type: 'index',
    label: '序号',
    width: 64,
    align: 'center',
    index: (index: number): number => {
      const flatList = flattenTree(treeData.value);
      const row = flatList[index];
      if (!row || row.parentId !== '0') {
        return 0;
      }
      const parentIndex = treeData.value.findIndex(item => item.id === row.id);
      return parentIndex >= 0 ? (pagination.pageNo - 1) * pagination.pageSize + parentIndex + 1 : 0;
    }
  },
  {
    prop: 'title',
    label: '需求名称',
    minWidth: 200,
    className: 'requirement-title-column',
    formatter: (row: Api.Product.Requirement) => {
      return (
        <ElTooltip content={row.title} placement="top" show-after={300}>
          <span
            class="requirement-title"
            role="button"
            tabindex={0}
            onClick={() => openView(row)}
            onKeydown={event => {
              if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                openView(row);
              }
            }}
          >
            {row.title}
          </span>
        </ElTooltip>
      );
    }
  },
  {
    prop: 'priority',
    label: '优先级',
    width: 75,
    align: 'center',
    formatter: (row: Api.Product.Requirement) => <DictTag dictCode={RDMS_REQ_PRIORITY_DICT_CODE} value={row.priority} />
  },
  {
    prop: 'statusCode',
    label: '状态',
    width: 100,
    align: 'center',
    formatter: (row: Api.Product.Requirement) => (
      <ElTag type={getStatusTagType('productRequirement', row.statusCode)}>{getStatusLabel(row.statusCode)}</ElTag>
    )
  },
  {
    prop: 'category',
    label: '需求类型',
    minWidth: 80,
    formatter: (row: Api.Product.Requirement) => row.category
  },
  // {
  //   prop: 'sourceType',
  //   label: '需求来源',
  //   minWidth: 80,
  //   align: 'center',
  //   formatter: (row: Api.Product.Requirement) => (
  //     <DictText dictCode={RDMS_REQ_SOURCE_TYPE_DICT_CODE} value={row.sourceType} />
  //   )
  // },
  // {
  //   prop: 'description',
  //   label: '内容',
  //   minWidth: 200,
  //   showOverflowTooltip: true,
  //   formatter: (row: Api.Product.Requirement) => {
  //     return row.description?.replace(/<[^>]+>/g, '').trim() || '--';
  //   }
  // },
  {
    prop: 'proposerNickname',
    label: '提出人',
    minWidth: 85,
    formatter: (row: Api.Product.Requirement) => row.proposerNickname || '--'
  },
  {
    prop: 'currentHandlerUserId',
    label: '负责人',
    minWidth: 85,
    formatter: (row: Api.Product.Requirement) => getMemberLabel(row.currentHandlerUserId)
  },
  {
    prop: 'sourceBizCode',
    label: '来源业务编号',
    minWidth: 140,
    formatter: (row: Api.Product.Requirement) => {
      if (!row.sourceBizCode) {
        return '--';
      }

      return row.sourceBizCode;
    }
  },
  {
    prop: 'implementProjectId',
    label: '关联项目',
    minWidth: 180,
    formatter: (row: Api.Product.Requirement) => {
      if (!row.implementProjectId) return '--';
      return projectNameMap.value.get(row.implementProjectId) || row.implementProjectName || '--';
    }
  },
  {
    prop: 'expectedTime',
    label: '预期完成时间',
    minWidth: 120,
    align: 'center',
    formatter: (row: Api.Product.Requirement) => formatDate(row.expectedTime)
  },
  {
    prop: 'createTime',
    label: '创建时间',
    minWidth: 120,
    formatter: (row: Api.Product.Requirement) => formatDateTime(row.createTime)
  },
  {
    prop: 'operate',
    label: '操作',
    width: 200,
    align: 'center',
    fixed: 'right',
    formatter: (row: Api.Product.Requirement) => {
      const actions: {
        key: string;
        label: string;
        icon: object;
        type: 'primary' | 'success' | 'danger';
        disabled?: boolean;
        onClick: () => void;
      }[] = [];

      if (hasObjectAuth('project:product:requirement:query') && canViewReviewRecord(row)) {
        actions.push({
          key: 'reviewRecord',
          label: '查看评审记录',
          icon: markRaw(IconMdiEyeOutline),
          type: 'primary',
          onClick: () => handleViewReviewRecord(row)
        });
      }

      if (hasObjectAuth('project:product:requirement:split') && canSplitRequirement(row)) {
        actions.push({
          key: 'split',
          label: '拆分',
          icon: ACTION_ICON_MAP.split,
          type: ACTION_TYPE_MAP.split,
          onClick: () => openSplit(row)
        });
      }

      if (hasObjectAuth('project:product:requirement:update') && canEditRequirement(row)) {
        actions.push({
          key: 'edit',
          label: '编辑',
          icon: ACTION_ICON_MAP.edit,
          type: ACTION_TYPE_MAP.edit,
          onClick: () => openEdit(row)
        });
      }

      if (row.implementProjectId) {
        actions.push({
          key: 'forward',
          label: '跳转',
          icon: ACTION_ICON_MAP.forward,
          type: 'primary',
          onClick: () => handleForwardToProjectRequirement(row)
        });
      }

      const lifecycleActions = getRowActions(row);
      const hasReviewAuth = hasObjectAuth('project:product:requirement:review');
      const hasStatusAuth = hasObjectAuth('project:product:requirement:status');

      if (hasReviewAuth && lifecycleActions.some(action => isReviewAction(row, action))) {
        actions.push({
          key: 'review',
          label: '评审',
          icon: ACTION_ICON_MAP.pass_review,
          type: 'primary',
          onClick: () => openReview(row)
        });
      }

      if (hasStatusAuth) {
        const nonTerminalActions: Api.Product.RequirementLifecycleAction[] = [];
        const terminalActions: Api.Product.RequirementLifecycleAction[] = [];

        for (const action of lifecycleActions.filter(item => !isReviewTransitionAction(item.actionCode))) {
          const code = action.actionCode as RequirementStatusActionCode;
          if (isRequirementActionTerminal(code)) {
            terminalActions.push(action);
          } else {
            nonTerminalActions.push(action);
          }
        }

        for (const action of [...nonTerminalActions, ...terminalActions]) {
          actions.push({
            key: `action-${action.actionCode}`,
            label: getRequirementActionDisplayName(action),
            icon: ACTION_ICON_MAP[action.actionCode] ?? markRaw(IconMdiSync),
            type: ACTION_TYPE_MAP[action.actionCode] ?? 'primary',
            onClick: () => handleActionClick(row, action)
          });
        }
      }

      if (canDeleteRequirement(row) && hasObjectAuth('project:product:requirement:delete')) {
        actions.push({
          key: 'delete',
          label: '删除',
          icon: ACTION_ICON_MAP.delete,
          type: ACTION_TYPE_MAP.delete,
          onClick: () => handleDelete(row)
        });
      }

      return (
        <div class="requirement-action-cell" onClick={event => event.stopPropagation()}>
          {actions.length === 0 ? (
            <ElButton link size="small" class="requirement-action-icon-btn" type="primary" disabled>
              <IconMdiPencilOutline class="text-15px" />
            </ElButton>
          ) : (
            actions.map(action => {
              const IconComponent = action.icon as any;
              return (
                <ElTooltip key={action.key} content={action.label} placement="top">
                  <ElButton
                    link
                    size="small"
                    class="requirement-action-icon-btn"
                    type={action.type}
                    disabled={action.disabled}
                    onClick={() => action.onClick()}
                  >
                    <IconComponent class="text-15px" />
                  </ElButton>
                </ElTooltip>
              );
            })
          )}
        </div>
      );
    }
  }
]);

const columnChecks = ref<UI.TableColumnCheck[]>([]);

watch(
  () => columns.value,
  cols => {
    const existingMap = new Map(columnChecks.value.map(c => [c.prop, c.checked]));
    columnChecks.value = cols
      .filter(col => col.prop && col.prop !== 'operate')
      .map(col => ({
        prop: String(col.prop),
        label: String(col.label || ''),
        checked: existingMap.has(String(col.prop)) ? existingMap.get(String(col.prop))! : true,
        visible: true
      }));
  },
  { immediate: true }
);

const visibleColumns = computed(() => {
  if (columnChecks.value.length === 0) return columns.value;
  const visibleSet = new Set(columnChecks.value.filter(c => c.checked).map(c => c.prop));
  return columns.value.filter(col => {
    const prop = String(col.prop || '');
    if (!prop) return true;
    if (prop === 'operate') return true;
    return visibleSet.has(prop);
  });
});

async function loadMembers() {
  if (!currentObjectId.value) {
    memberOptions.value = [];
    return;
  }

  const { error, data: members } = await fetchGetProductMembers(currentObjectId.value);

  if (error || !members) {
    memberOptions.value = [];
    return;
  }

  memberOptions.value = members;
}

async function loadTreeData() {
  if (!currentObjectId.value) {
    treeData.value = [];
    pagination.total = 0;
    return;
  }

  const { error, data } = await fetchGetRequirementTree({
    productId: currentObjectId.value,
    moduleId: selectedModuleId.value,
    pageNo: pagination.pageNo,
    pageSize: pagination.pageSize,
    title: searchParams.title,
    category: searchParams.category,
    priority: searchParams.priority,
    statusCode: searchParams.statusCode,
    currentHandlerUserId: searchParams.currentHandlerUserId,
    sourceBizCode: searchParams.sourceBizCode?.trim() || undefined
  });

  if (error || !data) {
    treeData.value = [];
    pagination.total = 0;
    return;
  }

  treeData.value = data.list;
  pagination.total = data.total;
}

async function loadRequirementDisplayTotal() {
  if (!currentObjectId.value) {
    requirementDisplayTotal.value = 0;
    return;
  }

  const { error, data } = await fetchGetProductRequirementDashboard(currentObjectId.value);

  if (error || !data) {
    requirementDisplayTotal.value = pagination.total;
    return;
  }

  requirementDisplayTotal.value = data.summary.total;
}

async function reloadTable() {
  loading.value = true;
  try {
    await loadTreeData();
    await Promise.all([loadAllowedTransitionsForAll(), loadHasDispatchedForAll(), loadRequirementDisplayTotal()]);
  } finally {
    loading.value = false;
  }
}

function handleModuleSelect(moduleId: string | undefined) {
  selectedModuleId.value = moduleId;
  pagination.pageNo = 1;
  reloadTable();
}

function handleSearch() {
  pagination.pageNo = 1;
  reloadTable();
}

function handleResetSearch() {
  searchParams.title = undefined;
  searchParams.category = undefined;
  searchParams.priority = undefined;
  searchParams.statusCode = undefined;
  searchParams.currentHandlerUserId = undefined;
  searchParams.sourceBizCode = undefined;
  pagination.pageNo = 1;
  reloadTable();
}

function handlePageChange(page: number) {
  pagination.pageNo = page;
  reloadTable();
}

function handleSizeChange(size: number) {
  pagination.pageNo = 1;
  pagination.pageSize = size;
  reloadTable();
}

function openCreate() {
  selectedRequirement.value = null;
  createVisible.value = true;
}

function openView(row: Api.Product.Requirement) {
  selectedRequirement.value = row;
  detailMode.value = 'view';
  detailVisible.value = true;
}

function openEdit(row: Api.Product.Requirement) {
  selectedRequirement.value = row;
  detailMode.value = 'edit';
  detailVisible.value = true;
}

function openSplit(row: Api.Product.Requirement) {
  splitParentRequirement.value = row;
  splitVisible.value = true;
}

function openReview(row: Api.Product.Requirement) {
  reviewRequirement.value = row;
  reviewVisible.value = true;
}

function handleViewReviewRecord(row: Api.Product.Requirement) {
  if (!canViewReviewRecord(row)) {
    return;
  }

  reviewRecordRequirement.value = row;
  reviewRecordVisible.value = true;
}

async function handleForwardToProjectRequirement(row: Api.Product.Requirement) {
  if (!row.implementProjectId) return;

  await router.replace({
    path: '/project/project/requirement',
    query: {
      objectId: row.implementProjectId
    }
  });
}

function handleActionClick(row: Api.Product.Requirement, action: Api.Product.RequirementLifecycleAction) {
  const actionCode = action.actionCode as RequirementStatusActionCode;

  if (
    !isRequirementActionNeedReviewChoice(actionCode) &&
    !isRequirementActionNeedProject(actionCode) &&
    !action.needReason
  ) {
    handleDirectAction(row, action);
    return;
  }

  actionRequirement.value = row;
  currentAction.value = action;
  actionVisible.value = true;
}

async function handleDirectAction(row: Api.Product.Requirement, action: Api.Product.RequirementLifecycleAction) {
  if (!currentObjectId.value) return;

  try {
    await window.$messageBox?.confirm(`确定要执行"${action.actionName}"操作吗？`, '确认操作', {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'info'
    });
  } catch {
    return;
  }

  const { error } = await fetchChangeRequirementStatus({
    id: row.id,
    productId: currentObjectId.value,
    actionCode: action.actionCode
  });

  if (error) {
    return;
  }

  window.$message?.success(`${action.actionName}成功`);
  await reloadTable();
}

async function handleActionSubmitted(payload: { actionCode: string; reason?: string; implementProjectId?: string }) {
  if (!currentObjectId.value || !actionRequirement.value) return;

  const { error } = await fetchChangeRequirementStatus({
    id: actionRequirement.value.id,
    productId: currentObjectId.value,
    actionCode: payload.actionCode,
    reason: payload.reason,
    implementProjectId: payload.implementProjectId
  });

  if (error) {
    return;
  }

  window.$message?.success('操作成功');
  actionVisible.value = false;
  await reloadTable();
}

async function handleDelete(row: Api.Product.Requirement) {
  if (!currentObjectId.value) return;

  try {
    await window.$messageBox?.confirm('确定要删除该需求吗？删除后不可恢复。', '删除确认', {
      confirmButtonText: '确认删除',
      cancelButtonText: '取消',
      type: 'warning'
    });
  } catch {
    return;
  }

  const { error } = await fetchDeleteRequirement({
    id: row.id,
    productId: currentObjectId.value
  });

  if (error) {
    return;
  }

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

async function handleCreateSubmitted() {
  createVisible.value = false;
  await reloadTable();
}

async function handleDetailSubmitted() {
  detailVisible.value = false;
  await reloadTable();
}

async function handleSplitSubmitted() {
  splitVisible.value = false;
  await reloadTable();
}

async function handleReviewSubmitted() {
  reviewVisible.value = false;
  await reloadTable();
}

watch(
  () => currentObjectId.value,
  async id => {
    if (id) {
      await Promise.all([loadMembers(), loadTreeData(), loadProjectOptions()]);
      await Promise.all([loadAllowedTransitionsForAll(), loadHasDispatchedForAll(), loadRequirementDisplayTotal()]);
    } else {
      memberOptions.value = [];
      treeData.value = [];
      projectOptions.value = [];
      allowedTransitionsMap.value = new Map();
      requirementDisplayTotal.value = 0;
    }
  },
  { immediate: true }
);

onMounted(async () => {
  await loadStatusOptions();
});
</script>

<template>
  <div
    class="min-h-560px gap-16px overflow-hidden xl:grid xl:grid-cols-[280px_minmax(0,1fr)] lt-xl:flex lt-xl:flex-col lt-xl:overflow-auto"
  >
    <div class="flex-col-stretch gap-16px xl:min-h-0">
      <RequirementModuleTree :requirement-tree="treeData" @select="handleModuleSelect" @refresh="reloadTable" />
    </div>

    <div class="flex-col-stretch gap-16px xl:min-h-0">
      <RequirementSearch
        v-model:model="searchParams"
        :member-options="memberUserOptions"
        :category-dict-code="RDMS_REQ_CATEGORY_DICT_CODE"
        :priority-dict-code="RDMS_REQ_PRIORITY_DICT_CODE"
        @reset="handleResetSearch"
        @search="handleSearch"
      />

      <ElCard class="card-wrapper xl:flex-1-hidden" body-class="requirement-table-card-body">
        <template #header>
          <div class="flex items-center justify-between gap-12px">
            <div class="flex flex-wrap items-center gap-8px">
              <p>需求列表</p>
              <ElTag effect="plain">{{ requirementDisplayTotal }} 条</ElTag>
            </div>
            <TableHeaderOperation v-model:columns="columnChecks" :loading="loading" @refresh="reloadTable">
              <template #default>
                <ElButton
                  v-auth="{ code: 'project:product:requirement:create', source: 'object' }"
                  plain
                  type="primary"
                  @click="openCreate"
                >
                  <template #icon>
                    <icon-ic-round-plus class="text-icon" />
                  </template>
                  新增
                </ElButton>
              </template>
            </TableHeaderOperation>
          </div>
        </template>

        <div class="flex-1">
          <ElTable
            ref="requirementTableRef"
            v-loading="loading"
            border
            lazy
            row-key="id"
            :indent="32"
            height="100%"
            :data="treeData"
            :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
          >
            <ElTableColumn v-for="col in visibleColumns" :key="String(col.prop || 'index')" v-bind="col" />

            <template #empty>
              <ElEmpty description="当前模块下暂无需求" />
            </template>
          </ElTable>
        </div>

        <div class="mt-16px flex justify-end">
          <ElPagination
            v-model:current-page="pagination.pageNo"
            v-model:page-size="pagination.pageSize"
            :total="pagination.total"
            :page-sizes="[10, 15, 20, 25, 30]"
            layout="total, sizes, prev, pager, next, jumper"
            @current-change="handlePageChange"
            @size-change="handleSizeChange"
          />
        </div>
      </ElCard>
    </div>

    <RequirementCreateDialog
      v-model:visible="createVisible"
      :product-id="currentObjectId || ''"
      :default-module-id="selectedModuleId"
      :member-options="memberOptions"
      :category-dict-code="RDMS_REQ_CATEGORY_DICT_CODE"
      :priority-dict-code="RDMS_REQ_PRIORITY_DICT_CODE"
      @submitted="handleCreateSubmitted"
    />

    <RequirementDetailDialog
      v-model:visible="detailVisible"
      :mode="detailMode"
      :requirement="selectedRequirement"
      :product-id="currentObjectId || ''"
      :member-options="memberOptions"
      :category-dict-code="RDMS_REQ_CATEGORY_DICT_CODE"
      :priority-dict-code="RDMS_REQ_PRIORITY_DICT_CODE"
      @submitted="handleDetailSubmitted"
    />

    <RequirementSplitDialog
      v-model:visible="splitVisible"
      :parent-requirement="splitParentRequirement"
      :product-id="currentObjectId || ''"
      :member-options="memberOptions"
      :category-dict-code="RDMS_REQ_CATEGORY_DICT_CODE"
      :priority-dict-code="RDMS_REQ_PRIORITY_DICT_CODE"
      @submitted="handleSplitSubmitted"
    />

    <RequirementActionDialog
      v-model:visible="actionVisible"
      :action="currentAction"
      :requirement-title="actionRequirement?.title || ''"
      :project-options="projectOptions"
      @submitted="handleActionSubmitted"
    />

    <RequirementReviewDialog
      v-model:visible="reviewVisible"
      :product-id="currentObjectId || ''"
      :requirement="reviewRequirement"
      :member-options="memberOptions"
      @submitted="handleReviewSubmitted"
    />

    <RequirementReviewRecordDialog
      v-model:visible="reviewRecordVisible"
      :product-id="currentObjectId || ''"
      :requirement="reviewRecordRequirement"
      :member-options="memberOptions"
    />
  </div>
</template>

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

:deep(.requirement-title) {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  font-weight: 500;
  color: var(--el-color-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.5;
  vertical-align: middle;
  cursor: pointer;
}

:deep(.requirement-title-column .cell) {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  min-width: 0;
}

:deep(.requirement-title:hover) {
  text-decoration: underline;
}

:deep(.requirement-title--terminal) {
  padding: 0;
  text-decoration: line-through;
  opacity: 0.6;
}

:deep(.el-table__row[class*='el-table__row--level-']:not(.el-table__row--level-0) td:first-child .cell) {
  color: transparent;
}

:deep(.requirement-action-cell) {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

:deep(.requirement-action-cell .el-button + .el-button) {
  margin-left: 0;
}

:deep(.requirement-action-icon-btn) {
  padding: 3px;
  height: auto;
  min-width: auto;
  line-height: 1;
}

:deep(.requirement-action-icon-btn:hover) {
  background-color: var(--el-fill-color-light);
}
</style>
