/*
 * @Author: code4eat awesomedema@gmail.com
 * @Date: 2025-09-30 00:00:00
 * @LastEditors: code4eat awesomedema@gmail.com
 * @LastEditTime: 2025-10-17 11:57:04
 * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/serviceEvaluate/index.tsx
 * @Description: 服务评价管理 - 左树右表 + 可展开选项子表
 */

import React, { useEffect, useMemo, useState } from 'react';
import './style.less';

import { Button, Input, InputNumber, message, Modal, Popconfirm, Tooltip, Transfer, Tree } from 'antd';
import { ProColumns } from '@ant-design/pro-table';
import { ModalForm, ProFormDigit, ProFormText } from '@ant-design/pro-form';
import KCTable from '@/components/kcTable';
import DirectoryTree from 'antd/es/tree/DirectoryTree';
import { DataNode } from 'antd/es/tree';
import type { TransferDirection } from 'antd/es/transfer';
import { createFromIconfontCN } from '@ant-design/icons';
import expandedIcon from '../../../../../public/images/treenode_open.png';
import closeIcon from '../../../../../public/images/treenode_collapse.png';
import { KCInput } from '@/components/KCInput';
import { getDictByDictTypeAndSysid } from '@/service/dictionary';

import {
  getCategoryTree,
  addCategory,
  getProjectList,
  getOptionList,
  addProject,
  delProject,
  addOption,
  delOption,
  updateProjectWeight,
  updateOptionScore,
  CategoryNode,
  ProjectItem,
  OptionItem,
  SystemTreeNode,
  getSystemListForModal,
  addSystems,
  getSelectedSystemList,
  addServiceTypes,
  getServiceEvaluationItem,
  getEvaluationSelect,
  addEvaluationItem,
  addEvaluationSelect,
  editEvaluationSelect,
  deleteEvaluationItem,
  deleteEvaluationSelect,
} from './service';

const IconFont = createFromIconfontCN({
  scriptUrl: '/zhongtaiC.js',
});

// 子表格：选项列表
const OptionsList: React.FC<{
  project: ProjectItem;
  options: OptionItem[];
  onAdd: (data: { optionCode: string; optionName: string; score: number }) => Promise<void>;
  onDelete: (optionId: string) => Promise<void>;
  onScoreChange: (optionId: string, score: number) => Promise<void>;
}> = ({ project, options, onAdd, onDelete, onScoreChange }) => {
  return (
    <div className="SE-OptionsWrap">
      <div className="SE-OptionsHeader">
        <span className="SE-SubTitle">{project.projectName} - 选项</span>
        <ModalForm
          title="新增选项"
          width={520}
          trigger={<Button type="link">新增选项</Button>}
          modalProps={{ destroyOnClose: true }}
          onFinish={async (values) => {
            await onAdd(values as any);
            return true;
          }}
        >
          <ProFormText name="optionCode" label="选项代码" placeholder="请输入" rules={[{ required: true, message: '必填' }]} />
          <ProFormText name="optionName" label="选项名称" placeholder="请输入" rules={[{ required: true, message: '必填' }]} />
          <ProFormDigit name="score" label="选项得分" placeholder="请输入" min={0} max={9999} rules={[{ required: true, message: '必填' }]} />
        </ModalForm>
      </div>

      <div className="SE-OptionsTable">
        <div className="SE-OptionsRow SE-OptionsHead">
          <div className="col idx">序号</div>
          <div className="col code">选项代码</div>
          <div className="col name">选项名称</div>
          <div className="col score">选项得分</div>
          <div className="col act">操作</div>
        </div>
        {options && options.length > 0 ? (
          options.map((opt, index) => (
            <div className="SE-OptionsRow" key={opt.optionId}>
              <div className="col idx">{index + 1}</div>
              <div className="col code">{opt.optionCode}</div>
              <div className="col name">{opt.optionName}</div>
              <div className="col score">
                <InputNumber
                  min={0}
                  max={9999}
                  value={opt.score}
                  onChange={(val) => {
                    const v = typeof val === 'number' ? val : Number(val);
                    if (!Number.isNaN(v)) onScoreChange(opt.optionId, v);
                  }}
                />
              </div>
              <div className="col act">
                <Popconfirm title="是否确认删除？" onConfirm={() => onDelete(opt.optionId)}>
                  <a>删除</a>
                </Popconfirm>
              </div>
            </div>
          ))
        ) : (
          <div className="SE-Empty">暂无选项</div>
        )}
      </div>
    </div>
  );
};

const ServiceEvaluatePage: React.FC = () => {
  // 左侧分类树
  const [categoryTree, set_categoryTree] = useState<CategoryNode[]>([]);
  const [currentCategory, set_currentCategory] = useState<CategoryNode | undefined>();
  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
  const [autoExpandParent, setAutoExpandParent] = useState(true);
  const [searchValue, setSearchValue] = useState('');

  // 主表相关
  const [reload, set_reload] = useState(false);
  const [tableParams, set_tableParams] = useState<{ current: number; pageSize: number; categoryId?: string }>({ current: 1, pageSize: 10 });
  const [tableKey, set_tableKey] = useState(0); // 用于强制刷新表格
  const [expandedRowKeys, set_expandedRowKeys] = useState<React.Key[]>([]); // 追踪展开的行

  // 展开区缓存选项数据，避免频繁请求
  const [projectOptionsMap, set_projectOptionsMap] = useState<Record<string, OptionItem[]>>({});
  // 项目权重编辑态（保持原交互：编辑/勾选）
  const [editingProjectId, set_editingProjectId] = useState<string | null>(null);
  const [editingProjectWeight, set_editingProjectWeight] = useState<number>(0);

  // 添加系统弹窗
  const [sysModalOpen, set_sysModalOpen] = useState(false);
  const [systemTree, set_systemTree] = useState<SystemTreeNode[]>([]);
  const [sysTargetKeys, set_sysTargetKeys] = useState<string[]>([]);
  const [sysSelectedKeys, set_sysSelectedKeys] = useState<string[]>([]);
  const [sysExpandedKeys, set_sysExpandedKeys] = useState<string[]>([]);
  // 服务项弹窗
  const [serviceModalOpen, set_serviceModalOpen] = useState(false);
  const [serviceDict, set_serviceDict] = useState<{ key: string; title: string }[]>([]);
  const [serviceSelected, set_serviceSelected] = useState<string[]>([]);
  const [serviceBindSystemId, set_serviceBindSystemId] = useState<string>('');
  const [serviceSaving, set_serviceSaving] = useState(false);
  // 服务节点展开行：缓存“评价项 -> 选项”数据（与 /centerSys/evaluation/getEvaluationSelect 返回结构一致）
  const [serviceOptionsMap, set_serviceOptionsMap] = useState<
    Record<string, { id: number | string; hospId?: string; itemCode: string; code: string; name: string; value: number; sort: number }[]>
  >({});

  // 评价项目弹窗（右侧"添加"）
  const [evalItemModalOpen, set_evalItemModalOpen] = useState(false);
  const [evalItemDict, set_evalItemDict] = useState<{ key: string; code: string; value: string; title: string }[]>([]);
  const [evalItemTargetKeys, set_evalItemTargetKeys] = useState<string[]>([]);
  const [evalItemSelectedKeys, set_evalItemSelectedKeys] = useState<string[]>([]);
  // 评价项权重编辑态
  const [editingEvalCode, set_editingEvalCode] = useState<string | null>(null);
  const [editingEvalValue, set_editingEvalValue] = useState<number>(0);
  // 选项弹窗（评价项 -> 选项）
  const [selectModalOpen, set_selectModalOpen] = useState(false);
  const [selectDict, set_selectDict] = useState<{ key: string; title: string }[]>([]);
  const [selectTargetKeys, set_selectTargetKeys] = useState<string[]>([]);
  const [selectSelectedKeys, set_selectSelectedKeys] = useState<string[]>([]);
  const [bindItemCode, set_bindItemCode] = useState<string>('');
  // 服务节点主表数据缓存（用于拖拽排序后保持展示顺序）
  const [evalItemRows, set_evalItemRows] = useState<any[]>([]);
  const [draggingMainKey, set_draggingMainKey] = useState<string | null>(null);
  const [draggingOverMainKey, set_draggingOverMainKey] = useState<string | null>(null);
  const [useLocalEvalOrder, set_useLocalEvalOrder] = useState<boolean>(false);
  // 嵌套选项拖拽的中间态
  const [draggingOption, set_draggingOption] = useState<{ parent: string; key: string } | null>(null);
  const [draggingOverOption, set_draggingOverOption] = useState<{ parent: string; key: string } | null>(null);

  // 工具：移动数组元素
  const moveItem = <T,>(list: T[], from: number, to: number): T[] => {
    const next = [...list];
    const [m] = next.splice(from, 1);
    next.splice(to, 0, m);
    return next;
  };

  // 获取左侧“已选系统”并渲染为单层树
  const fetchTree = async () => {
    const list = await getSelectedSystemList();
    const tree: any[] = (list || []).map((item: any) => ({
      id: String(item.systemId),
      name: String(item.systemName),
      nodeType: 'system',
      selectable: false,
      // 将 serviceList 映射为子节点
      children: (item.serviceList || []).map((s: any) => ({
        id: String(s.id),
        name: String(s.name),
        code: String(s.code || ''),
        nodeType: 'service',
        selectable: true,
      })),
    }));
    set_categoryTree(tree as any);

    // 默认选中第一个服务；若无服务则只展开系统，不触发右侧
    if (tree.length > 0) {
      const sys = tree[0];
      if (sys.children && sys.children.length > 0) {
        const firstChild = sys.children[0];
        set_currentCategory(firstChild as any);
        set_tableParams((p) => ({ ...p, current: 1, categoryId: firstChild.id }));
        set_reload(true);
        set_editingEvalCode(null);
        // 服务节点：首次加载右侧评价项
        if ((firstChild as any).nodeType === 'service') {
          await loadServiceEvalItems(String((firstChild as any).code || (firstChild as any).name));
        }
      }
      if (sys.children && sys.children.length > 0) {
        setExpandedKeys([sys.id]);
          setAutoExpandParent(true);
      }
    }
  };

  // 获取系统树（弹窗数据源）
  const fetchSystemTree = async () => {
    const { systemList, selectSystemList } = await getSystemListForModal();
    set_systemTree(systemList || []);
    // 默认已选
    set_sysTargetKeys((selectSystemList || []).map((v)=> String(v)));
    // 默认全部展开
    const allKeys: string[] = [];
    const walk = (list: SystemTreeNode[]) => { list.forEach(n=>{ allKeys.push(String(n.code)); if (n.children && n.children.length) walk(n.children); }); };
    walk(systemList || []);
    set_sysExpandedKeys(allKeys);
  };

  // 获取服务项字典
  const fetchServiceDict = async () => {
    // 使用中心系统ID：1547394914533380096 获取指定字典类型
    const resp: any = await getDictByDictTypeAndSysid('1547394914533380096', 'EVALUATION_SERVICE');
    const list = (resp?.dataVoList || []).map((x: any) => ({ key: String(x.code || x.value), title: String(x.name) }));
    set_serviceDict(list);
  };

  // 获取评价项目字典
  const fetchEvaluationItemsDict = async () => {
    const resp: any = await getDictByDictTypeAndSysid('1547394914533380096', 'EVALUATION_ITEM');
    const list = (resp?.dataVoList || []).map((x: any) => ({ 
      key: String(x.code || x.value), 
      code: String(x.code),
      value: String(x.value),
      title: String(x.name) 
    }));
    set_evalItemDict(list);
  };

  // 获取“选项”字典
  const fetchEvaluationSelectDict = async () => {
    const resp: any = await getDictByDictTypeAndSysid('1547394914533380096', 'EVALUATION_SELECT');
    const list = (resp?.dataVoList || []).map((x: any) => ({ key: String(x.code || x.value), title: String(x.name) }));
    set_selectDict(list);
  };

  // 拉取服务类型下的评价项（用于 dataSource 渲染 & 拖拽）
  const loadServiceEvalItems = async (serviceCode: string) => {
    const list = (await getServiceEvaluationItem(serviceCode)) || [];
    const normalizePercent = (v: any): number => {
      const n = Number(v);
      // 接口返回的是小数（如0.2），需要转换为百分比（20）
      return Number.isFinite(n) && n >= 0 ? n * 100 : 0;
    };
    const mapped = (list || []).map((it: any, idx: number) => ({
      id: it.id,  // 保留 id 字段，用于删除等操作
      itemCode: it.itemCode,
      itemName: it.itemName,
      percent: normalizePercent(it.percent),
      sort: it.sort ?? idx + 1,
    }));
    set_evalItemRows(mapped);
    set_useLocalEvalOrder(true);
  };

  // 获取表格数据：服务节点 → 评价项；系统/分类节点 → 项目列表
  const getTableData = async (params: any) => {
    set_reload(false);
    if (!currentCategory) return { data: [], success: true } as any;
    const node: any = currentCategory as any;
    if (node.nodeType === 'service') {
      // 使用 dataSource 渲染时，这里返回本地 rows，避免与 KCTable 拖拽冲突
      if (evalItemRows && evalItemRows.length > 0) {
        return { data: evalItemRows, success: true } as any;
      }
      await loadServiceEvalItems(String(node.code || node.name));
      return { data: evalItemRows, success: true } as any;
    }
    const resp = await getProjectList({ categoryId: currentCategory.id, ...params });
    return { data: resp.list || [], success: true } as any;
  };

  // 主表列定义 - 项目
  const projectColumns: ProColumns<ProjectItem>[] = useMemo(
    () => [
      { title: '', dataIndex: 'drag', width: 32, render: () => (<span className="SE-DragHandle" style={{ cursor:'move', display:'flex', alignItems:'center', justifyContent:'center', height:'100%' }}><IconFont type="iconliebiao" style={{ fontSize: 16, color: '#99A6BF' }} /></span>) },
      {
        title: '序号',
        dataIndex: 'index',
        width: 60,
        render: (_, __, index) => index + 1,
      },
      {
        title: '评价项目代码',
        dataIndex: 'projectCode',
        width: 100,
      },
      {
        title: '评价项目名称',
        dataIndex: 'projectName',
        ellipsis: true,
      },
      {
        title: '权重',
        dataIndex: 'weight',
        width: 120,
        render: (_, record) => (
          <InputNumber
            min={0}
            max={100}
            formatter={(value) => `${value}%`}
            parser={(value) => Number(String(value).replace('%', ''))}
            value={record.weight}
            onChange={async (val) => {
              const weight = typeof val === 'number' ? val : Number(val);
              if (Number.isNaN(weight)) return;
              const ok = await updateProjectWeight(record.projectId, weight);
              if (ok) set_reload(true);
            }}
          />
        ),
      },
      {
        title: '操作',
        key: 'option',
        width: 160,
        valueType: 'option',
        render: (_, record) => [
          <ModalForm
            key="add"
            title={`新增“${record.projectName}”的选项`}
            trigger={<a>选项</a>}
            width={520}
            onFinish={async (values) => {
              const ok = await addOption({ projectId: record.projectId, ...(values as any) });
              if (ok) {
              const opts = await getOptionList({ projectId: record.projectId });
              set_projectOptionsMap((old) => ({ ...old, [record.projectId]: opts || [] }));
              }
              return !!ok;
            }}
          >
            <ProFormText name="optionCode" label="选项代码" rules={[{ required: true, message: '必填' }]} />
            <ProFormText name="optionName" label="选项名称" rules={[{ required: true, message: '必填' }]} />
            <ProFormDigit name="score" label="选项得分" min={0} max={9999} rules={[{ required: true, message: '必填' }]} />
          </ModalForm>,
          <Popconfirm key="del" title="是否确认删除？" onConfirm={async () => { const ok = await delProject(record.projectId); if (ok) set_reload(true); }}>
            <a>删除</a>
          </Popconfirm>,
        ],
      },
    ],
    [projectOptionsMap]
  );

  // 评价项表格列
  const evalItemColumns: ProColumns<any>[] = useMemo(
    () => [
      { title: '', dataIndex: 'drag', width: 32, render: () => (<span className="SE-DragHandle" style={{ cursor:'move', display:'flex', alignItems:'center', justifyContent:'center', height:'100%' }}><IconFont type="iconliebiao" style={{ fontSize: 16, color: '#99A6BF' }} /></span>) },
      { title: '序号', dataIndex: 'index', width: 60, render: (_, __, index) => index + 1 },
      { title: '评价项目代码', dataIndex: 'itemCode', width: 120 },
      { title: '评价项目名称', dataIndex: 'itemName', ellipsis: true },
      {
        title: '权重',
        dataIndex: 'percent',
        width: 120,
        render: (v: any) => `${(Number.isFinite(Number(v)) && Number(v) >= 0 ? Number(v) : 0)}%`,
      },
      // 移除不需要的排序列
      {
        title: '操作',
        valueType: 'option',
        width: 120,
        render: (_, record) => [
          <a key="opt" onClick={async () => { 
            set_bindItemCode(record.itemCode); 
            // 获取该评价项已有的选项
            const current: any = currentCategory as any;
            const serviceType = String(current?.code || current?.name || '');
            const existingOptions = await getEvaluationSelect(record.itemCode, serviceType);
            const existingKeys = (existingOptions || []).map((item: any) => String(item.code));
            set_selectTargetKeys(existingKeys); 
            set_selectSelectedKeys([]); 
            await fetchEvaluationSelectDict(); 
            set_selectModalOpen(true); 
          }}>选项</a>,
          <Popconfirm key="del" title="是否确认删除？" onConfirm={async () => { 
            const res = await deleteEvaluationItem(record.id);
            if (res !== false) {
              // 删除成功后，如果该项是展开状态，从展开列表中移除
              set_expandedRowKeys((prev) => prev.filter(k => k !== record.itemCode));
              // 重新加载评价项列表
              const current: any = currentCategory as any;
              if (current && current.nodeType === 'service') {
                await loadServiceEvalItems(String(current.code || current.name));
              }
            }
          }}>
            <a>删除</a>
          </Popconfirm>,
        ],
      },
    ],
    [editingEvalCode, editingEvalValue]
  );

  // 展开行渲染（分类/系统场景使用）
  const expandedRowRender = (record: ProjectItem) => {
    const options = projectOptionsMap[record.projectId] || [];
    return (
      <OptionsList
        project={record}
        options={options}
        onAdd={async (data) => {
          const ok = await addOption({ projectId: record.projectId, ...data });
          if (ok) {
          const opts = await getOptionList({ projectId: record.projectId });
          set_projectOptionsMap((old) => ({ ...old, [record.projectId]: opts || [] }));
          }
        }}
        onDelete={async (optionId) => {
          const ok = await delOption(optionId);
          if (ok) {
          const opts = await getOptionList({ projectId: record.projectId });
          set_projectOptionsMap((old) => ({ ...old, [record.projectId]: opts || [] }));
          }
        }}
        onScoreChange={async (optionId, score) => {
          const ok = await updateOptionScore(optionId, score);
          if (ok) {
          const opts = await getOptionList({ projectId: record.projectId });
          set_projectOptionsMap((old) => ({ ...old, [record.projectId]: opts || [] }));
          }
        }}
      />
    );
  };

  // 服务节点：展开渲染（与外层保持一致的 KCTable 风格）
  const expandedRowRenderService = (record: any) => {
    const parentCode: string = record.itemCode;
    const rows = serviceOptionsMap[parentCode] || [];
    const columns: ProColumns<any>[] = [
      {
        title: '',
        dataIndex: 'drag',
        width: 32,
        render: (_, row: any) => (
          <span
            className="SE-DragHandle"
            style={{ cursor: 'move', display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}
            draggable
            onDragStart={(e) => {
              set_draggingOption({ parent: parentCode, key: String(row.id ?? row.code) });
              e.dataTransfer.effectAllowed = 'move';
              try { e.dataTransfer.setData('text/plain', String(row.id ?? row.code)); } catch {}
            }}
            onDragOver={(e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; }}
            onDrop={(e) => {
              e.preventDefault();
              if (!draggingOption || draggingOption.parent !== parentCode) return;
              const list = serviceOptionsMap[parentCode] || [];
              const from = list.findIndex((r: any) => String(r.id ?? r.code) === draggingOption.key);
              const to = list.findIndex((r: any) => String(r.id ?? r.code) === String(row.id ?? row.code));
              if (from === -1 || to === -1 || from === to) return;
              const next = moveItem(list, from, to);
              set_serviceOptionsMap((old) => ({ ...old, [parentCode]: next }));
              set_draggingOption(null);
              set_reload((v)=>!v);
              // TODO: 保存选项排序
            }}
            title="拖动排序"
          >
            <IconFont type="iconliebiao" style={{ fontSize: 16, color: '#99A6BF' }} />
          </span>
        ),
      },
      { title: '序号', dataIndex: 'index', width: 60, render: (_, __, index) => index + 1 },
      { title: '选项代码', dataIndex: 'code', width: 120 },
      { title: '选项名称', dataIndex: 'name', ellipsis: true },
      {
        title: '选项得分',
        dataIndex: 'value',
        width: 200,
        render: (v: any, row: any) => {
          const isEditing = row.__editing === true;
          if (!isEditing) {
    return (
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <div style={{ padding: '2px 10px', border: '1px solid #dae2f2', borderRadius: 6, minWidth: 72, textAlign: 'center', background: '#f7f9fc' }}>{v ?? 0}</div>
                <span
                  onClick={() => {
                    set_serviceOptionsMap((old) => {
                      const list = [...(old[parentCode] || [])];
                      const idx = list.findIndex((i: any) => String(i.id ?? i.code) === String(row.id ?? row.code));
                      if (idx > -1) list[idx] = { ...list[idx], __editing: true } as any;
                      return { ...old, [parentCode]: list };
                    });
                  }}
                  style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', height: 28, width: 28, border: '1px solid #dae2f2', borderRadius: 6, cursor: 'pointer' }}
                >
                  <IconFont type="iconbianji" style={{ fontSize: 16, color: '#17181A' }} />
                </span>
          </div>
            );
          }
          return (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <InputNumber
                min={0}
                max={9999}
                value={row.value}
                onChange={(val) => {
                  const next = Number(val) || 0;
                  set_serviceOptionsMap((old) => {
                    const list = [...(old[parentCode] || [])];
                    const idx = list.findIndex((i: any) => String(i.id ?? i.code) === String(row.id ?? row.code));
                    if (idx > -1) list[idx] = { ...list[idx], value: next, __editing: true } as any;
                    return { ...old, [parentCode]: list };
                  });
                }}
                style={{ width: 100 }}
              />
              <span
                onClick={async () => {
                  // 调用接口保存选项分值
                  const res = await editEvaluationSelect(row.id, row.value);
                  // 响应拦截器：成功返回 data 或 true，失败返回 false
                  // 且 POST 成功时拦截器已自动显示"操作成功！"提示
                  if (res !== false) {
                    // 成功，退出编辑状态
                    set_serviceOptionsMap((old) => {
                      const list = [...(old[parentCode] || [])];
                      const idx = list.findIndex((i: any) => String(i.id ?? i.code) === String(row.id ?? row.code));
                      if (idx > -1) list[idx] = { ...list[idx], __editing: false } as any;
                      return { ...old, [parentCode]: list };
                    });
                  }
                  // 失败时拦截器已显示错误提示，这里只需保持编辑状态
                }}
                style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', height: 28, width: 28, border: '1px solid #dae2f2', borderRadius: 6, cursor: 'pointer' }}
              >
                <IconFont type="iconqueren" style={{ fontSize: 16, color: '#17181A' }} />
              </span>
              </div>
          );
        },
      },
      {
        title: '操作',
        valueType: 'option',
        width: 120,
        render: (_, row: any) => [
          <Popconfirm 
            key="del" 
            title="是否确认删除？" 
            onConfirm={async () => {
              const res = await deleteEvaluationSelect(row.id);
              if (res !== false) {
                // 删除成功，重新加载该评价项的选项列表
                const current: any = currentCategory as any;
                const serviceType = String(current?.code || current?.name || '');
                const list = await getEvaluationSelect(parentCode, serviceType);
                set_serviceOptionsMap((old) => ({
                  ...old,
                  [parentCode]: (list || []) as any,
                }));
              }
            }}
          >
            <a>删除</a>
          </Popconfirm>
        ],
      },
    ];

    return (
      <div className="SE-ExpandWrap">
        <KCTable
          newVer
          columns={columns as ProColumns[]}
          dataSource={rows}
          rowKey={(r: any) => String(r.id ?? r.code)}
          dragSortKey="id"
          dragType="KC_TABLE_NESTED_ROW"
          pagination={false}
          toolBarRender={false as any}
          search={false as any}
          options={false as any}
          bordered={false as any}
          size={'small' as any}
          dragSort
          onDragSortEnd={(next)=>{ 
            set_serviceOptionsMap((old)=> ({ ...old, [parentCode]: next })); 
          }}
        />
      </div>
    );
  };

  // 表格展开回调
  const onExpand = async (expanded: boolean, record: any) => {
    const node: any = currentCategory as any;
    const rowKey = node?.nodeType === 'service' ? record.itemCode : record.projectId;
    
    // 更新展开行状态
    if (expanded) {
      set_expandedRowKeys((prev) => [...prev, rowKey]);
    } else {
      set_expandedRowKeys((prev) => prev.filter(k => k !== rowKey));
      return;
    }
    
    // 加载数据
    if (node && node.nodeType === 'service') {
      const serviceType = String(node.code || node.name || '');
      const list = await getEvaluationSelect(record.itemCode, serviceType);
      set_serviceOptionsMap((old: Record<string, { id: number | string; hospId?: string; itemCode: string; code: string; name: string; value: number; sort: number }[]>) => ({
        ...old,
        [record.itemCode]: (list || []) as { id: number | string; hospId?: string; itemCode: string; code: string; name: string; value: number; sort: number }[],
      }));
    } else {
      const opts = await getOptionList({ projectId: record.projectId });
      set_projectOptionsMap((old) => ({ ...old, [record.projectId]: opts || [] }));
    }
  };
  
  // 收起所有展开行
  const collapseAllRows = () => {
    set_expandedRowKeys([]);
  };

  useEffect(() => { fetchTree(); }, []);
  useEffect(() => { if (sysModalOpen) fetchSystemTree(); }, [sysModalOpen]);
  useEffect(() => {
    if (currentCategory) {
      set_tableParams((p) => ({ ...p, current: 1, categoryId: currentCategory.id }));
      set_reload(true);
      // 切换分类时清空展开行
      set_expandedRowKeys([]);
    }
  }, [currentCategory]);

  return (
    <>
    <div className="SystemNavMana">
      <div className="leftTree">
        <div className="search" style={{display:'flex',gap:8,alignItems:'center'}}>
          <Input className="searchInput" placeholder="请输入" size="small" allowClear onChange={(e)=>setSearchValue(e.target.value)} />
          <Tooltip title="添加系统">
            <span className="add" onClick={()=> set_sysModalOpen(true)}>
              <IconFont style={{ color: '#17181A', fontSize: 12 }} type="icon-xinzeng" />
            </span>
          </Tooltip>
        </div>
        <div className="treeeWrap">
          {categoryTree && categoryTree.length>0 && (
            <DirectoryTree
              fieldNames={{ title:'name', key:'id' }}
              rootStyle={{ overflowY:'scroll', overflowX:'hidden' }}
              onSelect={async (keys, info)=> {
                const node = info.node as any;
                // 仅允许选择服务节点
                if (node.nodeType !== 'service') return;
                set_currentCategory(node);
                set_tableParams((p)=>({ ...p, current:1, categoryId: node.id }));
                set_reload(true);
                // 服务节点：拉取右侧评价项（dataSource 渲染）
                await loadServiceEvalItems(String(node.code || node.name));
              }}
              onExpand={(keys)=>{ setExpandedKeys(keys as React.Key[]); setAutoExpandParent(false);} }
              expandedKeys={expandedKeys}
              autoExpandParent={autoExpandParent}
              selectedKeys={currentCategory && (currentCategory as any).nodeType==='service' ? [currentCategory.id] : []}
              blockNode
              className="KC-DirectoryTree"
              icon={() => null}
              titleRender={(nodeData: any) => {
                const strTitle = nodeData.name as string;
                const index = strTitle.indexOf(searchValue);
                const beforeStr = strTitle.substring(0, index);
                const afterStr = strTitle.slice(index + searchValue.length);
                const title = index > -1 ? (
                  <span>
                    {beforeStr}
                    <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
                    {afterStr}
                  </span>
                ) : (
                  <span className="strTitle">{strTitle}</span>
                );
                const isDirectory = Array.isArray(nodeData.children) && nodeData.children.length > 0;
                return (
                  <div style={{display:'flex',alignItems:'center',height:32}}>
                    <span className="node-title-area" style={{flex:1, minWidth:0}}>{title}</span>
                    {nodeData.nodeType === 'system' && (
                      <span
                        className="inline-add"
                        style={{display:'inline-flex', justifyContent:'center', alignItems:'center'}}
                        onClick={async (e)=>{
                          e.stopPropagation();
                        set_serviceBindSystemId(String(nodeData.id));
                        // 打开前重置已选，避免上次选择残留
                        set_serviceSelected([]);
                        await fetchServiceDict();
                        set_serviceModalOpen(true);
                        }}
                      >
                        <IconFont style={{ color: '#99A6BF', fontSize: 12 }} type="icon-xinzeng" />
                      </span>
                    )}
                  </div>
                );
              }}
              treeData={categoryTree as unknown as DataNode[]}
              switcherIcon={(props:any)=> props.expanded ? (<img style={{ width:20,height:20, position:'relative', top:5 }} src={closeIcon} />) : (<img style={{ width:20,height:20, position:'relative', top:5 }} src={expandedIcon} />)}
            />
          )}
        </div>
      </div>

      <div className="rightContent">
        <div className="tableToolbar">
          <div className="filter">
            <span style={{ fontSize: 16, fontWeight: 500, color: '#17181A' }}>
              {currentCategory?.name || '-'}
            </span>
          </div>
          <div className={'btnGroup'}>
            {expandedRowKeys.length > 0 && (
              <span className="collapse" onClick={collapseAllRows}>
                收起所有 ({expandedRowKeys.length})
              </span>
            )}
            <span className="add" onClick={async ()=>{ 
              // 获取当前已有的评价项，用于回显
              const current: any = currentCategory as any;
              if (current && current.nodeType === 'service') {
                const existingItems = await getServiceEvaluationItem(String(current.code || current.name));
                const existingKeys = (existingItems || []).map((item: any) => String(item.itemCode));
                set_evalItemTargetKeys(existingKeys);
              } else {
                set_evalItemTargetKeys([]);
              }
              set_evalItemSelectedKeys([]); 
              await fetchEvaluationItemsDict(); 
              set_evalItemModalOpen(true); 
            }}>
              添加
            </span>
          </div>
          <ModalForm
            title="新增评价项目"
            width={520}
            trigger={<span style={{ display:'none' }} />}
            onFinish={async (values) => {
              if (!currentCategory) return false;
              const ok = await addProject({ categoryId: currentCategory.id, ...(values as any) });
              if (ok) set_reload(true);
              return !!ok;
            }}
          >
            <ProFormText name="projectCode" label="项目代码" placeholder="请输入" rules={[{ required: true, message: '必填' }]} />
            <ProFormText name="projectName" label="项目名称" placeholder="请输入" rules={[{ required: true, message: '必填' }]} />
            <ProFormDigit name="weight" label="权重%" min={0} max={100} placeholder="0-100" rules={[{ required: true, message: '必填' }]} />
          </ModalForm>
        </div>

        {currentCategory && (
          <KCTable
            key={`table-${currentCategory.id}`}
            newVer
            reload={(currentCategory as any)?.nodeType === 'service' ? false : reload}
            params={(currentCategory as any)?.nodeType === 'service' ? undefined : tableParams}
            rowKey={(((currentCategory as any)?.nodeType === 'service')
              ? ((r: any) => String(r?.itemCode ?? ''))
              : ((r: any) => String(r?.projectId ?? ''))) as any}
            dragSortKey={(currentCategory as any)?.nodeType === 'service' ? 'itemCode' : 'projectId'}
            dragType="KC_TABLE_MAIN_ROW"
            disabledDragKeys={expandedRowKeys}
            scroll={{ y: `calc(100vh - 240px)` }}
            columns={((currentCategory as any)?.nodeType === 'service' ? evalItemColumns : projectColumns) as ProColumns[]}
            request={(((currentCategory as any)?.nodeType === 'service') ? undefined : ((p: any, s: any, f: any) => getTableData(p))) as any}
            expandable={{
              expandedRowRender: (currentCategory as any)?.nodeType === 'service' ? expandedRowRenderService : expandedRowRender,
              onExpand,
              expandedRowKeys,
              onExpandedRowsChange: (keys: readonly React.Key[]) => set_expandedRowKeys([...keys]),
              expandIconColumnIndex: 1  // 展开图标显示在第2列，第1列留给拖拽手柄
            }}
            pagination={false}
            dragSort={(currentCategory as any)?.nodeType === 'service'}
            dataSource={((currentCategory as any)?.nodeType === 'service') ? evalItemRows : undefined}
            onDragSortEnd={(rows: any[])=>{ 
              set_evalItemRows(rows); 
              set_useLocalEvalOrder(true);
            }}
          />
        )}
      </div>
    </div>
    <Modal
      title="添加系统"
      open={sysModalOpen}
      onCancel={()=> set_sysModalOpen(false)}
      onOk={async ()=>{
        const flat = (nodes: SystemTreeNode[]): SystemTreeNode[] => nodes.reduce<SystemTreeNode[]>((acc, n)=>{
          acc.push(n);
          if (n.children && n.children.length) acc.push(...flat(n.children));
          return acc;
        }, []);
        const all = flat(systemTree);
        const payload = all
          .filter(n => sysTargetKeys.includes(n.code) && n.type === 3)
          .map(n => ({ systemId: n.code, systemName: n.name }));
        if (payload.length === 0) {
          message.warning('请选择系统');
          return;
        }
        const ok = await addSystems(payload as any);
        if (ok) {
          set_sysModalOpen(false);
          // 刷新左侧“已选系统”列表
          set_reload(true);
          fetchTree();
        }
      }}
      width={720}
      destroyOnClose
    >
      <Transfer
        className="tree-transfer"
        listStyle={{ height: 600, overflowY: 'auto' }}
        dataSource={(function buildFlat(){
          const res: any[] = [];
          const walk = (list: SystemTreeNode[], parentChecked: boolean)=>{
            list.forEach(n=>{
              res.push({ key: n.code, code: n.code, name: n.name, type: n.type, node: n });
              if (n.children && n.children.length) walk(n.children, false);
            })
          };
          walk(systemTree, false);
          return res;
        })()}
        rowKey={(item)=> item.code}
        titles={[`待选项`, `已选项`]}
        targetKeys={sysTargetKeys}
        selectedKeys={sysSelectedKeys}
        showSearch
        locale={{ itemUnit:'项', itemsUnit:'项', searchPlaceholder:'请输入' }}
        render={(item)=> item.name}
        onChange={(nextTargetKeys)=> set_sysTargetKeys(nextTargetKeys as string[])}
        onSelectChange={(sourceSelectedKeys, targetSelectedKeys)=> set_sysSelectedKeys([...(sourceSelectedKeys as string[]), ...(targetSelectedKeys as string[])])}
      >
        {({ direction, onItemSelect, onItemSelectAll, selectedKeys })=>{
          if (direction === 'left') {
            const treeData = (function toTree(list: SystemTreeNode[]): any[] {
              return list.map((n: SystemTreeNode): any => ({
                key: n.code,
                title: n.name,
                // 不再用 children 判断是否可勾选；统一允许勾选，由 onCheck 决定加入哪些 key
                disabled: false,
                children: n.children ? (toTree(n.children) as any[]) : undefined,
              }));
            })(systemTree);

            const checkedKeys = [...selectedKeys, ...sysTargetKeys];
            return (
              <Tree
                checkable
                defaultExpandAll
                checkedKeys={checkedKeys}
                treeData={treeData as any}
                height={480}
                expandedKeys={sysExpandedKeys}
                onExpand={(keys)=> set_sysExpandedKeys(keys as string[])}
                onCheck={(keys, { node })=>{
                  // 仅加入“系统叶子”：type==3，或 type==5 但无 children（后端把系统标成5时兜底）
                  const isSystemLeafByCode = (code: string) => {
                    const flat = (function flat(){
                      const res: any[] = [];
                      const walk = (list: SystemTreeNode[])=>{ list.forEach(nn=>{ res.push({ code: nn.code, type: nn.type, children: nn.children }); if(nn.children) walk(nn.children); }); };
                      walk(systemTree); return res;
                    })();
                    const found = flat.find(i=> i.code===code);
                    if (!found) return false;
                    const noChildren = !found.children || found.children.length===0;
                    return found.type===3 || (found.type===5 && noChildren);
                  };

                  const getChildCodes = (n:any): string[] => {
                    if (!n.children || n.children.length===0) return [n.key as string];
                    return n.children.reduce((acc:any,c:any)=> acc.concat(getChildCodes(c)), []);
                  };

                  const isSelect = !(node as any).checked;
                  const candidate = (node.children && node.children.length>0) ? getChildCodes(node) : [node.key as string];
                  const systemLeafKeys = candidate.filter((code)=> isSystemLeafByCode(code));
                  onItemSelectAll(systemLeafKeys as string[], isSelect);
                }}
              />
            );
          }
          return null;
        }}
      </Transfer>
    </Modal>
    <Modal
      title="添加服务"
      open={serviceModalOpen}
      onCancel={()=> { set_serviceModalOpen(false); set_serviceSelected([]); set_serviceBindSystemId(''); }}
      confirmLoading={serviceSaving}
      onOk={async ()=> {
        if (!serviceBindSystemId) { set_serviceModalOpen(false); return; }
        try {
          set_serviceSaving(true);
          const ok: any = await addServiceTypes(serviceBindSystemId, serviceSelected);
          if (ok) {
            set_serviceModalOpen(false);
            set_serviceSelected([]);
            set_serviceBindSystemId('');
            // 刷新左侧列表
            set_reload(true);
            fetchTree();
          }
        } finally {
          set_serviceSaving(false);
        }
      }}
      width={560}
      destroyOnClose
    >
      <Transfer
        className="ServiceTransfer"
        style={{ width: '100%' }}
        titles={[`待选项`,`已选项`]}
        dataSource={serviceDict}
        rowKey={(item)=> item.key}
        render={(item)=> item.title}
        targetKeys={serviceSelected}
        onChange={(next)=> set_serviceSelected(next as string[])}
        listStyle={{ height: 460, width: 'calc(50% - 32px)' }}
        operationStyle={{ margin: '0 12px', display: 'flex', alignItems: 'center' }}
        locale={{ itemUnit:'项', itemsUnit:'项', searchPlaceholder:'请输入' }}
        showSearch
      />
    </Modal>
    <Modal
      title="评价项目"
      open={evalItemModalOpen}
      onCancel={()=> { set_evalItemModalOpen(false); set_evalItemTargetKeys([]); set_evalItemSelectedKeys([]); }}
      onOk={async ()=> {
        // 依据当前选中的服务类型保存评价项目
        const current: any = currentCategory as any;
        if (!current || current.nodeType !== 'service') { set_evalItemModalOpen(false); return; }
        // 从字典中匹配详细信息
        const itemCodes = evalItemTargetKeys.map((k, idx)=>{
          const found = evalItemDict.find(i=> i.key === k);
          return { itemCode: k, itemName: found?.title || k, itemValue: 1, sort: idx + 1 };
        });
        const ok: any = await addEvaluationItem(String(current.code || current.name), itemCodes);
        if (ok) {
          set_evalItemModalOpen(false);
          set_evalItemTargetKeys([]);
          set_evalItemSelectedKeys([]);
          // 刷新右侧表格：重新加载评价项列表
          await loadServiceEvalItems(String(current.code || current.name));
        }
      }}
      width={800}
      destroyOnClose
    >
      <Transfer
        titles={[`待选项`,`已选项`]}
        dataSource={evalItemDict}
        rowKey={(item)=> item.key}
        render={(item)=> item.value ? `${item.code} - ${item.title}(${item.value})` : `${item.code} - ${item.title}`}
        targetKeys={evalItemTargetKeys}
        selectedKeys={evalItemSelectedKeys}
        onChange={(next)=> set_evalItemTargetKeys(next as string[])}
        onSelectChange={(l,r)=> set_evalItemSelectedKeys([...(l as string[]), ...(r as string[])])}
        listStyle={{ height: 460, width: 'calc(50% - 24px)' }}
        operationStyle={{ margin: '0 12px', display: 'flex', alignItems: 'center' }}
        showSearch
        locale={{ itemUnit:'项', itemsUnit:'项', searchPlaceholder:'请输入' }}
      />
    </Modal>
    <Modal
      title="添加选项"
      open={selectModalOpen}
      onCancel={()=> { set_selectModalOpen(false); set_selectTargetKeys([]); set_selectSelectedKeys([]); set_bindItemCode(''); }}
      onOk={async ()=> {
        const selectCodes = selectTargetKeys.map((k, idx)=>{
          const found = selectDict.find(i=> i.key === k);
          return { itemCode: k, itemName: found?.title || k, itemValue: 1, sort: idx + 1 };
        });
        const ok: any = await addEvaluationSelect(bindItemCode, selectCodes);
        if (ok !== false) {
          set_selectModalOpen(false);
          set_selectTargetKeys([]);
          set_selectSelectedKeys([]);
          // 重新加载该评价项的选项数据
          const current: any = currentCategory as any;
          const serviceType = String(current?.code || current?.name || '');
          const list = await getEvaluationSelect(bindItemCode, serviceType);
          set_serviceOptionsMap((old) => ({
            ...old,
            [bindItemCode]: (list || []) as any,
          }));
          set_bindItemCode('');
          set_reload(true);
        }
      }}
      width={560}
      destroyOnClose
    >
      <Transfer
        titles={[`待选项`,`已选项`]}
        dataSource={selectDict}
        rowKey={(item)=> item.key}
        render={(item)=> item.title}
        targetKeys={selectTargetKeys}
        selectedKeys={selectSelectedKeys}
        onChange={(next)=> set_selectTargetKeys(next as string[])}
        onSelectChange={(l,r)=> set_selectSelectedKeys([...(l as string[]), ...(r as string[])])}
        listStyle={{ height: 360, width: 'calc(50% - 32px)' }}
        operationStyle={{ margin: '0 12px', display: 'flex', alignItems: 'center' }}
        showSearch
        locale={{ itemUnit:'项', itemsUnit:'项', searchPlaceholder:'请输入' }}
      />
    </Modal>
  </>
  );
};

export default ServiceEvaluatePage;


