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

import { beforeEach, describe, expect, it, vi } from 'vitest';

import RemoteModelDialog from './RemoteModelDialog.vue';

const apiMocks = vi.hoisted(() => ({
  getRemoteModels: vi.fn(),
  importRemoteModel: vi.fn(),
}));

vi.mock('#/api/ai/llm', () => apiMocks);
vi.mock('@easyflow/common-ui', async () => {
  const { defineComponent, h } = await import('vue');
  return {
    EasyFlowFormModal: defineComponent({
      props: {
        open: Boolean,
        title: { default: '', type: String },
      },
      emits: ['update:open'],
      setup(props, { slots }) {
        return () =>
          props.open
            ? h('section', [h('h2', props.title), slots.default?.()])
            : null;
      },
    }),
  };
});

const mountDialog = () =>
  mount(RemoteModelDialog, {
    global: {
      stubs: {
        Transition: false,
      },
    },
  });

describe('remote model dialog', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    apiMocks.getRemoteModels.mockResolvedValue({
      data: {
        models: [
          {
            addable: true,
            added: false,
            capabilitySource: 'CATALOG',
            displayName: 'BGE-M3',
            family: 'bge',
            modelId: 'BAAI/bge-m3',
            modelType: 'embeddingModel',
            supportImage: false,
            supportThinking: false,
            supportTool: false,
          },
        ],
        providerId: '100',
        truncated: false,
      },
      errorCode: 0,
    });
    apiMocks.importRemoteModel.mockResolvedValue({
      data: { localModelId: '200', status: 'CREATED' },
      errorCode: 0,
    });
  });

  it('loads remote models and keeps the dialog open after one-click import', async () => {
    const wrapper = mountDialog();

    wrapper.vm.openDialog('100', '测试服务商');
    await flushPromises();

    expect(apiMocks.getRemoteModels).toHaveBeenCalledWith('100');
    expect(wrapper.text()).toContain('BAAI/bge-m3');
    expect(wrapper.text()).not.toContain('BGE-M3');

    await wrapper.get('button[aria-label="添加 BAAI/bge-m3"]').trigger('click');
    await flushPromises();

    expect(apiMocks.importRemoteModel).toHaveBeenCalledWith(
      '100',
      'BAAI/bge-m3',
    );
    expect(wrapper.text()).toContain('已添加');
    expect(wrapper.emitted('imported')).toHaveLength(1);
    expect(wrapper.get('h2').text()).toBe('测试服务商 模型');
  });

  it('shows a retryable error and preserves manual add', async () => {
    apiMocks.getRemoteModels.mockRejectedValueOnce(
      new Error('当前服务暂不支持获取模型列表'),
    );
    const wrapper = mountDialog();

    wrapper.vm.openDialog('100', '测试服务商');
    await flushPromises();

    expect(wrapper.text()).toContain('获取失败');
    expect(wrapper.text()).toContain('当前服务暂不支持获取模型列表');
    const manualAdd = wrapper
      .findAll('button')
      .find((button) => button.text().trim() === '手动新增');
    await manualAdd?.trigger('click');

    expect(wrapper.emitted('manualAdd')).toHaveLength(1);
  });

  it('uses one scroll container and keeps semantic capability colors', async () => {
    apiMocks.getRemoteModels.mockResolvedValueOnce({
      data: {
        models: [
          {
            addable: true,
            added: false,
            capabilitySource: 'CATALOG',
            displayName: 'DeepSeek V4 Pro',
            family: 'deepseek-thinking',
            modelId: 'deepseek-v4-pro',
            modelType: 'chatModel',
            supportImage: false,
            supportThinking: true,
            supportTool: true,
          },
        ],
        providerId: '100',
        truncated: false,
      },
      errorCode: 0,
    });
    const wrapper = mountDialog();

    wrapper.vm.openDialog('100', '测试服务商');
    await flushPromises();

    expect(wrapper.find('.el-vl__wrapper').exists()).toBe(false);
    expect(wrapper.find('.el-tag--info').text()).toBe('推理');
    expect(wrapper.find('.el-tag--warning').text()).toBe('工具');
  });

  it('renders a flat list sorted by model id', async () => {
    apiMocks.getRemoteModels.mockResolvedValueOnce({
      data: {
        models: [
          {
            addable: true,
            added: false,
            capabilitySource: 'CATALOG',
            displayName: 'Zeta Model',
            family: 'zeta-family',
            modelId: 'zeta/model',
            modelType: 'chatModel',
            supportImage: false,
            supportThinking: false,
            supportTool: false,
          },
          {
            addable: true,
            added: false,
            capabilitySource: 'CATALOG',
            displayName: 'Alpha Model',
            family: 'alpha-family',
            modelId: 'alpha/model',
            modelType: 'chatModel',
            supportImage: false,
            supportThinking: false,
            supportTool: false,
          },
        ],
        providerId: '100',
        truncated: false,
      },
      errorCode: 0,
    });
    const wrapper = mountDialog();

    wrapper.vm.openDialog('100', '测试服务商');
    await flushPromises();

    expect(wrapper.find('.remote-model-dialog__group').exists()).toBe(false);
    expect(
      wrapper
        .findAll('.remote-model-row__identity strong')
        .map((item) => item.text()),
    ).toEqual(['alpha/model', 'zeta/model']);
    expect(wrapper.text()).not.toContain('alpha-family');
    expect(wrapper.text()).not.toContain('zeta-family');
  });
});
