/**
 * 组件名称：Nav 导航
 * 单测内容：
 * 1. 基本使用
 * 2. 多层级
 * 3. 横向摆放
 * 4. 响应式收纳
 * 5. 动态导航
 * 6. 懒加载
 * 7. 更多操作
 */

import {render, cleanup, fireEvent, waitFor} from '@testing-library/react';
import '../../src';
import {render as amisRender} from '../../src';
import {makeEnv, wait} from '../helper';

afterEach(cleanup);

// 1. 基本使用
test('Renderer:Nav', () => {
  const {container} = render(
    amisRender(
      {
        type: 'nav',
        stacked: true,
        className: 'w-md',
        itemBadge: {
          mode: 'ribbon',
          text: '${customText}',
          position: 'top-left',
          visibleOn: 'this.customText',
          level: '${customLevel}'
        },
        links: [
          {
            __id: 0,
            label: 'Nav 1',
            to: '/docs/index',
            icon: 'https://suda.cdn.bcebos.com/images%2F2021-01%2Fdiamond.svg',
            active: true
          },
          {
            __id: 1,
            label: 'Nav 2',
            to: '/docs/api',
            customText: 'HOT',
            customLevel: 'danger'
          },
          {
            __id: 2,
            label: 'Nav 3',
            to: '/docs/renderers',
            customText: 'SUC',
            customLevel: 'success'
          },
          {
            __id: 3,
            label: '外部地址',
            to: 'http://www.baidu.com/',
            target: '_blank'
          }
        ]
      },
      {},
      makeEnv({})
    )
  );

  expect(container).toMatchSnapshot();

  const items = container.querySelectorAll('.cxd-Nav-Menu-item')!;
  expect(items.length).toBe(4);
  expect(items[0].querySelector('img')).toHaveAttribute(
    'src',
    'https://suda.cdn.bcebos.com/images%2F2021-01%2Fdiamond.svg'
  );
  expect(items[1].firstElementChild?.firstElementChild).toHaveClass(
    'cxd-Badge'
  );
  expect(items[2].querySelector('.cxd-Badge--success')).toHaveTextContent(
    'SUC'
  );
});

// 2. 多层级
test('Renderer:Nav with multi-level', () => {
  const {container} = render(
    amisRender(
      {
        type: 'nav',
        stacked: true,
        className: 'w-md',
        links: [
          {
            __id: 1,
            label: 'Nav 1',
            to: '/docs/index',
            icon: 'fa fa-user',
            active: true
          },
          {
            __id: 2,
            label: 'Nav 2',
            unfolded: true,
            children: [
              {
                __id: 2.1,
                label: 'Nav 2-1',
                children: [
                  {
                    __id: 2.11,
                    label: 'Nav 2-1-1',
                    to: '/docs/api-2-1-1'
                  }
                ]
              },
              {
                __id: 2.2,
                label: 'Nav 2-2',
                to: '/docs/api-2-2'
              }
            ]
          },
          {
            __id: 3,
            label: 'Nav 3',
            to: '/docs/renderers'
          }
        ]
      },
      {},
      makeEnv({})
    )
  );

  expect(container).toMatchSnapshot();
  expect(container.querySelector('.cxd-Nav-Menu-submenu')!).toBeInTheDocument();
  const menuWrapper = container.querySelector(
    '.cxd-Nav-Menu > .cxd-Nav-Menu-submenu > .cxd-Nav-Menu'
  );
  const children = menuWrapper?.children;
  expect(children?.length).toBe(2);
});

// 3. 横向摆放
test('Renderer:Nav with stacked', () => {
  const {container} = render(
    amisRender(
      {
        type: 'nav',
        stacked: false,
        links: [
          {
            __id: 1,
            label: 'Nav 1',
            to: '/docs/index',
            icon: 'fa fa-user'
          },
          {
            __id: 2,
            label: 'Nav 2',
            to: '/docs/api'
          },
          {
            __id: 3,
            label: 'Nav 3',
            to: '/docs/renderers'
          }
        ]
      },
      {},
      makeEnv({})
    )
  );

  expect(container).toMatchSnapshot();
  expect(
    container.querySelector('.cxd-Nav-Menu-horizontal')!
  ).toBeInTheDocument();
});

// 4. 响应式收纳
test('Renderer:Nav with overflow', async () => {
  const {container} = render(
    amisRender(
      {
        type: 'page',
        body: {
          type: 'nav',
          stacked: false,
          overflow: {
            __id: 'overflowid',
            enable: true,
            overflowLabel: '点击展开',
            overflowIndicator: 'fas fa-angle-double-down',
            maxVisibleCount: 2,
            wrapperComponent: 'section',
            style: {
              color: 'red'
            },
            overflowClassName: 'thisisoverflowClassName',
            overflowPopoverClassName: 'thisisoverflowPopoverClassName',
            overflowListClassName: 'thisisoverflowListClassName'
          },
          links: [
            {
              __id: 1,
              label: 'Nav 1',
              to: '?to=nav1'
            },
            {
              __id: 2,
              label: 'Nav 2',
              to: '?to=nav1'
            },
            {
              __id: 3,
              label: 'Nav 3',
              to: '?to=nav3'
            },
            {
              __id: 4,
              label: 'Nav 4',
              to: '?to=nav4'
            },
            {
              __id: 5,
              label: 'Nav 5',
              to: '?to=nav5'
            },
            {
              __id: 6,
              label: 'Nav 6',
              to: '?to=nav6'
            },
            {
              __id: 7,
              label: 'Nav 7',
              to: '?to=nav7'
            },
            {
              __id: 8,
              label: 'Nav 8',
              to: '?to=nav8'
            }
          ]
        }
      },
      {},
      makeEnv({})
    )
  );

  const wrap = container.querySelector(
    'section.cxd-Nav-Menu.cxd-Nav-Menu-horizontal'
  )!;

  expect(wrap).toBeInTheDocument();
  expect(wrap).toHaveStyle({
    color: 'red'
  });

  const btn = container.querySelector('.cxd-Nav-Menu-overflow-item-rest');
  expect(btn).toBeInTheDocument();
  expect(btn).toHaveTextContent('点击展开');
  expect(btn?.querySelector('.fa-angle-double-down')!).toBeInTheDocument();
  expect(btn?.querySelector('.cxd-Nav-Menu-overflowedIcon')!).toHaveClass(
    'thisisoverflowClassName'
  );

  expect(
    container.querySelectorAll(
      '.cxd-Nav-Menu-item:not(.cxd-Nav-Menu-overflow-item-rest)'
    )!.length
  ).toEqual(2);

  fireEvent.click(btn!);

  await waitFor(() =>
    expect(container.querySelector('.cxd-Spinner')).not.toBeInTheDocument()
  );
  expect(container).toMatchSnapshot();
});

// 5. 动态导航
test('Renderer:Nav with source', async () => {
  const {container} = render(
    amisRender(
      {
        type: 'page',
        data: {
          nav: [
            {
              __id: 1,
              label: 'Nav 1',
              to: '/docs/index',
              icon: 'fa fa-user'
            },
            {
              __id: 2,
              label: 'Nav 2',
              to: '/docs/api'
            },
            {
              __id: 3,
              label: 'Nav 3',
              to: '/docs/renderers'
            }
          ]
        },
        body: {
          type: 'nav',
          stacked: true,
          source: '${nav}'
        }
      },
      {},
      makeEnv({})
    )
  );

  expect(container.querySelectorAll('.cxd-Nav-Menu-item').length).toBe(3);
  expect(container).toMatchSnapshot();
});

// 6. 懒加载
test('Renderer:Nav with defer', async () => {
  const fetcher = jest.fn().mockImplementation(
    ({query}) =>
      new Promise((resolve, reject) => {
        if (query?.parentId) {
          resolve({
            status: 0,
            msg: '',
            data: [
              {label: 'Nav 3-1', to: '?cat=3-1', value: '3-1', __id: 3.1},
              {label: 'Nav 3-2', to: '?cat=3-2', value: '3-2', __id: 3.2}
            ]
          });
          return;
        }

        resolve({
          status: 0,
          msg: '',
          data: {
            links: [
              {
                label: 'Nav 1',
                to: '?cat=1',
                value: '1',
                icon: 'fa fa-user',
                __id: 1
              },
              {
                label: 'Nav 2',
                __id: 2,
                unfolded: true,
                children: [
                  {
                    __id: 2.1,
                    label: 'Nav 2-1',
                    children: [
                      {
                        label: 'Nav 2-1-1',
                        to: '?cat=2-1',
                        value: '2-1',
                        __id: 2.11
                      }
                    ]
                  },
                  {label: 'Nav 2-2', to: '?cat=2-2', value: '2-2', __id: 2.2}
                ]
              },
              {label: 'Nav 3', to: '?cat=3', value: '3', defer: true, __id: 3}
            ],
            value: '?cat=1'
          }
        });
      })
  );

  const {container, getByTitle, getByText} = render(
    amisRender(
      {
        type: 'page',
        body: {
          type: 'nav',
          stacked: true,
          source: '/api/options/nav?parentId=${value}'
        }
      },
      {},
      makeEnv({
        fetcher,
        session: 'test-nav-1'
      })
    )
  );

  await wait(200);
  expect(fetcher).toBeCalled();

  const menu = container.querySelector('.cxd-Nav-Menu');
  expect(menu?.children.length).toBe(3);

  // const navThreeHeader = getByTitle('Nav 3');
  // expect(navThreeHeader).toBeInTheDocument();

  // fireEvent.click(
  //   navThreeHeader?.querySelector('.cxd-Nav-Menu-submenu-arrow')!
  // );

  // await wait(200);
  // expect(fetcher).toBeCalledTimes(1);
  // expect(fetcher.mock.calls[0][0]).toEqual({
  //   config: {},
  //   method: 'get',
  //   query: {parentId: '3'},
  //   url: '/api/options/nav?parentId=3'
  // });

  // await wait(200);
  // const navThree = container.querySelector(
  //   '.cxd-Menu > .cxd-Menu-submenu:last-of-type'
  // );

  // expect(navThree!.querySelector('.cxd-Menu-sub')?.children.length).toBe(2);
  // expect(getByText('Nav 3-2')).not.toBeNull();

  // expect(container).toMatchSnapshot();
});

// 7. 更多操作
test('Renderer:Nav with itemActions', async () => {
  const {container, getByTitle, getByText} = render(
    amisRender(
      {
        type: 'page',
        body: {
          type: 'nav',
          stacked: true,
          className: 'w-md',
          draggable: true,
          saveOrderApi: '/api/options/nav',
          source: '/api/options/nav?parentId=${value}',
          itemActions: [
            {
              type: 'icon',
              icon: 'cloud',
              visibleOn: "this.to === '?cat=1'"
            },
            {
              type: 'dropdown-button',
              level: 'link',
              icon: 'fa fa-ellipsis-h',
              hideCaret: true,
              buttons: [
                {
                  type: 'button',
                  label: '编辑'
                },
                {
                  type: 'button',
                  label: '删除'
                }
              ]
            }
          ],
          links: [
            {
              label: 'Nav 1',
              to: '?cat=1',
              value: '1',
              icon: 'fa fa-user',
              __id: 1
            },
            {
              label: 'Nav 2',
              __id: 2,
              unfolded: true,
              children: [
                {
                  __id: 2.1,
                  label: 'Nav 2-1',
                  children: [
                    {
                      label: 'Nav 2-1-1',
                      to: '?cat=2-1',
                      value: '2-1',
                      __id: 2.11
                    }
                  ]
                },
                {label: 'Nav 2-2', to: '?cat=2-2', value: '2-2', __id: 2.2}
              ]
            },
            {label: 'Nav 3', to: '?cat=3', value: '3', defer: true, __id: 3}
          ]
        }
      },
      {},
      makeEnv({})
    )
  );
  expect(container).toMatchSnapshot();

  expect(container.querySelectorAll('.fa-cloud').length).toBe(1);
  fireEvent.click(
    container.querySelector('.cxd-Nav-Menu-item-extra .cxd-Button')!
  );

  await waitFor(() =>
    expect(container.querySelector('.cxd-Spinner')).not.toBeInTheDocument()
  );
  expect(container).toMatchSnapshot();
  expect(getByText('编辑')).toBeInTheDocument();
});

// 8.各种图标展示
test('Renderer:Nav with icons', async () => {
  const {container} = render(
    amisRender(
      {
        type: 'page',
        body: {
          type: 'nav',
          stacked: true,
          links: [
            {
              label: 'Nav 1',
              to: '?cat=1',
              value: '1',
              icon: 'fa fa-user',
              __id: 1
            },
            {
              label: 'Nav 2',
              __id: 2,
              unfolded: true,
              children: [
                {
                  __id: 2.1,
                  label: 'Nav 2-1',
                  icon: [
                    {
                      icon: 'star',
                      position: 'before'
                    },
                    {
                      icon: 'search',
                      position: 'before'
                    },
                    {
                      icon: 'https://suda.cdn.bcebos.com/images%2F2021-01%2Fdiamond.svg',
                      position: 'after'
                    }
                  ],
                  children: [
                    {
                      label: 'Nav 2-1-1',
                      to: '?cat=2-1',
                      value: '2-1',
                      __id: 2.11
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      {},
      makeEnv({})
    )
  );
  expect(container).toMatchSnapshot();
  expect(container.querySelectorAll('.fa-user').length).toBe(1);
  expect(container.querySelectorAll('[icon=search]').length).toBe(1);
  expect(container.querySelectorAll('img').length).toBe(1);
});

// 9.Nav在Dialog里
test('Renderer:Nav with Dialog', async () => {
  const {container, getByText} = render(
    amisRender(
      {
        type: 'page',
        body: {
          type: 'button',
          label: '点击弹框',
          actionType: 'dialog',
          dialog: {
            title: '弹框',
            body: [
              {
                type: 'nav',
                stacked: true,
                className: 'w-md',
                draggable: true,
                saveOrderApi: '/api/options/nav',
                source: '/api/options/nav?parentId=${value}',
                itemActions: [
                  {
                    type: 'icon',
                    icon: 'cloud',
                    visibleOn: "this.to === '?cat=1'"
                  },
                  {
                    type: 'dropdown-button',
                    level: 'link',
                    icon: 'fa fa-ellipsis-h',
                    hideCaret: true,
                    buttons: [
                      {
                        type: 'button',
                        label: '编辑'
                      },
                      {
                        type: 'button',
                        label: '删除'
                      }
                    ]
                  }
                ],
                links: [
                  {
                    label: 'Nav 1',
                    to: '?cat=1',
                    value: '1',
                    icon: 'fa fa-user',
                    __id: 1
                  },
                  {
                    label: 'Nav 2',
                    __id: 2,
                    unfolded: true,
                    children: [
                      {
                        __id: 2.1,
                        label: 'Nav 2-1',
                        children: [
                          {
                            label: 'Nav 2-1-1',
                            to: '?cat=2-1',
                            value: '2-1',
                            __id: 2.11
                          }
                        ]
                      },
                      {
                        label: 'Nav 2-2',
                        to: '?cat=2-2',
                        value: '2-2',
                        __id: 2.2
                      }
                    ]
                  },
                  {
                    label: 'Nav 3',
                    to: '?cat=3',
                    value: '3',
                    defer: true,
                    __id: 3
                  }
                ]
              }
            ]
          }
        }
      },
      {},
      makeEnv({
        getModalContainer: () => container
      })
    )
  );
  expect(container).toMatchSnapshot();

  fireEvent.click(getByText('点击弹框'));
  await waitFor(() => {
    expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
  });

  fireEvent.click(
    container.querySelector(
      '[role="dialog"] .cxd-Nav-Menu-item-extra .cxd-Button'
    )!
  );

  await waitFor(() => {
    expect(
      container.querySelector('[role="dialog"] .cxd-PopOver')
    ).toBeInTheDocument();
  });
});

// 10.Nav配置reload动作
test('Renderer:Nav with reload1', async () => {
  const fetcher = jest.fn().mockImplementation(() =>
    Promise.resolve({
      data: {
        status: 0,
        msg: 'ok',
        data: ''
      }
    })
  );
  const {container}: any = render(
    amisRender(
      {
        type: 'page',
        data: {
          nav: [
            {
              label: 'Nav 1',
              to: '/docs/index',
              icon: 'fa fa-user'
            },
            {
              label: 'Nav 2',
              to: '/docs/api'
            },
            {
              label: 'Nav 3',
              to: '/docs/renderers'
            }
          ]
        },
        body: [
          {
            type: 'nav',
            stacked: true,
            id: 'xxNav',
            source: '${nav}'
          },
          {
            type: 'button',
            level: 'primary',
            className: 'mr-4',
            label: 'reload',
            onEvent: {
              click: {
                actions: [
                  {
                    componentId: 'xxNav',
                    actionType: 'reload'
                  }
                ]
              }
            }
          }
        ]
      },
      {},
      makeEnv({
        session: 'test-case-action-no',
        fetcher
      })
    )
  );
  fireEvent.click(container.querySelector('.cxd-Button'));
  await wait(500);
  expect(fetcher).not.toBeCalled();
});

// 11.Nav配置reload动作
test('Renderer:Nav with reload2', async () => {
  const fetcher = jest.fn().mockImplementation(() =>
    Promise.resolve({
      data: {
        status: 0,
        msg: 'ok',
        data: {
          links: [
            {
              label: 'Nav 1',
              to: '?cat=1',
              value: '1',
              icon: 'fa fa-user'
            },
            {
              label: 'Nav 2',
              unfolded: true,
              children: [
                {
                  label: 'Nav 2-1',
                  children: [
                    {
                      label: 'Nav 2-1-1',
                      to: '?cat=2-1',
                      value: '2-1'
                    }
                  ]
                },
                {
                  label: 'Nav 2-2',
                  to: '?cat=2-2',
                  value: '2-2'
                }
              ]
            },
            {
              label: 'Nav 3',
              to: '?cat=3',
              value: '3',
              defer: true
            }
          ],
          value: '?cat=1'
        }
      }
    })
  );
  const {container}: any = render(
    amisRender(
      {
        type: 'page',
        data: {
          url: '/api/options/nav'
        },
        body: [
          {
            type: 'nav',
            stacked: true,
            id: 'xxNav',
            source: '${url}'
          },
          {
            type: 'button',
            level: 'primary',
            className: 'mr-4',
            label: 'reload',
            onEvent: {
              click: {
                actions: [
                  {
                    componentId: 'xxNav',
                    actionType: 'reload'
                  }
                ]
              }
            }
          }
        ]
      },
      {},
      makeEnv({
        session: 'test-case-action-no',
        fetcher
      })
    )
  );
  await wait(500);
  const navItem = container.querySelector('.cxd-Nav-Menu-item');
  expect(navItem).toBeInTheDocument();
  fireEvent.click(container.querySelector('.cxd-Button'));
  await wait(500);
  expect(fetcher).toBeCalled();
});

test('Renderer:Nav with searchable', async () => {
  const {container} = render(amisRender({
    "type": "nav",
    "stacked": true,
    "searchable": true,
    "searchConfig": {
      "matchFunc": "return link.searchKey === keyword;"
    },
    "links": [
        {
          "label": "Nav 1",
          "to": "?to=nav1",
          "searchKey": "1"
        },
        {
          "label": "Nav 2",
          "to": "?to=nav2",
          "searchKey": "2",
          "children": [
              {
                "label": "Nav 2-1",
                "to": "?to=nav2-1",
                "searchKey": "2-1",
                "children": [
                    {
                      "label": "Nav 2-1-1",
                      "to": "?to=nav2-1-1",
                      "searchKey": "2-1-1"
                    }
                ]
              }
          ]
        },
        {
          "label": "Nav 3",
          "to": "?to=nav3",
          "searchKey": "3",
          "children": [
              {
                "label": "Nav 3-1",
                "to": "?to=nav3-1",
                "searchKey": "3-1"
              }
          ]
        },
        {
          "label": "Nav 4",
          "to": "?to=nav4",
          "searchKey": "4"
        },
        {
          "label": "Nav 5",
          "to": "?to=nav5",
          "searchKey": "5"
        }
    ]
  }, {}, makeEnv({})));

  const nav = container.querySelector('.cxd-Nav')!;
  const searchbox = container.querySelector('.cxd-Nav-SearchBox input')!;
  const searchboxBtn = container.querySelector('.cxd-SearchBox-searchBtn')!;

  expect(nav).toBeInTheDocument();

  fireEvent.change(searchbox, {target: {value: '2-1-1'}});
  await wait(200);
  fireEvent.click(searchboxBtn);
  await wait(200);
  expect(document.querySelectorAll('[role=menuitem]')?.length).toEqual(3);

  fireEvent.change(searchbox, {target: {value: '3'}});
  await wait(200);
  fireEvent.click(searchboxBtn);
  await wait(200);
  expect(document.querySelectorAll('[role=menuitem]')?.length).toEqual(2);
});
