import React, { useState, useEffect, useCallback, useRef } from 'react';
import { type MetaFunction, type LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData, useSearchParams, Link, useNavigate, useFetcher, useLocation } from "@remix-run/react";
import { Button } from '~/components/ui/Button';
import { Card } from '~/components/ui/Card';
import { Tag } from '~/components/ui/Tag';
import { StatusDot } from '~/components/ui/StatusDot';
import { Switch } from '~/components/ui/Switch';
import { TableRowSkeleton, LoadingIndicator, NumberSkeleton } from '~/components/ui/SkeletonScreen';
import rulesStyles from "~/styles/pages/rules_index.css?url";
import type { Rule, RuleType, RulePriority } from '~/models/rule';
import { RULE_PRIORITY_LABELS, RULE_PRIORITY_COLORS } from '~/models/rule';
import type { TagColor } from '~/components/ui/Tag';
import { Table } from '~/components/ui/Table';
import { FilterPanel, FilterSelect, SearchFilter } from '~/components/ui/FilterPanel';
import { Pagination } from '~/components/ui/Pagination';
import { messageService } from '~/components/ui/MessageModal';
import { toastService } from '~/components/ui/Toast';
import { usePermission } from '~/hooks/usePermission';
import {
  getRulesList,
  deleteRule,
  getRuleTypes,
  getRuleGroupsByType,
  getAttributeTypes,
  batchUpdateRuleStatus,
  batchDeleteRules,
  updateEvaluationPoint,
  type RuleType as ApiRuleType,
  type RuleGroup,
  type AttributeTypeOption
} from '~/api/evaluation_points/rules';
import { CONTRACT_TYPES } from '~/constants/contractTypes';

export const links = () => [
  { rel: "stylesheet", href: rulesStyles }
];


export const meta: MetaFunction = () => {
  return [
    { title: "中国烟草AI合同及卷宗审核系统 - 评查点列表" },
    { name: "rules", content: "管理评查点规则，支持根据类型、规则组和状态进行筛选" },
    { name: "keywords", content: "评查点,合同审核,规则管理,中国烟草" }
  ];
};

// export const handle = {
//   breadcrumb: "评查点列表"
// };

// 声明loader返回的数据类型
export type LoaderData = {
  rules: Rule[];
  totalCount: number;
  currentPage: number;
  pageSize: number;
  totalPages: number;
  ruleTypes: ApiRuleType[]; // 添加评查点类型
  initialLoad?: boolean; // 添加初始加载标志
};

// API返回的数据映射到前端模型
interface ApiRule {
  id: string;
  code: string;
  name: string;
  ruleType: string;
  groupId: string;
  groupName: string;
  priority: string;
  description: string;
  isActive: boolean;
  area?: string; // 地区
  documentAttributeType?: string; // 文档属性类型
  createdAt: string;
  updatedAt: string;
}

interface ActionResponse {
  result: boolean;
  message: string;
}

type SubtypeOption = {
  code: string;
  label: string;
};

const ADMIN_LICENSE_SUBTYPE_OPTIONS: SubtypeOption[] = [
  { code: '新办', label: '新办' },
  { code: '变更', label: '变更' },
  { code: '延续', label: '延续' },
  { code: '停业', label: '停业' },
  { code: '歇业', label: '歇业' },
  { code: '补办', label: '补办' },
  { code: '恢复营业', label: '恢复营业' },
  { code: '收回', label: '收回' },
  { code: '注销', label: '注销' }
];

const CONTRACT_SUBTYPE_OPTIONS: SubtypeOption[] = CONTRACT_TYPES.map(type => ({
  code: type.value === '通用' ? '通用' : type.label,
  label: type.label
}));
const SUBTYPE_DISCOVERY_PAGE_SIZE = 100;

function uniqueOptions(options: SubtypeOption[]): SubtypeOption[] {
  const seen = new Set<string>();
  return options.filter(option => {
    if (!option.code || seen.has(option.code)) {
      return false;
    }
    seen.add(option.code);
    return true;
  });
}

function matchesOption(option: AttributeTypeOption, target: SubtypeOption): boolean {
  return [option.code, option.label].some(value =>
    value === target.code ||
    value === target.label ||
    value.replace(/合同$/, '') === target.code ||
    target.label.replace(/合同$/, '') === value
  );
}

function normalizeSubtypeCode(value: string | undefined, options: SubtypeOption[]): string | undefined {
  if (!value) {
    return undefined;
  }

  const matchedOption = options.find(option =>
    option.code === value ||
    option.label === value ||
    option.label.replace(/合同$/, '') === value
  );

  return matchedOption?.code || value;
}

function matchRuleTypeByName(ruleTypes: ApiRuleType[], ruleTypeName?: string | null): ApiRuleType | undefined {
  if (!ruleTypeName) {
    return undefined;
  }

  return ruleTypes.find(type =>
    type.name === ruleTypeName ||
    type.name.includes(ruleTypeName) ||
    ruleTypeName.includes(type.name)
  );
}

function resolveCurrentRuleTypeId(
  ruleTypes: ApiRuleType[],
  ruleTypeId?: string | null,
  ruleTypeName?: string | null
): string | undefined {
  if (ruleTypeId && ruleTypeId !== 'all') {
    return ruleTypeId;
  }

  return matchRuleTypeByName(ruleTypes, ruleTypeName)?.id || ruleTypes[0]?.id;
}

function resolveScopedSubtypeOptions(
  params: {
    documentTypeIds: number[];
    selectedModuleName: string;
    ruleTypeName?: string | null;
    apiOptions: AttributeTypeOption[];
    ruleOptions: SubtypeOption[];
  }
): SubtypeOption[] {
  const { documentTypeIds, selectedModuleName, ruleTypeName, apiOptions, ruleOptions } = params;
  const isContractModule = selectedModuleName.includes('合同') || documentTypeIds.includes(1);
  const isCaseFileModule = selectedModuleName.includes('案卷') || selectedModuleName.includes('卷宗') || documentTypeIds.includes(2) || documentTypeIds.includes(3);

  if (isContractModule) {
    const apiContractOptions = CONTRACT_SUBTYPE_OPTIONS.flatMap(target =>
      apiOptions
        .filter(option => matchesOption(option, target))
        .map(option => ({ code: option.code, label: option.label }))
    );

    return uniqueOptions(apiContractOptions);
  }

  if (isCaseFileModule && ruleTypeName?.includes('行政许可')) {
    const apiLicenseOptions = ADMIN_LICENSE_SUBTYPE_OPTIONS.flatMap(target =>
      apiOptions
        .filter(option => matchesOption(option, target))
        .map(option => ({ code: option.code, label: option.label }))
    );

    return uniqueOptions(apiLicenseOptions);
  }

  if (isCaseFileModule && ruleTypeName?.includes('行政处罚')) {
    const punishmentOptions = apiOptions
      .filter(option => option.code === '通用' || option.label === '通用')
      .map(option => ({ code: option.code, label: option.label }));

    return uniqueOptions(punishmentOptions.length > 0 ? punishmentOptions : [{ code: '通用', label: '通用' }]);
  }

  return uniqueOptions(ruleOptions);
}

function mapApiRuleToModel(apiRule: ApiRule): Rule {
  // 🔑 清洗评查点编码：移除最后一个 '--' 及其后面的字符
  // 例如：'code-mis--mz' --> 'code-mis', 'code-mbs--alsi--gz' --> 'code-mbs--alsi'
  let cleanedCode = apiRule.code;
  const lastDoubleHyphenIndex = cleanedCode.lastIndexOf('--');
  if (lastDoubleHyphenIndex !== -1) {
    cleanedCode = cleanedCode.substring(0, lastDoubleHyphenIndex);
  }

  return {
    id: apiRule.id,
    code: cleanedCode,
    name: apiRule.name,
    ruleType: apiRule.ruleType as RuleType, // 类型转换
    ruleGroupId: apiRule.groupId,
    groupName: apiRule.groupName,
    priority: apiRule.priority as RulePriority, // 类型转换
    description: apiRule.description,
    checkMethod: 'automatic', // 默认值
    prompt: apiRule.description, // 使用描述作为默认prompt
    isActive: apiRule.isActive,
    area: apiRule.area || '', // 地区
    documentAttributeType: apiRule.documentAttributeType || '', // 文档属性类型
    createdAt: apiRule.createdAt,
    updatedAt: apiRule.updatedAt
  };
}

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);

  // 从 URL 参数中提取查询条件
  const params = {
    page: parseInt(url.searchParams.get("page") || "1", 10),
    pageSize: parseInt(url.searchParams.get("pageSize") || "10", 10)
  };

  try {
    // 🔑 使用 handleServerAuth 包装，自动处理 token 过期
    const { handleServerAuth } = await import("~/utils/server-auth-handler");

    return handleServerAuth(async () => {
      // 获取用户会话信息
      const { getUserSession } = await import("~/api/login/auth.server");
      const { frontendJWT } = await getUserSession(request);

      // 返回初始空数据，客户端将根据 sessionStorage 中的 documentTypeIds 加载实际数据
      return Response.json({
        rules: [],
        totalCount: 0,
        currentPage: params.page,
        pageSize: params.pageSize,
        ruleTypes: [], // 服务端无法访问 sessionStorage，客户端加载
        initialLoad: true,
        frontendJWT
      }, {
        headers: {
          "Cache-Control": "max-age=60, s-maxage=180"
        }
      });
    }, url.pathname);

  } catch (error) {
    console.error('加载评查点列表失败:', error);
    return Response.json({
      error: error || '加载评查点列表失败',
      status: 500
    }, { status: 500 });
  }
}

export async function action({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  const formData = await request.formData();
  const _action = formData.get('_action');
  const ruleId = formData.get('ruleId');

  if (!ruleId) {
    return Response.json({ result: false, message: "缺少评查点ID" }, { status: 400 });
  }

  try {
    // 🔑 使用 handleServerAuth 包装，自动处理 token 过期
    const { handleServerAuth } = await import("~/utils/server-auth-handler");

    return handleServerAuth(async () => {
      // 获取用户会话信息
      const { getUserSession } = await import("~/api/login/auth.server");
      const { frontendJWT } = await getUserSession(request);

      if (_action === 'delete') {
        // 调用API删除评查点
        const deleteResponse = await deleteRule(ruleId as string, frontendJWT);

        if (deleteResponse.error) {
          return Response.json({ result: false, message: deleteResponse.error }, { status: deleteResponse.status || 500 });
        }

        return Response.json({ result: true, message: "评查点删除成功" }, { status: 200 });
      }

      return Response.json({ result: false, message: "未知操作" }, { status: 400 });
    }, url.pathname);

  } catch (error) {
    console.error('操作评查点失败:', error);
    return Response.json({ result: false, message: error instanceof Error ? error.message : "操作失败" }, { status: 500 });
  }
}


// 规则优先级的描述标签映射
const priorityLabels = {
  'high': '高',
  'medium': '中',
  'low': '低'
};

export default function RulesIndex() {
  const loaderData = useLoaderData<typeof loader>();
  const { rules: initialRules, totalCount: initialTotalCount, currentPage, pageSize, ruleTypes: initialRuleTypes, initialLoad } = loaderData;
  const [searchParams, setSearchParams] = useSearchParams();
  const navigate = useNavigate();
  const fetcher = useFetcher<ActionResponse>();
  const location = useLocation();

  // ✅ 使用权限 Hook
  const { canCreate, canUpdate, canDelete, canBatch, canView } = usePermission();
  const canCreateRule = canCreate('evaluation_point');
  const canUpdateRule = canUpdate('evaluation_point');
  const canDeleteRule = canDelete('evaluation_point');
  const canBatchRule = canBatch('evaluation_point');
  const canViewRule = canView('evaluation_point');

  // 状态管理
  const [ruleGroups, setRuleGroups] = useState<RuleGroup[]>([]);
  const [loadingGroups, setLoadingGroups] = useState(false);
  const [loading, setLoading] = useState(false);
  const [filteredRules, setFilteredRules] = useState<Rule[]>(initialRules);
  const [filteredTotalCount, setFilteredTotalCount] = useState<number>(initialTotalCount);
  const [ruleTypes, setRuleTypes] = useState<ApiRuleType[]>(initialRuleTypes);
  const [attributeTypes, setAttributeTypes] = useState<Array<{ code: string; label: string }>>([]);
  const [selectedModuleName, setSelectedModuleName] = useState('');
  const [moduleScopeReady, setModuleScopeReady] = useState(false);

  // 添加一个状态来跟踪是否执行了删除操作
  const [isDeleting, setIsDeleting] = useState(false);

  // 批量选择状态
  const [selectedIds, setSelectedIds] = useState<string[]>([]);

  // 跟踪单个评查点状态更新时的加载状态
  const [updatingStatusIds, setUpdatingStatusIds] = useState<Set<string>>(new Set());

  // 使用 ref 跟踪是否正在加载数据，避免重复加载
  const isLoadingRef = useRef(false);
  
  // 获取当前的ruleType值
  const ruleTypeParam = searchParams.get('ruleType');
  const ruleTypeNameParam = searchParams.get('ruleTypeName');
  const selectedRuleTypeId = resolveCurrentRuleTypeId(ruleTypes, ruleTypeParam, ruleTypeNameParam) || '';

  // 判断是否禁用规则组选择
  const isRuleGroupSelectDisabled = loadingGroups || !selectedRuleTypeId || ruleGroups.length === 0;
  
  // 在组件渲染时初始化状态
  // useEffect(() => {  
  //   setFilteredRules(initialRules);
  //   setFilteredTotalCount(initialTotalCount);
  //   setRuleTypes(initialRuleTypes);
  // }, [initialRules, initialTotalCount, initialRuleTypes]);

  // 使用useEffect监听loaderData.error变化并显示Toast
  useEffect(() => {
    if(loaderData.error) {
      toastService.error(loaderData.error);
    }
    // ❌ 不再检查 loaderData.ruleTypes，因为服务端永远返回空数组
    // 如果需要检查评查点类型数据，应该在 fetchData 完成后检查状态 ruleTypes
  }, [loaderData.error]);
  
  // 客户端数据加载函数
  const fetchData = useCallback(async () => {
    try {
      // 🔑 如果正在加载，避免重复调用
      if (isLoadingRef.current) {
        console.log('📋 [fetchData] 正在加载中，跳过重复调用');
        return;
      }

      // 🔑 从 sessionStorage 获取 documentTypeIds
      const typeIdsStr = typeof window !== 'undefined' ? sessionStorage.getItem('documentTypeIds') : null;
      const documentTypeIds = typeIdsStr ? JSON.parse(typeIdsStr) : null;
      const currentModuleName = typeof window !== 'undefined'
        ? sessionStorage.getItem('selectedModuleName') || ''
        : '';

      if (!documentTypeIds || documentTypeIds.length === 0) {
        console.warn('无法加载评查点数据：未找到 documentTypeIds');
        return;
      }

      isLoadingRef.current = true;

      // 🔑 从 localStorage 获取 user_info 中的 area
      let userArea: string | undefined = undefined;
      if (typeof window !== 'undefined') {
        try {
          const userInfoStr = localStorage.getItem('user_info');
          if (userInfoStr) {
            const userInfo = JSON.parse(userInfoStr);
            userArea = userInfo.area;
            console.log("📋 [fetchData] 从 localStorage 获取到用户地区:", userArea);
          }
        } catch (error) {
          console.error('解析 user_info 失败:', error);
        }
      }

      console.log("📋 [fetchData] 开始加载评查点数据, documentTypeIds:", documentTypeIds, "area:", userArea);
      setLoading(true);

      // 🔑 获取评查点类型（通过 documentTypeIds）
      let loadedRuleTypes: ApiRuleType[] = [];
      try {
        const typeResponse = await getRuleTypes(documentTypeIds, loaderData.frontendJWT);
        if (typeResponse.data) {
          loadedRuleTypes = typeResponse.data;
          setRuleTypes(loadedRuleTypes);
          // console.log("📋 [fetchData] 获取到评查点类型:", loadedRuleTypes);
        }
      } catch (error) {
        console.error('加载评查点类型失败:', error);
      }

      // 主类型筛选已从界面隐藏，未显式传参时默认使用当前模块的第一个主类型。
      const finalRuleType = resolveCurrentRuleTypeId(loadedRuleTypes, ruleTypeParam, ruleTypeNameParam);

      let apiAttributeTypes: AttributeTypeOption[] = [];
      try {
        const attributeTypesResponse = await getAttributeTypes(loaderData.frontendJWT);
        if (attributeTypesResponse.data) {
          apiAttributeTypes = attributeTypesResponse.data;
        }
      } catch (error) {
        console.error('加载子类型枚举失败:', error);
      }

      let effectiveAttributeType = searchParams.get('documentAttributeType') || undefined;
      const presetScopedAttributeTypes = resolveScopedSubtypeOptions({
        documentTypeIds,
        selectedModuleName: currentModuleName,
        ruleTypeName: ruleTypeNameParam,
        apiOptions: apiAttributeTypes,
        ruleOptions: []
      });

      if (presetScopedAttributeTypes.length > 0) {
        setAttributeTypes(presetScopedAttributeTypes);
        const originalAttributeType = effectiveAttributeType;
        effectiveAttributeType = normalizeSubtypeCode(effectiveAttributeType, presetScopedAttributeTypes);

        if (effectiveAttributeType && originalAttributeType !== effectiveAttributeType) {
          const nextParams = new URLSearchParams(searchParams);
          nextParams.set('documentAttributeType', effectiveAttributeType);
          nextParams.set('page', '1');
          setSearchParams(nextParams);
        } else if (effectiveAttributeType && !presetScopedAttributeTypes.some(type => type.code === effectiveAttributeType)) {
          effectiveAttributeType = undefined;
          const nextParams = new URLSearchParams(searchParams);
          nextParams.delete('documentAttributeType');
          nextParams.set('page', '1');
          setSearchParams(nextParams);
        }
      } else if (finalRuleType) {
        const attributeResponse = await getRulesList({
          ruleType: finalRuleType,
          page: 1,
          pageSize: SUBTYPE_DISCOVERY_PAGE_SIZE,
          token: loaderData.frontendJWT
        });

        if (attributeResponse.data) {
          const ruleAttributeTypes = Array.from(
            new Set(
              attributeResponse.data.rules
                .map(rule => rule.documentAttributeType)
                .filter((value): value is string => Boolean(value))
            )
          ).map(value => ({ code: value, label: value }));
          const scopedAttributeTypes = resolveScopedSubtypeOptions({
            documentTypeIds,
            selectedModuleName: currentModuleName,
            ruleTypeName: ruleTypeNameParam,
            apiOptions: apiAttributeTypes,
            ruleOptions: ruleAttributeTypes
          });

          setAttributeTypes(scopedAttributeTypes);
          const originalAttributeType = effectiveAttributeType;
          effectiveAttributeType = normalizeSubtypeCode(effectiveAttributeType, scopedAttributeTypes);

          if (effectiveAttributeType && originalAttributeType !== effectiveAttributeType) {
            const nextParams = new URLSearchParams(searchParams);
            nextParams.set('documentAttributeType', effectiveAttributeType);
            nextParams.set('page', '1');
            setSearchParams(nextParams);
          } else if (effectiveAttributeType && !scopedAttributeTypes.some(type => type.code === effectiveAttributeType)) {
            effectiveAttributeType = undefined;
            const nextParams = new URLSearchParams(searchParams);
            nextParams.delete('documentAttributeType');
            nextParams.set('page', '1');
            setSearchParams(nextParams);
          }
        } else {
          setAttributeTypes([]);
          effectiveAttributeType = undefined;
        }
      } else {
        setAttributeTypes([]);
        effectiveAttributeType = undefined;
      }

      const baseQueryParams = {
        ruleType: finalRuleType,
        groupId: searchParams.get('groupId') || undefined,
        isActive: searchParams.get('isActive') ? searchParams.get('isActive') === 'true' : undefined,
        keyword: searchParams.get('keyword') || undefined,
        area: userArea, // 添加地区过滤
        token: loaderData.frontendJWT
      };

      if (effectiveAttributeType) {
        const allRules: ApiRule[] = [];
        let totalCount = 0;
        let pageToFetch = 1;

        do {
          const response = await getRulesList({
            ...baseQueryParams,
            page: pageToFetch,
            pageSize: SUBTYPE_DISCOVERY_PAGE_SIZE
          });

          if (!response.data) {
            break;
          }

          allRules.push(...(response.data.rules as unknown as ApiRule[]));
          totalCount = response.data.totalCount || 0;
          pageToFetch += 1;
        } while (allRules.length < totalCount);

        const subtypeRules = allRules.filter(rule => rule.documentAttributeType === effectiveAttributeType);
        const startIndex = (currentPage - 1) * pageSize;
        const pageRules = subtypeRules.slice(startIndex, startIndex + pageSize);

        setFilteredRules(pageRules.map((apiRule: ApiRule) => mapApiRuleToModel(apiRule)));
        setFilteredTotalCount(subtypeRules.length);
        return;
      }

      // 调用 API 获取数据
      const response = await getRulesList({
        ...baseQueryParams,
        page: currentPage,
        pageSize
      });

      if (response.data) {
        const apiRules = response.data.rules || [];
        const total = response.data.totalCount || 0;
        const mappedRules = apiRules.map((apiRule: ApiRule) => mapApiRuleToModel(apiRule));

        setFilteredRules(mappedRules);
        setFilteredTotalCount(total);
      }
    } catch (error) {
      console.error('客户端加载评查点列表失败:', error);
      toastService.error('加载评查点列表失败');
    } finally {
      setLoading(false);
      isLoadingRef.current = false;
    }
  }, [ruleTypeParam, ruleTypeNameParam, searchParams, currentPage, pageSize, loaderData.frontendJWT, setSearchParams]);

  // 当评查点类型变化时，加载对应的规则组
  useEffect(() => {
    // 如果选择了"全部"或未选择，则清空规则组
    if (!selectedRuleTypeId) {
      setRuleGroups([]);
      return;
    }
    
    // 加载当前类型的规则组
    const loadRuleGroups = async () => {
      setLoadingGroups(true);
      try {
        const response = await getRuleGroupsByType(selectedRuleTypeId, loaderData.frontendJWT);
        if (response.data) {
          setRuleGroups(response.data);
        } else if (response.error) {
          console.error('加载规则组失败:', response.error);
          setRuleGroups([]);
        }
      } catch (error) {
        console.error('加载规则组出错:', error);
        setRuleGroups([]);
      } finally {
        setLoadingGroups(false);
      }
    };
    
    loadRuleGroups();
  }, [selectedRuleTypeId, loaderData.frontendJWT]);

  // 使用useEffect监听fetcher状态变化并显示Toast fetcher.state有以下几种状态： 通过fetcher提交数据后，action返回结果，fetcher.state会发生变化
  // idle: 空闲状态
  // loading: 加载中状态
  // submittting: 提交中状态
  // loading: 加载中状态
  // idle: 空闲状态
  useEffect(() => {
    // 仅在fetcher有数据且状态为idle时处理
    if (fetcher.data && fetcher.state === 'idle' && isDeleting) {
      // 重置删除状态
      setIsDeleting(false);
      
      if (fetcher.data.result) {
        toastService.success(fetcher.data.message);
        // 删除成功后重新加载数据
        fetchData();
      } else if (!fetcher.data.result) {
        // 删除失败只显示错误信息，不刷新数据
        if(fetcher.data.message.includes("evaluation_results_evaluation_point_id_fkey")) {
          toastService.error('对表evaluation_points进行更新或删除违反了表evaluation results上的外键约束evaluations results_evaluation _point_id_fkey');
        } else {
          toastService.error(fetcher.data.message);
        }
        // 删除失败不刷新数据
      }
    }
  }, [fetcher.data, fetcher.state, fetchData, isDeleting]);

  // 在组件挂载时从 sessionStorage 获取 documentTypeIds 并加载数据
  useEffect(() => {
    try {
      if (typeof window !== 'undefined') {
        const typeIdsStr = sessionStorage.getItem('documentTypeIds');
        const documentTypeIds = typeIdsStr ? JSON.parse(typeIdsStr) : null;
        console.log("📋 组件挂载，从 sessionStorage 获取 documentTypeIds:", documentTypeIds);
        setSelectedModuleName(sessionStorage.getItem('selectedModuleName') || '');
        setModuleScopeReady(true);

        // 如果有 documentTypeIds，加载数据
        if (documentTypeIds && documentTypeIds.length > 0) {
          // 使用 setTimeout 确保该操作在其他状态更新之后执行
          setTimeout(() => {
            fetchData();
          }, 0);
        }
      }
    } catch (error) {
      console.error('获取 sessionStorage 中的 documentTypeIds 失败:', error);
      setModuleScopeReady(true);
    }
  }, [initialLoad, fetchData]);

  // 注释掉重复的路由监听逻辑，避免与searchParams监听重复触发
  // useEffect(() => {
  //   if (routeChangeCount > 0) {
  //     console.log("📋 路由变化触发数据刷新，计数:", routeChangeCount);
  //     const typeIdsStr = typeof window !== 'undefined' ? sessionStorage.getItem('documentTypeIds') : null;
  //     const documentTypeIds = typeIdsStr ? JSON.parse(typeIdsStr) : null;
  //     console.log("📋 documentTypeIds:", documentTypeIds);

  //     if (documentTypeIds && documentTypeIds.length > 0) {
  //       // 使用 setTimeout 确保该操作在其他状态更新之后执行
  //       setTimeout(() => {
  //         fetchData();
  //       }, 0);
  //     }
  //   }
  // }, [routeChangeCount, fetchData]);

  // 监听 URL 参数变化，重新获取数据
  useEffect(() => {
    // 检查是否有 documentTypeIds
    const typeIdsStr = typeof window !== 'undefined' ? sessionStorage.getItem('documentTypeIds') : null;
    const documentTypeIds = typeIdsStr ? JSON.parse(typeIdsStr) : null;

    if (documentTypeIds && documentTypeIds.length > 0) {
      fetchData();
    }
  }, [searchParams, fetchData]);

  // 筛选评查点
  const handleFilterChange = (e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>) => {
    const { name, value } = e.target;
    const newParams = new URLSearchParams(searchParams);
    
    // 如果是规则组选择，但是当前应该被禁用，则不处理
    if (name === 'groupId' && isRuleGroupSelectDisabled) {
      return;
    }
    
    if (value) {
      newParams.set(name, value);
      
      // 如果是评查点类型变更，清空规则组选择
      if (name === 'ruleType') {
        newParams.delete('groupId');
        // 如果选择了"全部"或空值，也清空规则组选择
        if (value === '' || value === 'all') {
          setRuleGroups([]);
        }
        newParams.delete('ruleTypeName');
      }
    } else {
      newParams.delete(name);
      
      // 如果清除评查点类型，也清除规则组
      if (name === 'ruleType') {
        newParams.delete('groupId');
        setRuleGroups([]);
      }
      if (name === 'ruleType') {
        newParams.delete('ruleTypeName');
      }
    }
    
    // 切换筛选条件时，重置到第一页
    newParams.set('page', '1');
    setSearchParams(newParams);
  };

  // 搜索评查点
  const handleSearch = (keyword: string) => {
    const newParams = new URLSearchParams(searchParams);
    if (keyword) {
      newParams.set('keyword', keyword);
    } else {
      newParams.delete('keyword');
    }

    // 搜索时，重置到第一页
    newParams.set('page', '1');
    setSearchParams(newParams);
  };

  // 删除评查点
  const handleDeleteClick = (rule: Rule) => {
    // ✅ 检查删除权限
    if (!canDeleteRule) {
      toastService.warning('您没有删除权限');
      return;
    }

    messageService.show({
      title: "确认删除",
      message: `确认删除评查点【${rule.name}】吗？`,
      type: "warning",
      confirmText: "删除",
      cancelText: "取消",
      onConfirm: () => {
        // 设置删除状态为true
        setIsDeleting(true);
        const form = new FormData();
        form.append("_action", "delete");
        form.append("ruleId", rule.id);

        fetcher.submit(form, { method: "post" });
      }
    });
  };

  // 复制评查点
  const handleCopy = (rule: Rule) => {
    navigate(`/rules/new?id=${rule.id}&mode=copy`);
  };

  // 批量选择处理
  const handleSelectAll = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.checked) {
      setSelectedIds(filteredRules.map(rule => rule.id));
    } else {
      setSelectedIds([]);
    }
  };

  const handleSelectRow = (id: string) => {
    setSelectedIds(prev =>
      prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id]
    );
  };

  // 批量启用/禁用
  const handleBatchEnable = async (isEnabled: boolean) => {
    // ✅ 检查批量操作权限
    if (!canBatchRule) {
      toastService.warning('您没有批量操作权限');
      return;
    }

    if (selectedIds.length === 0) {
      toastService.warning('请先选择要操作的评查点');
      return;
    }

    try {
      setLoading(true);
      const result = await batchUpdateRuleStatus(selectedIds, isEnabled, loaderData.frontendJWT);

      if (result.success) {
        toastService.success(`成功${isEnabled ? '启用' : '禁用'} ${result.updated_count} 个评查点`);
        if (result.failed_ids.length > 0) {
          toastService.warning(`有 ${result.failed_ids.length} 个评查点操作失败`);
        }
        // 清空选择
        setSelectedIds([]);
        // 重新加载数据
        fetchData();
      } else {
        toastService.error('批量操作失败');
      }
    } catch (error) {
      console.error('批量操作失败:', error);
      toastService.error('批量操作失败');
    } finally {
      setLoading(false);
    }
  };

  // 批量删除
  const handleBatchDelete = async () => {
    // ✅ 检查批量删除权限
    if (!canBatchRule || !canDeleteRule) {
      toastService.warning('您没有批量删除权限');
      return;
    }

    if (selectedIds.length === 0) {
      toastService.warning('请先选择要删除的评查点');
      return;
    }

    messageService.show({
      title: "确认批量删除",
      message: `确定要删除选中的 ${selectedIds.length} 个评查点吗？此操作不可恢复。`,
      type: "warning",
      confirmText: "删除",
      cancelText: "取消",
      onConfirm: async () => {
        try {
          setLoading(true);
          const result = await batchDeleteRules(selectedIds, loaderData.frontendJWT);

          if (result.success) {
            toastService.success(`成功删除 ${result.deleted_count} 个评查点`);
            if (result.failed_ids.length > 0) {
              toastService.warning(`有 ${result.failed_ids.length} 个评查点删除失败`);
            }
            // 清空选择
            setSelectedIds([]);
            // 重新加载数据
            fetchData();
          } else {
            toastService.error('批量删除失败');
          }
        } catch (error) {
          console.error('批量删除失败:', error);
          toastService.error('批量删除失败');
        } finally {
          setLoading(false);
        }
      }
    });
  };

  const handlePageChange = (page: number) => {
    const newParams = new URLSearchParams(searchParams);
    newParams.set('page', page.toString());
    setSearchParams(newParams);
  };

  // 处理每页条数变化
  const handlePageSizeChange = (size: number) => {
    const newParams = new URLSearchParams(searchParams);
    newParams.set('pageSize', size.toString());
    newParams.set('page', '1'); // 更改每页条数时，重置到第一页
    setSearchParams(newParams);
  };

  // 处理重置筛选
  const handleReset = () => {
    const input = document.querySelector('input[placeholder="输入评查点名称或编码"]');
    if (input) {
      (input as HTMLInputElement).value = '';
    }

    const newParams = new URLSearchParams();
    setSearchParams(newParams);
  };

  // 处理单个评查点状态切换
  const handleStatusChange = (rule: Rule) => {
    // ✅ 检查更新权限
    if (!canUpdateRule) {
      toastService.warning('您没有更新权限');
      return;
    }

    // 如果正在更新，不处理
    if (updatingStatusIds.has(rule.id)) {
      return;
    }

    const newStatus = !rule.isActive;
    const statusText = newStatus ? '启用' : '禁用';

    messageService.show({
      title: "确认操作",
      message: `确认要${statusText}评查点【${rule.name}】吗？`,
      type: "warning",
      confirmText: "确定",
      cancelText: "取消",
      onConfirm: async () => {
        try {
          // 添加到更新中的ID集合
          setUpdatingStatusIds(prev => new Set(prev).add(rule.id));

          const response = await updateEvaluationPoint(
            rule.id,
            { is_enabled: newStatus },
            loaderData.frontendJWT
          );

          if (response.error) {
            toastService.error(`${statusText}失败：${response.error}`);
          } else {
            toastService.success(`评查点已${statusText}`);
            // 刷新列表数据
            fetchData();
          }
        } catch (error) {
          console.error('更新评查点状态失败:', error);
          toastService.error(`更新失败：${error instanceof Error ? error.message : '未知错误'}`);
        } finally {
          // 从更新中的ID集合移除
          setUpdatingStatusIds(prev => {
            const newSet = new Set(prev);
            newSet.delete(rule.id);
            return newSet;
          });
        }
      }
    });
  };

  // 定义表格列配置
  const columns = [
    // ✅ 添加复选框列（有批量操作权限时可见）
    ...(canBatchRule ? [{
      title: (
        <input
          type="checkbox"
          checked={selectedIds.length > 0 && selectedIds.length === filteredRules.length && filteredRules.length > 0}
          onChange={handleSelectAll}
          disabled={filteredRules.length === 0}
        />
      ),
      key: "selection",
      align: "center" as const,
      width: "3%",
      render: (_: unknown, record: Rule) => (
        <input
          type="checkbox"
          checked={selectedIds.includes(record.id)}
          onChange={() => handleSelectRow(record.id)}
          onClick={(e) => e.stopPropagation()}
        />
      )
    }] : []),
    {
      title: "评查点编码",
      dataIndex: "code" as keyof Rule,
      key: "code",
      align: "left" as const,
      width: "9%",
      className: "whitespace-normal break-all",
      render: (value: string) => (
        <div className="whitespace-normal break-all overflow-visible">{value}</div>
      )
    },
    {
      title: "评查点名称",
      dataIndex: "name" as keyof Rule,
      key: "name",
      align: "left" as const,
      width: "12%"
    },
    // 主类型已拆分到左侧菜单，列表不再重复展示评查点类型列。
    // {
    //   title: "评查点类型",
    //   key: "ruleType",
    //   align: "left" as const,
    //   width: "8%",
    //   render: (_: unknown, record: Rule) => {
    //     const typeColor = RULE_TYPE_COLORS[record.ruleType] as TagColor;
    //     return (
    //       record.ruleType ? <Tag color={typeColor}>
    //         {record.ruleType}
    //       </Tag> : null
    //     );
    //   }
    // },
    {
      title: "所属规则组",
      dataIndex: "groupName" as keyof Rule,
      key: "groupName",
      align: "left" as const,
      width: "12%"
    },
    {
      title: "地区",
      dataIndex: "area" as keyof Rule,
      key: "area",
      align: "left" as const,
      width: "5%",
      render: (value: string) => value || '-'
    },
    {
      title: "子类型",
      dataIndex: "documentAttributeType" as keyof Rule,
      key: "documentAttributeType",
      align: "left" as const,
      width: "10%",
      render: (value: string) => value || '-'
    },
    {
      title: "优先级",
      key: "priority",
      align: "left" as const,
      width: "5%",
      render: (_: unknown, record: Rule) => {
        const priorityColor = RULE_PRIORITY_COLORS[record.priority] as TagColor;
        return (
          <Tag color={priorityColor}>
            {priorityLabels[record.priority as keyof typeof priorityLabels] || RULE_PRIORITY_LABELS[record.priority]}
          </Tag>
        );
      }
    },
    {
      title: "状态",
      key: "isActive",
      align: "left" as const,
      width: "5%",
      render: (_: unknown, record: Rule) => (
        <Switch
          checked={record.isActive}
          onChange={() => handleStatusChange(record)}
          disabled={!canUpdateRule}
          loading={updatingStatusIds.has(record.id)}
        />
      )
    },
    {
      title: "创建时间",
      dataIndex: "createdAt" as keyof Rule,
      key: "createdAt",
      align: "left" as const,
      width: "9%"
    },
    {
      title: "操作",
      key: "operation",
      align: "left" as const,
      width: "14%",
      render: (_: unknown, record: Rule) => (
        <div className="operations-cell">
          {/* ✅ 查看/编辑和复制按钮 - 需要查看权限 */}
          {canViewRule && (
            <>
              {/* ✅ 编辑/查看按钮 - 根据权限显示编辑或查看 */}
              <Link to={`/rules/new?id=${record.id}${!canUpdateRule ? '&mode=view' : ''}`} className="operation-btn">
                <i className={canUpdateRule ? "ri-edit-line" : "ri-eye-line"}></i> {canUpdateRule ? '编辑' : '查看'}
              </Link>
              {/* ✅ 复制按钮 - 有创建权限时显示 */}
              {canCreateRule && (
                <button className="operation-btn" onClick={() => handleCopy(record)}>
                  <i className="ri-file-copy-line"></i> 复制
                </button>
              )}
            </>
          )}
          {/* ✅ 删除按钮 - 只需要删除权限 */}
          {canDeleteRule && (
            <button className="operation-btn operation-btn-danger" onClick={() => handleDeleteClick(record)}>
              <i className="ri-delete-bin-line"></i> 删除
            </button>
          )}
          {/* 如果什么权限都没有，显示 - */}
          {!canViewRule && !canDeleteRule && (
            <span className="text-gray-400">-</span>
          )}
        </div>
      )
    }
  ];
  
  return (
    <div className="rules-page">
      {/* 页面头部 */}
      <div className="flex justify-between items-center mb-4">
        <div className="flex items-center">
          <div>
            <h2 className="text-xl font-medium">评查点管理</h2>
            <p className="mt-1 text-sm text-gray-500">
              {selectedModuleName
                ? `当前仅展示“${selectedModuleName}”入口关联文档类型的规则点。`
                : '请先从首页进入具体入口模块，再查看该入口对应的规则点。'}
            </p>
          </div>
          {loading ? (
            <div className="flex items-center ml-4 bg-white px-3 py-1 rounded-md">
              <NumberSkeleton className="ml-1" />
            </div>
          ) : (
            <div className="flex items-center ml-4 bg-white px-3 py-1 rounded-md">
              <i className="ri-file-list-3-line text-primary text-lg mr-1"></i>
              <span className="text-sm text-secondary">总评查点数：</span>
              <span className="text-base font-normal text-primary ml-1">{filteredTotalCount}</span>
            </div>
          )}
        </div>
        <div className="flex items-center gap-2">
          {/* ✅ 批量操作按钮（有批量权限且有选择时显示） */}
          {canBatchRule && selectedIds.length > 0 && (
            <>
              <Button
                type="default"
                icon="ri-check-line"
                onClick={() => handleBatchEnable(true)}
                className="btn-batch-enable"
              >
                批量启用 ({selectedIds.length})
              </Button>
              <Button
                type="default"
                icon="ri-close-line"
                onClick={() => handleBatchEnable(false)}
                className="btn-batch-disable"
              >
                批量禁用 ({selectedIds.length})
              </Button>
              {canDeleteRule && (
                <Button
                  type="danger"
                  icon="ri-delete-bin-line"
                  onClick={handleBatchDelete}
                  className="btn-batch-delete"
                >
                  批量删除 ({selectedIds.length})
                </Button>
              )}
            </>
          )}
          {/* ✅ 新增按钮 - 有创建权限时显示 */}
          {canCreateRule && (
            <Button type="primary" icon="ri-add-line" to="/rules/new" className="btn-add-rule">
              新增评查点
            </Button>
          )}
        </div>
      </div>

      {moduleScopeReady && !selectedModuleName && (
        <Card className="ant-card mb-4 border-amber-200 bg-amber-50">
          <div className="flex items-start gap-3 text-amber-900">
            <i className="ri-information-line text-lg mt-0.5"></i>
            <div>
              <div className="font-medium">当前未绑定业务入口上下文</div>
              <div className="text-sm mt-1">
                评查点列表按入口模块显示对应文档类型规则。请先从首页进入具体入口，再查看这里。
              </div>
            </div>
          </div>
        </Card>
      )}
      
      {/* 筛选区域 */}
      <FilterPanel className="px-3 py-3" noActionDivider={true}
        actions={
          <>
            <Button type="default" icon="ri-refresh-line" onClick={handleReset} className="mr-2 hover:!border-gray-300">
              重置
            </Button>
          </>
        }
      >
        <FilterSelect
          label="所属规则组"
          name="groupId"
          value={searchParams.get('groupId') || ''}
          options={[
            ...(isRuleGroupSelectDisabled ? [{ value: "", label: "请先选择主类型" }] : []),
            ...ruleGroups.map(group => ({ 
              value: group.id, 
              label: group.name 
            }))
          ]}
          onChange={handleFilterChange}
          className={`mr-3 w-[22%] ${isRuleGroupSelectDisabled ? 'opacity-50' : ''}`}
        />

        <FilterSelect
          label="子类型"
          name="documentAttributeType"
          value={searchParams.get('documentAttributeType') || ''}
          options={attributeTypes.map(type => ({
            value: type.code,
            label: type.label
          }))}
          onChange={handleFilterChange}
          className="mr-3 w-[18%]"
        />
        
        <FilterSelect
          label="状态"
          name="isActive"
          value={searchParams.get('isActive') || ''}
          options={[
            { value: "true", label: "启用" },
            { value: "false", label: "禁用" }
          ]}
          onChange={handleFilterChange}
          className="mr-3 w-[15%]"
        />
        
        <SearchFilter
          label="搜索"
          placeholder="输入评查点名称或编码"
          value={searchParams.get('keyword') || ''}
          buttonText="搜索"
          onSearch={handleSearch}
          className="min-w-[200px] flex-1"
        />
      </FilterPanel>
      
      
      {/* 评查点列表 - 使用Table组件 */}
      <Card className="ant-card">
          {loading && <LoadingIndicator />}
        <div className={loading ? "opacity-70 pointer-events-none transition-opacity" : ""}>
          
          {loading && filteredRules.length === 0 ? (
            <TableRowSkeleton count={5} />
          ) : (
            <Table
              columns={columns}
              dataSource={filteredRules}
              rowKey="id"
              // emptyText={loading ? "正在加载数据..." : "暂无评查点数据"}
              className="rules-table"
              scroll={{ y: 700 }}
            />
          )}
          
          {/* 分页 */}
          {filteredTotalCount > 0 && (
            <Pagination
              currentPage={currentPage}
              total={filteredTotalCount}
              pageSize={pageSize}
              onChange={handlePageChange}
              onPageSizeChange={handlePageSizeChange}
              showTotal={true}
              showPageSizeChanger={true}
              pageSizeOptions={[10, 20, 30, 50]}
            />
          )}
        </div>
      </Card>
      
    </div>
  );
} 

// 错误边界
export function ErrorBoundary() {
  return (
    <div className="error-container p-6">
      <h1 className="text-xl font-bold text-red-500 mb-4">出错了</h1>
      <p className="mb-4">加载评查点列表时发生错误。请稍后再试，或联系管理员。</p>
      <Button type="primary" to="/">返回首页</Button>
    </div>
  );
}
