/* @vitest-environment happy-dom */

import { flushPromises, mount } from '@vue/test-utils';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import ReportFormDetailPane from '../ReportFormDetailPane.vue';

const apiMocks = vi.hoisted(() => ({
  getConfigData: vi.fn(),
  getDataChange: vi.fn(),
  getModelInfo: vi.fn(),
}));

vi.mock('#/api/onlineDev/visualDev', () => ({
  getConfigData: apiMocks.getConfigData,
  getDataChange: apiMocks.getDataChange,
  getModelInfo: apiMocks.getModelInfo,
}));

vi.mock('@jnpf/utils', async () => {
  const { defineAsyncComponent } = await import('vue');

  return {
    createAsyncComponent: (loader: any) => defineAsyncComponent(() => loader().then((module: any) => module.default || module)),
  };
});

vi.mock('ant-design-vue', async () => {
  const { defineComponent, h } = await import('vue');

  return {
    Button: defineComponent({
      name: 'AButton',
      emits: ['click'],
      setup(_, { emit, slots }) {
        return () => h('button', { type: 'button', onClick: () => emit('click') }, slots.default?.());
      },
    }),
    Result: defineComponent({
      name: 'AResult',
      setup(_, { slots }) {
        return () => h('div', { 'data-test': 'result' }, slots.extra?.());
      },
    }),
    Spin: defineComponent({
      name: 'ASpin',
      setup() {
        return () => h('div', { 'data-test': 'spin' });
      },
    }),
  };
});

vi.mock('#/views/common/dynamicModel/list/detail/Parser.vue', async () => {
  const { defineComponent, h } = await import('vue');

  return {
    default: defineComponent({
      name: 'DetailParser',
      props: {
        formConf: {
          required: true,
          type: Object,
        },
        formData: {
          required: true,
          type: Object,
        },
      },
      setup(props) {
        return () => h('div', { 'data-test': 'detail-parser' }, JSON.stringify({ formConf: props.formConf, formData: props.formData }));
      },
    }),
  };
});

function createFormConf() {
  return {
    fields: [
      {
        __config__: {
          defaultValue: '',
          jnpfKey: 'relationForm',
        },
        __vModel__: 'supplier',
      },
      {
        __config__: {
          defaultValue: '',
          jnpfKey: 'popupSelect',
        },
        __vModel__: 'sample',
      },
    ],
    labelWidth: 100,
  };
}

describe('ReportFormDetailPane', () => {
  beforeEach(() => {
    apiMocks.getConfigData.mockResolvedValue({
      data: {
        formData: JSON.stringify(createFormConf()),
      },
    });
    apiMocks.getDataChange.mockResolvedValue({
      data: {
        data: JSON.stringify({
          sample: '样品A',
          sample_id: 'sample-id',
          supplier: '供应商A',
          supplier_id: 'supplier-id',
        }),
        id: 'record-id',
      },
    });
    apiMocks.getModelInfo.mockResolvedValue({
      data: {
        data: JSON.stringify({
          sample: 'sample-id',
          supplier: 'supplier-id',
        }),
        id: 'record-id',
      },
    });
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('使用详情展示接口数据回显关联表单和弹窗选择名称', async () => {
    const wrapper = mount(ReportFormDetailPane, {
      props: {
        tab: {
          id: 'record-id',
          key: 'formDetail',
          modelId: 'model-id',
        },
      },
    });

    await flushPromises();

    expect(apiMocks.getDataChange).toHaveBeenCalledWith('model-id', { id: 'record-id' });
    const parser = wrapper.findComponent({ name: 'DetailParser' });
    const formConf = parser.props('formConf') as any;

    expect(formConf.fields[0].__config__.defaultValue).toBe('supplier-id');
    expect(formConf.fields[0].name).toBe('供应商A');
    expect(formConf.fields[1].__config__.defaultValue).toBe('sample-id');
    expect(formConf.fields[1].name).toBe('样品A');
  });
});
