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

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

import SkillList from './SkillList.vue';
import skillListSource from './SkillList.vue?raw';

/* eslint-disable vue/one-component-per-file -- Inline stubs keep this layout test isolated. */

const apiMocks = vi.hoisted(() => ({
  deleteSkillCategory: vi.fn(),
  getSkillCategories: vi.fn(),
}));
const permissionMocks = vi.hoisted(() => ({
  hasPermission: vi.fn((_permissions: string[]) => true),
}));
const pageDataMocks = vi.hoisted(() => ({
  reload: vi.fn(),
  setQuery: vi.fn(),
}));

vi.mock('#/api/common/hasPermission', () => permissionMocks);
vi.mock('#/locales', () => ({
  $t: (key: string) => (key === 'common.allCategories' ? '全部' : key),
}));
vi.mock('./api', () => ({
  cancelSkillImport: vi.fn(),
  copySkill: vi.fn(),
  deleteSkillCategory: apiMocks.deleteSkillCategory,
  exportSkills: vi.fn(),
  getSkillCapabilityCandidates: vi.fn(),
  getSkillCategories: apiMocks.getSkillCategories,
  importSkillConfirm: vi.fn(),
  importSkillPreview: vi.fn(),
  submitSkillDeleteApproval: vi.fn(),
  submitSkillOfflineApproval: vi.fn(),
  submitSkillPublishApproval: vi.fn(),
}));
vi.mock('#/components/page/PageData.vue', async () => {
  const { defineComponent, h } = await import('vue');
  return {
    default: defineComponent({
      name: 'PageData',
      setup(_, { expose }) {
        expose(pageDataMocks);
        return () => h('div', { class: 'page-data-container' });
      },
    }),
  };
});
vi.mock('./SkillCategoryFormDialog.vue', async () => {
  const { defineComponent, h } = await import('vue');
  return {
    default: defineComponent({
      name: 'SkillCategoryFormDialog',
      setup: () => () => h('div'),
    }),
  };
});
vi.mock('./SkillCreateDialog.vue', async () => {
  const { defineComponent, h } = await import('vue');
  return {
    default: defineComponent({
      name: 'SkillCreateDialog',
      props: { modelValue: Boolean },
      emits: ['created', 'update:modelValue'],
      setup(props) {
        return () =>
          h('div', {
            'data-open': String(props.modelValue),
            'data-testid': 'skill-create-dialog',
          });
      },
    }),
  };
});

async function mountSkillList() {
  const router = createRouter({
    history: createMemoryHistory(),
    routes: [
      { component: { template: '<div />' }, path: '/ai/skill' },
      {
        component: { template: '<div />' },
        path: '/ai/skill/detail/:id?',
      },
    ],
  });
  await router.push('/ai/skill');
  await router.isReady();

  const wrapper = mount(SkillList, {
    global: {
      directives: { access: {}, loading: {} },
      plugins: [router],
      stubs: { ElDialog: true },
    },
  });
  await flushPromises();
  return wrapper;
}

describe('skill list layout', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    permissionMocks.hasPermission.mockReturnValue(true);
    apiMocks.getSkillCategories.mockResolvedValue({
      data: [
        {
          categoryName: '研发',
          id: 1,
          status: 1,
          children: [
            {
              categoryName: '平台',
              id: 2,
              parentId: 1,
              status: 1,
            },
          ],
        },
      ],
      errorCode: 0,
    });
  });

  it('places the toolbar above a full-height category and list workspace', async () => {
    const wrapper = await mountSkillList();

    const header = wrapper.get('.skill-list-page__header');
    const toolbar = header.get('.custom-header');
    expect(toolbar.text()).toContain('导入');
    expect(toolbar.text()).toContain('导出');
    expect(toolbar.text()).toContain('新建 Skill');
    expect(toolbar.get('.search-group').findAll('button')).toHaveLength(2);
    expect(toolbar.find('input').attributes()).toMatchObject({
      placeholder: '请输入 Skill 名称或描述',
    });

    const workspace = wrapper.get('.skill-list-page__workspace');
    expect(workspace.find('.skill-list-page__header').exists()).toBe(false);
    expect(workspace.element.children[0]?.classList).toContain('page-side');
    expect(workspace.element.children[1]?.classList).toContain(
      'skill-list-page__content',
    );
    expect(workspace.get('.skill-list-page__content').classes()).toContain(
      'skill-list-page__content',
    );

    const sidebar = workspace.get('#skill-category-sidebar');
    expect(sidebar.text()).toContain('全部');
    expect(sidebar.text()).toContain('研发');
    expect(sidebar.text()).toContain('平台');
    expect(sidebar.text()).not.toContain('未分类');
    expect(sidebar.get('.page-side__footer').text()).toContain('添加');

    const developmentNode = sidebar
      .findAll('.el-tree-node__content')
      .find((node) => node.text().includes('研发'));
    expect(developmentNode).toBeTruthy();
    await developmentNode?.trigger('click');
    expect(pageDataMocks.setQuery).toHaveBeenLastCalledWith({
      categoryId: 1,
      displayName: undefined,
    });

    wrapper.unmount();
  });

  it('keeps the complete flex height chain for the list area', () => {
    expect(skillListSource).toMatch(
      /\.skill-list-page\s*\{[^}]*display:\s*flex;[^}]*height:\s*100%;[^}]*min-height:\s*0;/,
    );
    expect(skillListSource).toMatch(
      /\.skill-list-page__workspace\s*\{[^}]*display:\s*grid;[^}]*flex:\s*1;[^}]*min-height:\s*0;/,
    );
    expect(skillListSource).toMatch(
      /\.skill-list-page__content\s*\{[^}]*display:\s*flex;[^}]*flex:\s*1;[^}]*height:\s*100%;[^}]*min-height:\s*0;/,
    );
    expect(skillListSource).toMatch(
      /\.skill-list-page\s+:deep\(\.page-data-container\)\s*\{[^}]*height:\s*100%;/,
    );
  });

  it('opens the compact creation dialog without navigating to a fake detail', async () => {
    const wrapper = await mountSkillList();
    const createButton = wrapper
      .findAll('button')
      .find((button) => button.text().includes('新建 Skill'));

    await createButton?.trigger('click');
    await flushPromises();

    expect(
      wrapper
        .get('[data-testid="skill-create-dialog"]')
        .attributes('data-open'),
    ).toBe('true');
    wrapper.unmount();
  });

  it('hides category write actions without category management permission', async () => {
    permissionMocks.hasPermission.mockImplementation(
      (permissions: string[]) =>
        !permissions.includes('/api/v1/skill/category'),
    );
    const wrapper = await mountSkillList();
    const sidebar = wrapper.get('#skill-category-sidebar');

    expect(sidebar.find('.page-side__footer').exists()).toBe(false);
    expect(sidebar.findAll('.page-side__more')).toHaveLength(0);

    wrapper.unmount();
  });
});
