import { render, screen } from '@testing-library/react';

import { Page } from '../Page';
import { PageSidebar } from '../PageSidebar';
import { PageSidebarBody } from '../PageSidebarBody';
import { PageSection } from '../PageSection';
import { Breadcrumb, BreadcrumbItem } from '../../Breadcrumb';
import { Nav, NavList, NavItem } from '../../Nav';
import { SkipToContent } from '../../SkipToContent';
import { PageBreadcrumb } from '../PageBreadcrumb';
import { PageGroup } from '../PageGroup';
import { Masthead } from '../../Masthead';

import styles from '@patternfly/react-styles/css/components/Page/page';

const props = {
  'aria-label': 'Page layout',
  id: 'PageId',
  className: 'my-page-class'
};

describe('Page', () => {
  test('Check page vertical layout example against snapshot', () => {
    const masthead = <Masthead />;
    const Sidebar = (
      <PageSidebar isSidebarOpen>
        <PageSidebarBody>Navigation</PageSidebarBody>
      </PageSidebar>
    );

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(asFragment()).toMatchSnapshot();
  });

  test('Check dark page against snapshot', () => {
    const masthead = <Masthead />;
    const Sidebar = (
      <PageSidebar isSidebarOpen>
        <PageSidebarBody>Navigation</PageSidebarBody>
      </PageSidebar>
    );

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page horizontal layout example against snapshot', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page to verify breadcrumb is created', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;
    const PageBreadcrumb = () => (
      <Breadcrumb>
        <BreadcrumbItem>Section Home</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#" isActive>
          Section Landing
        </BreadcrumbItem>
      </Breadcrumb>
    );

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar} breadcrumb={<PageBreadcrumb />}>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Verify sticky top breadcrumb on all height breakpoints', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;
    const PageBreadcrumb = () => (
      <Breadcrumb>
        <BreadcrumbItem>Section Home</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#" isActive>
          Section Landing
        </BreadcrumbItem>
      </Breadcrumb>
    );

    const { asFragment } = render(
      <Page
        {...props}
        masthead={masthead}
        sidebar={Sidebar}
        breadcrumb={<PageBreadcrumb />}
        breadcrumbProps={{ stickyOnBreakpoint: { sm: 'top', md: 'top', lg: 'top', xl: 'top', '2xl': 'top' } }}
      >
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Verify sticky bottom breadcrumb on all height breakpoints', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;
    const PageBreadcrumb = () => (
      <Breadcrumb>
        <BreadcrumbItem>Section Home</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#" isActive>
          Section Landing
        </BreadcrumbItem>
      </Breadcrumb>
    );

    const { asFragment } = render(
      <Page
        {...props}
        masthead={masthead}
        sidebar={Sidebar}
        breadcrumb={<PageBreadcrumb />}
        breadcrumbProps={{
          stickyOnBreakpoint: { sm: 'bottom', md: 'bottom', lg: 'bottom', xl: 'bottom', '2xl': 'bottom' }
        }}
      >
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page to verify breadcrumb is created - PageBreadcrumb syntax', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageBreadcrumb>
          <Breadcrumb>
            <BreadcrumbItem>Section Home</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#" isActive>
              Section Landing
            </BreadcrumbItem>
          </Breadcrumb>
        </PageBreadcrumb>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Verify sticky top breadcrumb on all height breakpoints - PageBreadcrumb syntax', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageBreadcrumb stickyOnBreakpoint={{ sm: 'top', md: 'top', lg: 'top', xl: 'top', '2xl': 'top' }}>
          <Breadcrumb>
            <BreadcrumbItem>Section Home</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#" isActive>
              Section Landing
            </BreadcrumbItem>
          </Breadcrumb>
        </PageBreadcrumb>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Sticky bottom breadcrumb on all height breakpoints - PageBreadcrumb syntax', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageBreadcrumb
          stickyOnBreakpoint={{ sm: 'bottom', md: 'bottom', lg: 'bottom', xl: 'bottom', '2xl': 'bottom' }}
        >
          <Breadcrumb>
            <BreadcrumbItem>Section Home</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
            <BreadcrumbItem to="#" isActive>
              Section Landing
            </BreadcrumbItem>
          </Breadcrumb>
        </PageBreadcrumb>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page to verify grouped nav and breadcrumb - new components syntax', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;

    const { asFragment } = render(
      <Page {...props} masthead={masthead} sidebar={Sidebar}>
        <PageGroup stickyOnBreakpoint={{ default: 'bottom' }}>
          <PageBreadcrumb>
            <Breadcrumb>
              <BreadcrumbItem>Section Home</BreadcrumbItem>
              <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
              <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
              <BreadcrumbItem to="#" isActive>
                Section Landing
              </BreadcrumbItem>
            </Breadcrumb>
          </PageBreadcrumb>
          <Nav aria-label="Nav" variant="horizontal-subnav">
            <NavList>
              <NavItem itemId={0} isActive>
                System Panel
              </NavItem>
              <NavItem itemId={1}>Policy</NavItem>
              <NavItem itemId={2}>Authentication</NavItem>
              <NavItem itemId={3}>Network Services</NavItem>
              <NavItem itemId={4}>Server</NavItem>
            </NavList>
          </Nav>
        </PageGroup>
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page to verify grouped nav and breadcrumb - old / props syntax', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;
    const crumb = (
      <PageBreadcrumb>
        <Breadcrumb>
          <BreadcrumbItem>Section Home</BreadcrumbItem>
          <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
          <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
          <BreadcrumbItem to="#" isActive>
            Section Landing
          </BreadcrumbItem>
        </Breadcrumb>
      </PageBreadcrumb>
    );
    const nav = (
      <Nav aria-label="Nav" variant="horizontal-subnav">
        <NavList>
          <NavItem itemId={0} isActive>
            System Panel
          </NavItem>
          <NavItem itemId={1}>Policy</NavItem>
          <NavItem itemId={2}>Authentication</NavItem>
          <NavItem itemId={3}>Network Services</NavItem>
          <NavItem itemId={4}>Server</NavItem>
        </NavList>
      </Nav>
    );

    const { asFragment } = render(
      <Page
        {...props}
        masthead={masthead}
        sidebar={Sidebar}
        breadcrumb={crumb}
        horizontalSubnav={nav}
        isBreadcrumbGrouped
        isHorizontalSubnavGrouped
        groupProps={{
          stickyOnBreakpoint: { default: 'bottom' },
          hasShadowTop: true,
          hasOverflowScroll: true,
          'aria-label': 'test'
        }}
      >
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).not.toHaveAttribute('id');
    expect(screen.getByLabelText('test')).toHaveClass('pf-m-shadow-top');
    expect(asFragment()).toMatchSnapshot();
  });

  test('Check page to verify skip to content points to main content region', () => {
    const masthead = <Masthead />;
    const Sidebar = <PageSidebar isSidebarOpen />;
    const PageBreadcrumb = (
      <Breadcrumb>
        <BreadcrumbItem>Section Home</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#">Section Title</BreadcrumbItem>
        <BreadcrumbItem to="#" isActive>
          Section Landing
        </BreadcrumbItem>
      </Breadcrumb>
    );
    const mainId = 'main-content-page-layout-test-nav';
    const PageSkipToContent = <SkipToContent href={`#${mainId}`}>Skip to Content</SkipToContent>;

    const { asFragment } = render(
      <Page
        {...props}
        masthead={masthead}
        sidebar={Sidebar}
        breadcrumb={PageBreadcrumb}
        skipToContent={PageSkipToContent}
        mainContainerId={mainId}
        data-testid="page-test-id"
      >
        <PageSection variant="default">Section with default background</PageSection>
      </Page>
    );

    expect(screen.getByRole('main')).toHaveAttribute('id', mainId);
    expect(screen.getByTestId('page-test-id')).toHaveAttribute('id', props.id);
    expect(asFragment()).toMatchSnapshot();
  });

  test(`Does not render with class ${styles.modifiers.noSidebar} by default`, () => {
    render(<Page data-testid="page"></Page>);

    expect(screen.getByTestId('page')).not.toHaveClass(styles.modifiers.noSidebar);
  });

  test(`Does not render with class ${styles.modifiers.noSidebar} when sidebar prop is passed with valid content`, () => {
    render(<Page data-testid="page" sidebar={<div>sidebar content</div>}></Page>);

    expect(screen.getByTestId('page')).not.toHaveClass(styles.modifiers.noSidebar);
  });

  test(`Renders with class ${styles.modifiers.noSidebar} when sidebar is set to null`, () => {
    render(<Page data-testid="page" sidebar={null}></Page>);

    expect(screen.getByTestId('page')).toHaveClass(styles.modifiers.noSidebar);
  });

  test(`Does not render with ${styles.modifiers.fill} or ${styles.modifiers.noFill} if isContentFilled is not passed`, () => {
    render(<Page {...props} role="main"></Page>);

    expect(screen.getByRole('main').parentElement).not.toHaveClass(styles.modifiers.fill);
    expect(screen.getByRole('main').parentElement).not.toHaveClass(styles.modifiers.noFill);
  });

  test(`Renders with ${styles.modifiers.fill} if isContentFilled={true} is passed`, () => {
    render(<Page {...props} role="main" isContentFilled={true}></Page>);

    expect(screen.getByRole('main').parentElement).toHaveClass(styles.modifiers.fill);
  });

  test(`Does not render with ${styles.modifiers.noFill} if isContentFilled={false} is passed`, () => {
    render(<Page {...props} role="main" isContentFilled={false}></Page>);

    expect(screen.getByRole('main').parentElement).not.toHaveClass(styles.modifiers.noFill);
  });
});

describe('Page docked variant', () => {
  test(`Does not render with docked classes when variant is default`, () => {
    render(<Page {...props} variant="default" data-testid="page"></Page>);

    const page = screen.getByTestId('page');
    expect(page).not.toHaveClass(styles.modifiers.docked);
    expect(page.querySelector(`.${styles.pageDock}`)).not.toBeInTheDocument();
    expect(page.querySelector(`.${styles.pageDockMain}`)).not.toBeInTheDocument();
  });

  test(`Does not render with docked classes when variant is not passed`, () => {
    render(<Page data-testid="page"></Page>);

    const page = screen.getByTestId('page');
    expect(page).not.toHaveClass(styles.modifiers.docked);
    expect(page.querySelector(`.${styles.pageDock}`)).not.toBeInTheDocument();
    expect(page.querySelector(`.${styles.pageDockMain}`)).not.toBeInTheDocument();
  });

  test(`Renders with ${styles.modifiers.docked} class when variant is docked`, () => {
    render(<Page {...props} variant="docked" data-testid="page"></Page>);

    expect(screen.getByTestId('page')).toHaveClass(styles.modifiers.docked);
  });

  test('Renders dock content when dockContent and variant="docked" is passed', () => {
    render(<Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead</>} data-testid="page"></Page>);

    expect(screen.getByText('Dock content')).toBeInTheDocument();
  });

  test('Renders masthead content when masthead and variant="docked" is passed', () => {
    render(
      <Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead content</>} data-testid="page"></Page>
    );

    expect(screen.getByText('Masthead content')).toBeInTheDocument();
  });

  test(`Renders with ${styles.pageDock} wrapper when variant is docked`, () => {
    render(<Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead</>} data-testid="page"></Page>);

    const pageDock = screen.getByText('Dock content').closest(`.${styles.pageDock}`);
    expect(pageDock).toBeInTheDocument();
  });

  test(`Does not render with ${styles.modifiers.expanded} by default when variant is docked`, () => {
    render(<Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead</>} data-testid="page"></Page>);

    const pageDock = screen.getByText('Dock content').closest(`.${styles.pageDock}`);
    expect(pageDock).not.toHaveClass(styles.modifiers.expanded);
  });

  test(`Does not render with ${styles.modifiers.textExpanded} by default when variant is docked`, () => {
    render(<Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead</>} data-testid="page"></Page>);

    const pageDock = screen.getByText('Dock content').closest(`.${styles.pageDock}`);
    expect(pageDock).not.toHaveClass(styles.modifiers.textExpanded);
  });

  test(`Renders with ${styles.modifiers.expanded} when isDockExpanded is true and variant is docked`, () => {
    render(
      <Page
        variant="docked"
        isDockExpanded
        dockContent={<>Dock content</>}
        masthead={<>Masthead</>}
        data-testid="page"
      ></Page>
    );

    const pageDock = screen.getByText('Dock content').closest(`.${styles.pageDock}`);
    expect(pageDock).toHaveClass(styles.modifiers.expanded);
  });

  test(`Renders with ${styles.modifiers.textExpanded} when isDockTextExpanded is true and variant is docked`, () => {
    render(
      <Page
        variant="docked"
        isDockTextExpanded
        dockContent={<>Dock content</>}
        masthead={<>Masthead</>}
        data-testid="page"
      ></Page>
    );

    const pageDock = screen.getByText('Dock content').closest(`.${styles.pageDock}`);
    expect(pageDock).toHaveClass(styles.modifiers.textExpanded);
  });

  test(`Renders with ${styles.pageDockMain} wrapper when variant is docked`, () => {
    render(<Page variant="docked" dockContent={<>Dock content</>} masthead={<>Masthead</>} data-testid="page"></Page>);

    const pageDockMain = screen.getByText('Dock content').closest(`.${styles.pageDockMain}`);
    expect(pageDockMain).toBeInTheDocument();
  });
});
