import type { CrossTemplateScalarCandidate, CrossTemplateSourceTemplate, TemplateBinding, TemplateFieldOption } from '../../src/domain/types';

import { mount } from '@vue/test-utils';

import Antd, { Select } from 'ant-design-vue';
import { beforeAll, describe, expect, it, vi } from 'vitest';

import FieldEditor from '../../src/components/FieldEditor.vue';

beforeAll(() => {
  window.matchMedia ??= () =>
    ({
      addEventListener() {},
      addListener() {},
      dispatchEvent: () => false,
      matches: false,
      media: '',
      onchange: null,
      removeEventListener() {},
      removeListener() {},
    }) as MediaQueryList;
  globalThis.ResizeObserver ??= class ResizeObserver {
    disconnect() {}
    observe() {}
    unobserve() {}
  };
});

const fields: TemplateFieldOption[] = [
  {
    alias: '样品编号',
    controlConfig: { defaultValue: 'S-001', placeholder: '请输入样品编号' },
    fieldCode: 'sample_code',
    fieldId: 'field-global',
    fieldVersionId: 'version-global',
    isCurrent: true,
    label: '样品编号',
    required: true,
    scope: 'GLOBAL',
    source: 'SYSTEM',
    type: 'TEXT',
    versionStatus: 'PUBLISHED',
  },
  {
    alias: '检测结论',
    controlConfig: {
      options: [
        { display: '合格', value: 'PASS' },
        { display: '不合格', value: 'FAIL' },
      ],
      placeholder: '请选择',
    },
    fieldCode: 'result',
    fieldId: 'field-private',
    fieldVersionId: 'version-private',
    isCurrent: true,
    label: '检测结论',
    required: false,
    scope: 'TEMPLATE',
    source: 'NONE',
    type: 'SELECT',
    versionStatus: 'PRE_RELEASE',
  },
];
const crossTemplateCandidates: CrossTemplateScalarCandidate[] = [
  {
    sourceFieldCode: 'source_result',
    sourceFieldId: 'source-field',
    sourceFieldName: '来源检验结果',
    sourceFieldType: 'DECIMAL',
    sourceFieldVersionId: 'source-version-2',
    sourceTemplateCode: 'SOURCE-TPL-001',
    sourceTemplateId: 'source-template',
  },
];
const crossTemplateSourceTemplates: CrossTemplateSourceTemplate[] = [
  { sourceTemplateCode: 'SOURCE-TPL-001', sourceTemplateId: 'source-template' },
  { sourceTemplateCode: 'ENV-TPL-002', sourceTemplateId: 'environment-template' },
];
const editableCheckbox: TemplateFieldOption = {
  alias: '合格',
  controlConfig: { defaultChecked: false },
  fieldCode: 'passed',
  fieldId: 'passed-field',
  fieldVersionId: 'passed-version',
  isCurrent: true,
  label: '合格',
  required: false,
  scope: 'TEMPLATE',
  source: 'NONE',
  type: 'CHECKBOX',
  versionStatus: 'PUBLISHED',
};
const readOnlyCheckbox: TemplateFieldOption = {
  ...editableCheckbox,
  alias: '系统判定',
  fieldCode: 'system_result',
  fieldId: 'system-result-field',
  fieldVersionId: 'system-result-version',
  label: '系统判定',
  source: 'SYSTEM',
};
function checkboxBinding(id: string, groupCode: string, stepId: string): TemplateBinding {
  return {
    checkboxGroupCode: groupCode,
    controlAlias: id,
    controlConfig: { defaultChecked: false },
    controlRole: 'PRIMARY',
    controlTag: `eln.field.${id}`,
    controlType: 'CHECKBOX',
    fieldCode: id,
    fieldId: `${id}-field`,
    fieldVersionId: `${id}-version`,
    id,
    primaryBindingId: null,
    status: 'ACTIVE',
    stepId,
    templateId: 'template',
    version: 1,
  };
}

function mountEditor(disabled = false) {
  return mount(FieldEditor, { props: { disabled, fields }, global: { plugins: [Antd] } });
}

describe('fieldEditor', () => {
  it('将标注当前位置放在两个字段入口上方', () => {
    const wrapper = mountEditor();

    expect(
      wrapper
        .findAll('[data-test="submit-field"], [data-test="open-private-field"], [data-test="open-cross-template"]')
        .map((item) => item.attributes('data-test')),
    ).toEqual(['submit-field', 'open-private-field', 'open-cross-template']);
    expect(wrapper.get('[data-test="submit-field"]').classes()).toContain('ant-btn-primary');
    expect(wrapper.get('[data-test="open-private-field"]').classes()).toContain('ant-btn-dashed');
    expect(wrapper.get('[data-test="open-cross-template"]').classes()).toContain('ant-btn-dashed');
  });

  it('按公共字段与本模板字段分组搜索并标记预发布风险', async () => {
    const wrapper = mountEditor();
    const select = wrapper.findComponent(Select);

    expect(select.props('allowClear')).toBe(true);
    expect(select.props('options')).toEqual([
      expect.objectContaining({ label: '公共字段', options: [expect.objectContaining({ value: 'version-global' })] }),
      expect.objectContaining({ label: '本模板字段', options: [expect.objectContaining({ value: 'version-private' })] }),
    ]);
    select.vm.$emit('update:value', 'version-private');
    await wrapper.vm.$nextTick();
    expect(wrapper.get('[data-test="pre-release-risk"]').text()).toContain('预发布');
    expect(wrapper.text()).toContain('检测结论');

    select.vm.$emit('update:value', undefined);
    await wrapper.vm.$nextTick();
    expect(wrapper.find('[data-test="field-properties"]').exists()).toBe(false);
    expect(wrapper.get('[data-test="submit-field"]').attributes('disabled')).toBeDefined();
  });

  it('不提供自由文本字段编码，并平铺展示全部只读属性', async () => {
    const wrapper = mountEditor();
    expect(wrapper.find('[data-test="field-code"]').exists()).toBe(false);
    expect(wrapper.find('[data-test="mode-editor"]').exists()).toBe(false);
    expect(wrapper.find('[data-test="annotation-mode"]').exists()).toBe(true);

    wrapper.findComponent(Select).vm.$emit('update:value', 'version-global');
    await wrapper.vm.$nextTick();
    expect(wrapper.get('[data-test="field-alias-readonly"]').text()).toContain('样品编号');
    expect(wrapper.get('[data-test="field-scope-readonly"]').text()).toContain('公共字段');
    expect(wrapper.get('[data-test="field-type-readonly"]').text()).toContain('单行文本');
    expect(wrapper.get('[data-test="field-required-readonly"]').text()).toContain('必填');
    expect(wrapper.find('[data-test="field-config"]').exists()).toBe(false);
    expect(wrapper.get('[data-test="field-properties"]').classes()).toContain('field-properties');
    expect(wrapper.findAll('.field-summary')).toHaveLength(1);
    expect(wrapper.get('[data-test="field-placeholder-readonly"]').text()).toContain('请输入样品编号');
    expect(wrapper.get('[data-test="field-default-readonly"]').text()).toContain('S-001');
  });

  it('只提交选中的后端字段版本，不允许覆盖 required/type/binding', async () => {
    const wrapper = mountEditor();
    wrapper.findComponent(Select).vm.$emit('update:value', 'version-global');
    await wrapper.vm.$nextTick();
    await wrapper.get('[data-test="submit-field"]').trigger('click');

    expect(wrapper.emitted('submit')).toEqual([[fields[0]]]);
    expect(wrapper.html()).not.toContain('binding');
  });

  it('重复行模式提交组编码并固定使用所选字段版本', async () => {
    const wrapper = mountEditor();
    wrapper.findComponent(Select).vm.$emit('update:value', 'version-private');
    wrapper.get('[data-test="annotation-mode"]').findComponent({ name: 'ASegmented' }).vm.$emit('update:value', 'repeat');
    await wrapper.vm.$nextTick();
    expect(wrapper.get('[data-test="annotation-mode"]').text()).toContain('重复行');
    expect(wrapper.get('[data-test="annotation-mode"]').text()).not.toContain('重复列');
    wrapper.getComponent({ name: 'AAutoComplete' }).vm.$emit('update:value', 'test_results');
    await wrapper.vm.$nextTick();
    expect((wrapper.get('[data-test="repeat-min-rows"]').element as HTMLInputElement).value).toBe('0');
    expect((wrapper.get('[data-test="repeat-max-rows"]').element as HTMLInputElement).value).toBe('100');
    await wrapper.get('[data-test="submit-field"]').trigger('click');

    expect(wrapper.emitted('submit-repeat')).toEqual([[fields[1], { groupCode: 'test_results', maxRows: 100, minRows: 0 }]]);
  });

  it('重复组行数约束无效时禁止提交', async () => {
    const wrapper = mountEditor();
    wrapper.findComponent(Select).vm.$emit('update:value', 'version-private');
    wrapper.get('[data-test="annotation-mode"]').findComponent({ name: 'ASegmented' }).vm.$emit('update:value', 'repeat');
    await wrapper.vm.$nextTick();
    wrapper.getComponent({ name: 'AAutoComplete' }).vm.$emit('update:value', 'results');
    await wrapper.vm.$nextTick();
    await wrapper.get('[data-test="repeat-min-rows"]').setValue('5');
    await wrapper.get('[data-test="repeat-max-rows"]').setValue('4');
    await wrapper.vm.$nextTick();

    expect(wrapper.get('[data-test="submit-field"]').attributes('disabled')).toBeDefined();
    await wrapper.get('[data-test="submit-field"]').trigger('click');
    expect(wrapper.emitted('submit-repeat')).toBeUndefined();
  });

  it('重复组编码提供输入提示，格式非法时显示中文校验并禁止提交', async () => {
    const wrapper = mount(FieldEditor, {
      props: { fields, repeatGroups: [{ groupCode: 'results', minRows: 2, maxRows: 20 }] },
      global: { plugins: [Antd] },
    });
    wrapper.findComponent(Select).vm.$emit('update:value', 'version-private');
    wrapper.get('[data-test="annotation-mode"]').findComponent({ name: 'ASegmented' }).vm.$emit('update:value', 'repeat');
    await wrapper.vm.$nextTick();

    const groupInput = wrapper.getComponent({ name: 'AAutoComplete' });
    expect(groupInput.props('placeholder')).toBe('输入新编码或选择已有重复组');
    expect(groupInput.props('options')).toEqual([{ label: 'results（2 至 20 行）', value: 'results' }]);
    expect(wrapper.find('[data-test="repeat-group-error"]').exists()).toBe(false);

    groupInput.vm.$emit('update:value', '含中文');
    await wrapper.vm.$nextTick();
    expect(wrapper.get('[data-test="repeat-group-error"]').text()).toContain('字母、数字、下划线或连字符');
    expect(wrapper.get('[data-test="submit-field"]').attributes('disabled')).toBeDefined();
    await wrapper.get('[data-test="submit-field"]').trigger('click');
    expect(wrapper.emitted('submit-repeat')).toBeUndefined();
  });

  it('生成重复组编码后先展示建议，确认后才替换当前编码', async () => {
    const suggestCode = vi.fn(async () => 'jianyan_jieguo');
    const wrapper = mount(FieldEditor, {
      props: { fields, suggestCode },
      global: { plugins: [Antd] },
    });
    wrapper.get('[data-test="annotation-mode"]').findComponent({ name: 'ASegmented' }).vm.$emit('update:value', 'repeat');
    await wrapper.vm.$nextTick();
    const repeatGroupInput = wrapper.findAllComponents({ name: 'AAutoComplete' }).find((item) => item.attributes('data-test') === 'repeat-group-code');
    expect(repeatGroupInput).toBeDefined();
    repeatGroupInput!.vm.$emit('update:value', 'original_group');
    await wrapper.vm.$nextTick();

    expect(wrapper.get('[data-test="repeat-code-assist"]').attributes('aria-label')).toBe('中文转拼音');
    await wrapper.get('[data-test="repeat-code-assist"]').trigger('click');
    expect(wrapper.get('[data-test="code-assist-modal"]').text()).toContain('生成重复组编码');
    expect(wrapper.get('[data-test="code-assist-generate"]').attributes('disabled')).toBeDefined();

    await wrapper.get('[data-test="code-assist-text"]').setValue('检验结果');
    await wrapper.get('[data-test="code-assist-generate"]').trigger('click');
    await vi.waitFor(() => expect(suggestCode).toHaveBeenCalledWith('检验结果'));

    expect(wrapper.find('[data-test="code-assist-modal"]').exists()).toBe(true);
    expect(wrapper.get('[data-test="code-assist-suggestion"]').attributes('value')).toBe('jianyan_jieguo');
    expect(repeatGroupInput!.props('value')).toBe('original_group');

    await wrapper.get('[data-test="code-assist-confirm"]').trigger('click');

    expect(wrapper.find('[data-test="code-assist-modal"]').exists()).toBe(false);
    expect(repeatGroupInput!.props('value')).toBe('jianyan_jieguo');
  });

  it('仅可编辑复选框显示选择组，并按当前步骤提供成员数候选', async () => {
    const wrapper = mount(FieldEditor, {
      props: {
        bindings: [
          checkboxBinding('passed', 'inspection_result', 'step-1'),
          checkboxBinding('failed', 'inspection_result', 'step-1'),
          checkboxBinding('other', 'other_step_group', 'step-2'),
        ],
        currentStepId: 'step-1',
        fields: [...fields, editableCheckbox, readOnlyCheckbox],
      },
      global: { plugins: [Antd] },
    });
    const fieldSelect = wrapper.findAllComponents(Select)[0]!;

    fieldSelect.vm.$emit('update:value', editableCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();

    const groupInput = wrapper.getComponent({ name: 'AAutoComplete' });
    expect(wrapper.find('[data-test="checkbox-group-code"]').exists()).toBe(true);
    expect(groupInput.props('options')).toEqual([{ label: 'inspection_result（2 个成员）', value: 'inspection_result' }]);

    fieldSelect.vm.$emit('update:value', readOnlyCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();
    expect(wrapper.find('[data-test="checkbox-group-code"]').exists()).toBe(false);
  });

  it('标注成功只清空字段并保留选择组，切换作用域后清空组编码', async () => {
    const wrapper = mount(FieldEditor, {
      props: { bindings: [], currentStepId: 'step-1', fields: [...fields, editableCheckbox], resetToken: 0 },
      global: { plugins: [Antd] },
    });
    const fieldSelect = wrapper.findAllComponents(Select)[0]!;
    fieldSelect.vm.$emit('update:value', editableCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();
    const groupInput = wrapper.getComponent({ name: 'AAutoComplete' });
    groupInput.vm.$emit('update:value', 'inspection_result');
    await wrapper.vm.$nextTick();
    await wrapper.get('[data-test="submit-field"]').trigger('click');

    expect(wrapper.emitted('submit')).toEqual([
      [editableCheckbox, { groupCode: 'inspection_result', maxSelected: 1, minSelected: 0 }],
    ]);
    await wrapper.setProps({ resetToken: 1 });
    expect(fieldSelect.props('value')).toBeUndefined();
    expect(groupInput.props('value')).toBe('inspection_result');

    await wrapper.setProps({ currentStepId: 'step-2' });
    expect(groupInput.props('value')).toBe('');
  });

  it('公共复选框使用推荐选择组预填任意上下限', async () => {
    const recommended = {
      ...editableCheckbox,
      recommendedCheckboxGroupCode: 'review_result',
      recommendedCheckboxMaxSelected: null,
      recommendedCheckboxMinSelected: 2,
      scope: 'GLOBAL' as const,
    };
    const wrapper = mount(FieldEditor, {
      props: { fields: [...fields, recommended] },
      global: { plugins: [Antd] },
    });

    wrapper.findAllComponents(Select)[0]!.vm.$emit('update:value', recommended.fieldVersionId);
    await wrapper.vm.$nextTick();

    expect(wrapper.getComponent({ name: 'AAutoComplete' }).props('value')).toBe('review_result');
    expect((wrapper.get('[data-test="checkbox-group-min"]').element as HTMLInputElement).value).toBe('2');
    expect(wrapper.get('[data-test="checkbox-group-unlimited"]').attributes('aria-checked')).toBe('true');
    expect(wrapper.find('[data-test="checkbox-group-max"]').exists()).toBe(false);
    await wrapper.get('[data-test="submit-field"]').trigger('click');
    expect(wrapper.emitted('submit')).toEqual([
      [recommended, { groupCode: 'review_result', maxSelected: null, minSelected: 2 }],
    ]);
  });

  it('选择已有选择组时回填并锁定模板权威规则', async () => {
    const wrapper = mount(FieldEditor, {
      props: {
        bindings: [checkboxBinding('passed', 'inspection_result', 'step-1')],
        checkboxGroups: [{ groupCode: 'inspection_result', maxSelected: 3, minSelected: 1, version: 2 }],
        currentStepId: 'step-1',
        fields: [...fields, editableCheckbox],
      },
      global: { plugins: [Antd] },
    });
    wrapper.findAllComponents(Select)[0]!.vm.$emit('update:value', editableCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();
    wrapper.getComponent({ name: 'AAutoComplete' }).vm.$emit('update:value', 'inspection_result');
    await wrapper.vm.$nextTick();

    expect((wrapper.get('[data-test="checkbox-group-min"]').element as HTMLInputElement).value).toBe('1');
    expect((wrapper.get('[data-test="checkbox-group-max"]').element as HTMLInputElement).value).toBe('3');
    expect(wrapper.get('[data-test="checkbox-group-min"]').attributes('disabled')).toBeDefined();
    expect(wrapper.get('[data-test="checkbox-group-max"]').attributes('disabled')).toBeDefined();
  });

  it('选择组编码非法时显示中文校验并禁止提交', async () => {
    const wrapper = mount(FieldEditor, {
      props: { bindings: [], currentStepId: 'step-1', fields: [...fields, editableCheckbox] },
      global: { plugins: [Antd] },
    });
    wrapper.findAllComponents(Select)[0]!.vm.$emit('update:value', editableCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();
    wrapper.getComponent({ name: 'AAutoComplete' }).vm.$emit('update:value', '含中文');
    await wrapper.vm.$nextTick();

    expect(wrapper.get('[data-test="checkbox-group-error"]').text()).toContain('字母、数字、下划线或连字符');
    expect(wrapper.get('[data-test="submit-field"]').attributes('disabled')).toBeDefined();
  });

  it('选择组编码生成失败时保留窗口、中文输入和原编码', async () => {
    const suggestCode = vi.fn(async () => {
      throw new Error('分词服务暂不可用');
    });
    const wrapper = mount(FieldEditor, {
      props: { bindings: [], currentStepId: 'step-1', fields: [...fields, editableCheckbox], suggestCode },
      global: { plugins: [Antd] },
    });
    wrapper.findAllComponents(Select)[0]!.vm.$emit('update:value', editableCheckbox.fieldVersionId);
    await wrapper.vm.$nextTick();
    const checkboxGroupInput = wrapper
      .findAllComponents({ name: 'AAutoComplete' })
      .find((item) => item.attributes('data-test') === 'checkbox-group-code');
    expect(checkboxGroupInput).toBeDefined();
    checkboxGroupInput!.vm.$emit('update:value', 'original_group');
    await wrapper.vm.$nextTick();

    expect(wrapper.get('[data-test="checkbox-code-assist"]').attributes('aria-label')).toBe('中文转拼音');
    await wrapper.get('[data-test="checkbox-code-assist"]').trigger('click');
    expect(wrapper.get('[data-test="code-assist-modal"]').text()).toContain('生成选择组编码');
    await wrapper.get('[data-test="code-assist-text"]').setValue('检验结果');
    await wrapper.get('[data-test="code-assist-generate"]').trigger('click');
    await vi.waitFor(() => expect(wrapper.get('[data-test="code-assist-error"]').text()).toContain('分词服务暂不可用'));

    expect(wrapper.get('[data-test="code-assist-text"]').attributes('value')).toBe('检验结果');
    expect(checkboxGroupInput!.props('value')).toBe('original_group');
    expect(wrapper.find('[data-test="code-assist-modal"]').exists()).toBe(true);
  });

  it('选择已有重复组时回填并锁定版本约束', async () => {
    const wrapper = mount(FieldEditor, {
      props: { fields, repeatGroups: [{ groupCode: 'results', minRows: 2, maxRows: 20 }] },
      global: { plugins: [Antd] },
    });
    wrapper.get('[data-test="annotation-mode"]').findComponent({ name: 'ASegmented' }).vm.$emit('update:value', 'repeat');
    await wrapper.vm.$nextTick();
    wrapper.getComponent({ name: 'AAutoComplete' }).vm.$emit('update:value', 'results');
    await wrapper.vm.$nextTick();

    expect((wrapper.get('[data-test="repeat-min-rows"]').element as HTMLInputElement).value).toBe('2');
    expect((wrapper.get('[data-test="repeat-max-rows"]').element as HTMLInputElement).value).toBe('20');
    expect(wrapper.get('[data-test="repeat-min-rows"]').attributes('disabled')).toBeDefined();
    expect(wrapper.get('[data-test="repeat-max-rows"]').attributes('disabled')).toBeDefined();
  });

  it('进入面板内二级页面创建本模板字段并可返回', async () => {
    const wrapper = mountEditor();
    await wrapper.get('[data-test="open-private-field"]').trigger('click');
    expect(wrapper.find('[data-test="private-field-form"]').exists()).toBe(true);
    expect(wrapper.find('[data-test="annotation-main"]').exists()).toBe(false);
    const backButton = wrapper.get('[data-test="private-field-back"]');
    expect(backButton.classes()).toContain('secondary-page-back');
    await wrapper.get('[data-test="private-field-back"]').trigger('click');
    expect(wrapper.find('[data-test="private-field-form"]').exists()).toBe(false);
    expect(wrapper.find('[data-test="annotation-main"]').exists()).toBe(true);

    await wrapper.get('[data-test="open-private-field"]').trigger('click');
    await wrapper.get('[data-test="private-field-name"]').setValue('临时备注');
    await wrapper.get('[data-test="private-field-submit"]').trigger('click');
    expect(wrapper.emitted('create-private')?.[0]?.[0]).toMatchObject({ ziduanMingcheng: '临时备注', shujuLeixing: 'TEXT' });
  });

  it('打开本模板字段页面时使用当前选中文本预填字段名称', async () => {
    const readSelectedText = vi.fn(async () => ' 是否\n  合格 ');
    const wrapper = mount(FieldEditor, {
      props: { fields, readSelectedText },
      global: { plugins: [Antd] },
    });

    await wrapper.get('[data-test="open-private-field"]').trigger('click');
    await vi.waitFor(() => expect(wrapper.find('[data-test="private-field-form"]').exists()).toBe(true));

    expect(readSelectedText).toHaveBeenCalledOnce();
    expect(wrapper.get('[data-test="private-field-name"]').attributes('value')).toBe('是否 合格');
  });

  it('读取选中文本失败时打开空表单并保留字段名称必填校验', async () => {
    const readSelectedText = vi.fn(async () => {
      throw new Error('selection unavailable');
    });
    const wrapper = mount(FieldEditor, {
      props: { fields, readSelectedText },
      global: { plugins: [Antd] },
    });

    await wrapper.get('[data-test="open-private-field"]').trigger('click');
    await vi.waitFor(() => expect(wrapper.find('[data-test="private-field-form"]').exists()).toBe(true));
    expect(wrapper.get('[data-test="private-field-name"]').attributes('value')).toBe('');

    await wrapper.get('[data-test="private-field-submit"]').trigger('click');
    expect(wrapper.emitted('create-private')).toBeUndefined();
    expect(wrapper.get('[data-test="private-field-error"]').text()).toContain('请输入字段名称');
  });

  it('创建本模板复选框时复用当前步骤选择组候选', async () => {
    const wrapper = mount(FieldEditor, {
      props: {
        bindings: [checkboxBinding('passed', 'inspection_result', 'step-1'), checkboxBinding('other', 'other_step_group', 'step-2')],
        currentStepId: 'step-1',
        fields,
      },
      global: { plugins: [Antd] },
    });
    await wrapper.get('[data-test="open-private-field"]').trigger('click');
    await wrapper.get('[data-test="private-field-name"]').setValue('是否复核');
    wrapper.getComponent({ name: 'ASelect' }).vm.$emit('update:value', 'CHECKBOX');
    await wrapper.vm.$nextTick();

    const groupInput = wrapper.getComponent({ name: 'AAutoComplete' });
    expect(groupInput.props('options')).toEqual([{ label: 'inspection_result（1 个成员）', value: 'inspection_result' }]);
    groupInput.vm.$emit('update:value', 'inspection_result');
    await wrapper.get('[data-test="private-field-submit"]').trigger('click');

    expect(wrapper.emitted('create-private')?.[0]?.[0]).toMatchObject({
      checkboxGroupCode: 'inspection_result',
      shujuLeixing: 'CHECKBOX',
    });
  });

  it('用紧凑列表选择引用字段，并在固定详情区展示精确信息', async () => {
    const second = {
      ...crossTemplateCandidates[0]!,
      sourceFieldCode: 'temperature',
      sourceFieldName: '环境温度',
      sourceFieldType: 'TEXT' as const,
      sourceFieldVersionId: 'temperature-version-3',
      sourceTemplateCode: 'ENV-TPL-002',
      sourceTemplateId: 'environment-template',
    };
    const wrapper = mount(FieldEditor, {
      props: {
        crossTemplateCandidates: [...crossTemplateCandidates, second],
        crossTemplateSourceTemplates,
        fields,
      },
      global: { plugins: [Antd] },
    });

    const openCrossTemplate = wrapper.get('[data-test="open-cross-template"]');
    expect(openCrossTemplate.text()).toBe('引用其他模板字段');
    expect(openCrossTemplate.find('.anticon-link').exists()).toBe(true);
    await openCrossTemplate.trigger('click');

    expect(wrapper.emitted('load-cross-template-templates')).toEqual([[]]);
    expect(wrapper.text()).toContain('引用其他模板字段');
    expect(wrapper.getComponent({ name: 'AEmpty' }).classes()).toContain('content-empty');
    const templateSelect = wrapper.getComponent({ name: 'ASelect' });
    expect(templateSelect.props('allowClear')).toBe(true);
    expect(templateSelect.props('options')).toEqual([
      { label: 'SOURCE-TPL-001', value: 'source-template' },
      { label: 'ENV-TPL-002', value: 'environment-template' },
    ]);
    expect(wrapper.get('[data-test="cross-template-search"]').attributes('disabled')).toBeDefined();

    templateSelect.vm.$emit('update:value', 'source-template');
    await wrapper.vm.$nextTick();
    expect(wrapper.emitted('load-cross-template-fields')).toEqual([['source-template']]);
    expect(wrapper.get('[data-test="cross-template-count"]').text()).toContain('1');
    const options = wrapper.findAll('[data-test="cross-template-option"]');
    expect(options).toHaveLength(1);
    expect(options[0]!.get('[data-test="cross-template-field-name"]').text()).toBe('来源检验结果');
    expect(options[0]!.get('[data-test="cross-template-source-template"]').text()).toBe('SOURCE-TPL-001');
    expect(options[0]!.get('[data-test="cross-template-type"]').text()).toBe('数值');
    expect(options[0]!.find('.ant-tag').exists()).toBe(false);
    expect(options[0]!.get('[data-test="cross-template-type"]').classes()).toContain('cross-template-type--decimal');
    expect(options[0]!.text()).not.toContain('source_result');
    expect(options[0]!.text()).not.toContain('source-version-2');

    expect(wrapper.find('[data-test="cross-template-details"]').exists()).toBe(false);
    expect(wrapper.get('[data-test="submit-cross-template"]').attributes('disabled')).toBeDefined();
    wrapper.getComponent({ name: 'ARadioGroup' }).vm.$emit('update:value', 'source-template::source-version-2');
    await wrapper.vm.$nextTick();

    const details = wrapper.get('[data-test="cross-template-details"]');
    expect(details.text()).toContain('SOURCE-TPL-001');
    expect(details.get('[data-test="cross-template-detail-code"]').text()).toBe('source_result');
    expect(details.get('[data-test="cross-template-detail-version"]').text()).toBe('source-version-2');
    const detailValues = details.findAll('[data-test="cross-template-detail-value"]');
    expect(detailValues).toHaveLength(3);
    expect(detailValues.map((value) => value.attributes('title'))).toEqual(['SOURCE-TPL-001', 'source_result', 'source-version-2']);
    expect(wrapper.get('[data-test="cross-template-list"]').classes()).toContain('cross-template-list');
    expect(wrapper.get('[data-test="cross-template-footer"]').classes()).toContain('cross-template-footer');

    templateSelect.vm.$emit('update:value', 'environment-template');
    await wrapper.vm.$nextTick();
    expect(wrapper.emitted('load-cross-template-fields')).toEqual([['source-template'], ['environment-template']]);
    expect(wrapper.find('[data-test="cross-template-details"]').exists()).toBe(false);
    wrapper.getComponent({ name: 'ARadioGroup' }).vm.$emit('update:value', 'environment-template::temperature-version-3');
    await wrapper.vm.$nextTick();
    expect(wrapper.get('[data-test="cross-template-details"]').text()).toContain('ENV-TPL-002');
    expect(wrapper.get('[data-test="cross-template-detail-code"]').text()).toBe('temperature');
    expect(wrapper.get('[data-test="cross-template-detail-version"]').text()).toBe('temperature-version-3');

    await wrapper.get('[data-test="submit-cross-template"]').trigger('click');
    expect(wrapper.emitted('submit-cross-template')).toEqual([[second]]);

    templateSelect.vm.$emit('update:value', undefined);
    await wrapper.vm.$nextTick();
    expect(wrapper.find('[data-test="cross-template-option"]').exists()).toBe(false);
    expect(wrapper.find('[data-test="cross-template-details"]').exists()).toBe(false);
  });

  it('按字段名称、编码或版本筛选所选模板候选', async () => {
    const second = {
      ...crossTemplateCandidates[0]!,
      sourceFieldCode: 'temperature',
      sourceFieldName: '环境温度',
      sourceFieldVersionId: 'temperature-version-3',
    };
    const wrapper = mount(FieldEditor, {
      props: {
        crossTemplateCandidates: [...crossTemplateCandidates, second],
        crossTemplateSourceTemplates,
        fields,
      },
      global: { plugins: [Antd] },
    });

    await wrapper.get('[data-test="open-cross-template"]').trigger('click');
    wrapper.getComponent({ name: 'ASelect' }).vm.$emit('update:value', 'source-template');
    await wrapper.vm.$nextTick();
    await wrapper.get('[data-test="cross-template-search"]').setValue('temperature-version');

    expect(wrapper.text()).toContain('环境温度');
    expect(wrapper.text()).not.toContain('来源检验结果');
  });

  it('相同全局字段版本来自不同模板时仍可精确选择来源模板', async () => {
    const second = {
      ...crossTemplateCandidates[0]!,
      sourceTemplateCode: 'SOURCE-TPL-002',
      sourceTemplateId: 'source-template-2',
    };
    const wrapper = mount(FieldEditor, {
      props: { crossTemplateCandidates: [], crossTemplateSourceTemplates, fields },
      global: { plugins: [Antd] },
    });

    await wrapper.get('[data-test="open-cross-template"]').trigger('click');
    wrapper.getComponent({ name: 'ASelect' }).vm.$emit('update:value', 'source-template-2');
    await wrapper.setProps({ crossTemplateCandidates: [second] });
    await wrapper.vm.$nextTick();
    wrapper.getComponent({ name: 'ARadioGroup' }).vm.$emit('update:value', 'source-template-2::source-version-2');
    await wrapper.vm.$nextTick();
    await wrapper.get('[data-test="submit-cross-template"]').trigger('click');

    expect(wrapper.emitted('submit-cross-template')).toEqual([[second]]);
  });

  it('disabled 时不能选择、创建或提交', () => {
    const wrapper = mountEditor(true);
    expect(wrapper.findComponent(Select).props('disabled')).toBe(true);
    expect(wrapper.get('[data-test="open-private-field"]').attributes('disabled')).toBeDefined();
    expect(wrapper.get('[data-test="submit-field"]').attributes('disabled')).toBeDefined();
  });
});
