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

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

import CardList from '../CardList.vue';

const { hasAccessByCodes } = vi.hoisted(() => ({
  hasAccessByCodes: vi.fn((codes: string[]) => codes[0] !== 'blocked'),
}));

vi.mock('@easyflow/access', () => ({
  useAccess: () => ({
    hasAccessByCodes,
  }),
}));

vi.mock('#/locales', () => ({
  $t: (key: string) => {
    const labelMap: Record<string, string> = {
      'aiResource.created': '创建时间',
      'aiResource.createdBy': '创建者',
    };
    return labelMap[key] || key;
  },
}));

describe('cardList', () => {
  function mountCardList(props: Record<string, unknown>) {
    return mount(CardList, {
      props: {
        data: [
          {
            id: 'bot-1',
            title: '演示卡片',
            description: '用于验证主次交互是否正常工作',
          },
        ],
        defaultIcon: '/favicon.svg',
        ...props,
      },
      global: {
        stubs: {
          IconifyIcon: {
            props: ['icon'],
            template: '<span class="iconify-icon">{{ icon }}</span>',
          },
        },
      },
    });
  }

  it('点击卡片空白区域时触发主动作', async () => {
    const primaryAction = vi.fn();
    const wrapper = mountCardList({
      primaryAction: {
        text: '进入设置',
        onClick: primaryAction,
      },
    });

    await wrapper.get('.card-item').trigger('click');

    expect(primaryAction).toHaveBeenCalledTimes(1);
    expect(primaryAction).toHaveBeenCalledWith(
      expect.objectContaining({ id: 'bot-1' }),
    );
  });

  it('点击次级按钮时不会冒泡触发主动作', async () => {
    const primaryAction = vi.fn();
    const inlineAction = vi.fn();
    const wrapper = mountCardList({
      primaryAction: {
        text: '进入设置',
        onClick: primaryAction,
      },
      actions: [
        {
          text: '编辑',
          placement: 'inline',
          onClick: inlineAction,
        },
      ],
    });

    await wrapper.get('.card-action-btn').trigger('click');

    expect(inlineAction).toHaveBeenCalledTimes(1);
    expect(primaryAction).not.toHaveBeenCalled();
  });

  it('将可见主操作与行内操作紧凑放在左侧，并将更多菜单独立放在右侧', () => {
    const wrapper = mountCardList({
      primaryAction: {
        text: '编排',
        onClick: vi.fn(),
      },
      actions: [
        {
          text: '发布',
          placement: 'inline',
          onClick: vi.fn(),
        },
        {
          text: '删除',
          placement: 'menu',
          onClick: vi.fn(),
        },
      ],
    });

    const mainActions = wrapper.get('.card-main-actions');

    expect(mainActions.get('.card-primary-hint').text()).toContain('编排');
    expect(mainActions.get('.card-actions').text()).toContain('发布');
    expect(mainActions.find('.card-action-btn--menu').exists()).toBe(false);
    expect(wrapper.find('.card-overflow-action').exists()).toBe(true);
  });

  it('仅渲染当前可见的行内操作且不保留空占位', () => {
    const wrapper = mountCardList({
      actions: [
        {
          text: '编辑',
          placement: 'inline',
          visible: false,
          onClick: vi.fn(),
        },
        {
          text: '运行',
          placement: 'inline',
          onClick: vi.fn(),
        },
      ],
    });

    const inlineButtons = wrapper.findAll('.card-actions .card-action-btn');

    expect(inlineButtons).toHaveLength(1);
    expect(inlineButtons[0]?.text()).toContain('运行');
    expect(wrapper.text()).not.toContain('编辑');
  });

  it('异步次级操作执行中会禁用重复点击并展示加载态', async () => {
    const inlineAction = vi.fn();
    const wrapper = mountCardList({
      actions: [
        {
          disabled: () => true,
          loading: () => true,
          text: '分享',
          placement: 'inline',
          onClick: inlineAction,
        },
      ],
    });

    const actionButton = wrapper.get('.card-action-btn');
    await actionButton.trigger('click');

    expect(actionButton.classes()).toContain('is-loading');
    expect(actionButton.classes()).toContain('is-disabled');
    expect(inlineAction).not.toHaveBeenCalled();
  });

  it('键盘 Enter 可以触发主动作', async () => {
    const primaryAction = vi.fn();
    const wrapper = mountCardList({
      primaryAction: {
        text: '进入设计',
        onClick: primaryAction,
      },
    });

    await wrapper.get('.card-item').trigger('keydown.enter');

    expect(primaryAction).toHaveBeenCalledTimes(1);
  });

  it('未提供主动作时保持旧卡片模式，不会把卡片变成可点击入口', async () => {
    const legacyAction = vi.fn();
    const wrapper = mountCardList({
      actions: [
        {
          text: '编辑',
          onClick: legacyAction,
        },
      ],
    });

    await wrapper.get('.card-item').trigger('click');
    await wrapper.get('.card-action-btn').trigger('click');

    expect(wrapper.get('.card-item').attributes('role')).toBeUndefined();
    expect(legacyAction).toHaveBeenCalledTimes(1);
  });

  it('同时展示创建人与创建时间', () => {
    const wrapper = mountCardList({
      data: [
        {
          id: 'bot-1',
          title: '演示卡片',
          description: '用于验证元信息展示',
          createdByName: '管理员',
          created: '2026-04-12 10:00:00',
        },
      ],
    });

    const metaText = wrapper.get('.card-meta-row').text();

    expect(metaText).toContain('创建者：管理员');
    expect(metaText).toContain('创建时间：2026-04-12 10:00:00');
  });

  it('缺少创建人时仅展示创建时间', () => {
    const wrapper = mountCardList({
      data: [
        {
          id: 'bot-1',
          title: '演示卡片',
          description: '用于验证元信息展示',
          created: '2026-04-12 10:00:00',
        },
      ],
    });

    const metaText = wrapper.get('.card-meta-row').text();

    expect(metaText).toContain('创建时间：2026-04-12 10:00:00');
    expect(metaText).not.toContain('创建者：');
  });

  it('缺少创建信息时不渲染元信息区', () => {
    const wrapper = mountCardList({
      data: [
        {
          id: 'bot-1',
          title: '演示卡片',
          description: '用于验证元信息展示',
        },
      ],
    });

    expect(wrapper.find('.card-meta-row').exists()).toBe(false);
  });

  it('支持知识库使用标题与类型标签的堆叠布局', () => {
    const wrapper = mountCardList({
      data: [
        {
          collectionType: 'FAQ',
          id: 'knowledge-1',
          title: '常见问题',
        },
      ],
      tagField: 'collectionType',
      tagLayout: 'stacked',
      tagMap: {
        FAQ: 'FAQ',
      },
    });

    expect(wrapper.get('.title-row').classes()).toContain('title-row--stacked');
    expect(wrapper.get('.title-row').text()).toContain('FAQ');
  });
});
