import { describe, expect, it, vi } from 'vitest';
import * as React from 'react';
import { fireEvent, render, screen } from '../../utils/test-utils';
import { ElementsSidebar } from './ElementsSidebar';
import { IContainerModel } from '../../Interfaces/ContainerModel';

describe.concurrent('Elements sidebar', () => {
  it('With a MainContainer', () => {
    render(<ElementsSidebar
      MainContainer={{
        children: [],
        parent: null,
        properties: {
          id: 'main',
          parentId: null,
          x: 0,
          y: 0,
          width: 2000,
          height: 100
        },
        userData: {}
      }}
      isOpen={true}
      isHistoryOpen={false}
      SelectedContainer={null}
      onPropertyChange={() => {}}
      SelectContainer={() => {}}
      DeleteContainer={() => {}}
      AddContainer={() => {}}
    />);

    expect(screen.getByText(/Elements/i));
    expect(screen.queryByText('id')).toBeNull();
    expect(screen.getByText(/main/i));
  });

  it('With a selected MainContainer', () => {
    const MainContainer = {
      children: [],
      parent: null,
      properties: {
        id: 'main',
        parentId: '',
        x: 0,
        y: 0,
        width: 2000,
        height: 100
      },
      userData: {}
    };

    const { container } = render(<ElementsSidebar
      MainContainer={MainContainer}
      isOpen={true}
      isHistoryOpen={false}
      SelectedContainer={MainContainer}
      onPropertyChange={() => {}}
      SelectContainer={() => {}}
      DeleteContainer={() => {}}
      AddContainer={() => {}}
    />);

    expect(screen.getByText(/Elements/i));
    expect(screen.getByText(/main/i));
    expect(screen.queryByText('id')).toBeDefined();
    expect(screen.queryByText('parentId')).toBeDefined();
    expect(screen.queryByText('x')).toBeDefined();
    expect(screen.queryByText('y')).toBeDefined();
    expect(screen.queryByText('width')).toBeDefined();
    expect(screen.queryByText('height')).toBeDefined();
    const propertyId = container.querySelector('#property-id');
    const propertyParentId = container.querySelector('#property-parentId');
    const propertyX = container.querySelector('#property-x');
    const propertyY = container.querySelector('#property-y');
    const propertyWidth = container.querySelector('#property-width');
    const propertyHeight = container.querySelector('#property-height');
    expect((propertyId as HTMLInputElement).value).toBe(MainContainer.properties.id.toString());
    expect(propertyParentId).toBeDefined();
    expect((propertyParentId as HTMLInputElement).value).toBe('');
    expect(propertyX).toBeDefined();
    expect((propertyX as HTMLInputElement).value).toBe(MainContainer.properties.x.toString());
    expect(propertyY).toBeDefined();
    expect((propertyY as HTMLInputElement).value).toBe(MainContainer.properties.y.toString());
    expect(propertyWidth).toBeDefined();
    expect((propertyWidth as HTMLInputElement).value).toBe(MainContainer.properties.width.toString());
    expect(propertyHeight).toBeDefined();
    expect((propertyHeight as HTMLInputElement).value).toBe(MainContainer.properties.height.toString());
  });

  it('With multiple containers', () => {
    const children: IContainerModel[] = [];
    const MainContainer = {
      children,
      parent: null,
      properties: {
        id: 'main',
        parentId: '',
        x: 0,
        y: 0,
        width: 2000,
        height: 100
      },
      userData: {}
    };

    children.push(
      {
        children: [],
        parent: MainContainer,
        properties: {
          id: 'child-1',
          parentId: 'main',
          x: 0,
          y: 0,
          width: 0,
          height: 0
        },
        userData: {}
      }
    );

    children.push(
      {
        children: [],
        parent: MainContainer,
        properties: {
          id: 'child-2',
          parentId: 'main',
          x: 0,
          y: 0,
          width: 0,
          height: 0
        },
        userData: {}
      }
    );

    render(<ElementsSidebar
      MainContainer={MainContainer}
      isOpen={true}
      isHistoryOpen={false}
      SelectedContainer={MainContainer}
      onPropertyChange={() => {}}
      SelectContainer={() => {}}
      DeleteContainer={() => {}}
      AddContainer={() => {}}
    />);

    expect(screen.getByText(/Elements/i));
    expect(screen.queryByText('id')).toBeDefined();
    expect(screen.getByText(/main/i));
    expect(screen.getByText(/child-1/i));
    expect(screen.getByText(/child-2/i));
  });

  it('With multiple containers, change selection', () => {
    const children: IContainerModel[] = [];
    const MainContainer: IContainerModel = {
      children,
      parent: null,
      properties: {
        id: 'main',
        parentId: '',
        x: 0,
        y: 0,
        width: 2000,
        height: 100
      },
      userData: {}
    };

    const child1Model: IContainerModel = {
      children: [],
      parent: MainContainer,
      properties: {
        id: 'child-1',
        parentId: 'main',
        x: 0,
        y: 0,
        width: 0,
        height: 0
      },
      userData: {}
    };
    children.push(child1Model);

    let SelectedContainer = MainContainer;
    const selectContainer = vi.fn((container: IContainerModel) => {
      SelectedContainer = container;
    });

    const { container, rerender } = render(<ElementsSidebar
      MainContainer={MainContainer}
      isOpen={true}
      isHistoryOpen={false}
      SelectedContainer={SelectedContainer}
      onPropertyChange={() => {}}
      SelectContainer={selectContainer}
      DeleteContainer={() => {}}
      AddContainer={() => {}}
    />);

    expect(screen.getByText(/Elements/i));
    expect(screen.queryByText('id')).toBeDefined();
    expect(screen.getByText(/main/i));
    const child1 = screen.getByText(/child-1/i);
    expect(child1);
    const propertyId = container.querySelector('#property-id');
    const propertyParentId = container.querySelector('#property-parentId');
    expect((propertyId as HTMLInputElement).value).toBe(MainContainer.properties.id.toString());
    expect((propertyParentId as HTMLInputElement).value).toBe('');

    fireEvent.click(child1);

    rerender(<ElementsSidebar
      MainContainer={MainContainer}
      isOpen={true}
      isHistoryOpen={false}
      SelectedContainer={SelectedContainer}
      onPropertyChange={() => {}}
      SelectContainer={selectContainer}
      DeleteContainer={() => {}}
      AddContainer={() => {}}
    />);

    expect((propertyId as HTMLInputElement).value === 'main').toBeFalsy();
    expect((propertyParentId as HTMLInputElement).value === '').toBeFalsy();
    expect((propertyId as HTMLInputElement).value).toBe(child1Model.properties.id.toString());
    expect((propertyParentId as HTMLInputElement).value).toBe(child1Model.properties.parentId?.toString());
  });
});
