import { getMinimalMe } from '../../../support/helpers';

describe('The Room Page (Teacher)', () => {
  const MeQuery = getMinimalMe();
  const selectedClass = MeQuery.me.selectedClass;
  const entryText = 'something should be here';
  const entryTitle = 'some title';
  const slug = 'ein-historisches-festival';
  const id = btoa('RoomNode:1');
  const room = {
    id,
    slug,
    schoolClass: selectedClass,
    restricted: false,
    roomEntries: {
      edges: [],
    },
  };

  const RoomEntriesQuery = {
    room,
  };

  const operations = {
    MeQuery,
    RoomEntriesQuery,
    AddRoomEntry: {
      addRoomEntry: {
        roomEntry: {
          slug: 'entry-slug',
          title: entryTitle,
          contents: [
            {
              type: 'text_block',
              value: {
                text: entryText,
              },
            },
          ],
          author: {
            firstName: 'Rachel',
            lastName: 'Green',
            id: window.btoa('PublicUserNode:rachels-id'),
          },
        },
        errors: [],
      },
    },
  };

  const checkRadioButton = () => {
    cy.get('.base-input-container__input:checked + .base-input-container__radiobutton svg').should('have.length', 1);
  };

  beforeEach(() => {
    cy.setup();
  });

  it('displays new room entry with author name', () => {
    cy.mockGraphqlOps({
      operations,
    });
    cy.visit(`/room/${slug}`);

    cy.getByDataCy('add-room-entry-button').click();
    cy.getByDataCy('add-content-link').first().click();
    cy.getByDataCy('choose-text-widget').click();
    cy.getByDataCy('input-with-label-input').type(entryTitle);

    cy.get('.tip-tap__editor').type(entryText);
    cy.getByDataCy('save-button').click();

    cy.get('.room-entry__content:first').should('contain', entryText).should('contain', 'Rachel Green');
  });

  // todo: re-enable once cypress can do it correctly
  it.skip('changes visibility of a room', () => {
    const MeQuery = getMinimalMe({
      isTeacher: true,
    });
    const operations = {
      MeQuery,
      RoomEntriesQuery,
      UpdateRoomVisibility: {
        updateRoomVisibility: {
          success: true,
          room: {
            ...room,
            restricted: true,
          },
        },
      },
    };

    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-visibility-status').should('contain', 'alle Lernenden');
    cy.getByDataCy('toggle-more-actions-menu').click();
    cy.getByDataCy('change-visibility').click();
    cy.getByDataCy('modal-title').should('contain', 'Sichtbarkeit anpassen');
    cy.get('.change-visibility__radio').should('have.length', 2);
    cy.get('.change-visibility__radio--selected').should('have.length', 1);
    checkRadioButton();
    cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'alle Lernenden');
    checkRadioButton();
    cy.getByDataCy('select-option').eq(0).click();
    cy.get('.change-visibility__radio--selected').should('have.length', 1);
    checkRadioButton();
    cy.getByDataCy('select-option').eq(1).click();
    cy.getByDataCy('select-option').eq(1).click();
    cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'eigenen Beiträge');
    checkRadioButton();
    cy.getByDataCy('modal-save-button').click();
    cy.getByDataCy('room-visibility-status').should('contain', 'eigenen Beiträge');
    cy.getByDataCy('toggle-more-actions-menu').click();
    cy.getByDataCy('change-visibility').click();
    cy.getByDataCy('modal-title').should('contain', 'Sichtbarkeit anpassen');
    cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'eigenen Beiträge');
    checkRadioButton();
  });

  it('deletes the room and goes back to the overview', () => {
    const MeQuery = getMinimalMe();
    const schoolClass = MeQuery.me.selectedClass;
    const roomToDelete = {
      id: window.btoa('RoomNode:room-to-delete'),
      title: 'Delete Me',
      schoolClass,
      slug: 'delete-me',
      roomEntries: {
        edges: [],
      },
    };
    const otherRoom = {
      id: window.btoa('RoomNode:otherRoom'),
      slug: 'other-slug',
      title: 'Other Room',
      schoolClass,
    };
    let rooms = [roomToDelete, otherRoom];
    const operations = {
      MeQuery,
      RoomsQuery() {
        return {
          rooms,
        };
      },
      RoomEntriesQuery: {
        room: roomToDelete,
      },
      DeleteRoom: {
        deleteRoom: {
          success: true,
        },
      },
    };
    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/rooms`);
    cy.getByDataCy('room-widget').should('have.length', 2);
    cy.getByDataCy('room-widget').first().click();
    cy.getByDataCy('room-title').should('contain', 'Delete Me');
    cy.getByDataCy('toggle-more-actions-menu').click();
    cy.getByDataCy('delete-room').within(() => {
      cy.get('a').click();
    });
    cy.getByDataCy('modal-save-button').click();
    cy.url().should('include', 'rooms');
    cy.getByDataCy('room-widget').should('have.length', 1);
  });

  it('changes class while on room page', () => {
    const { me } = MeQuery;
    const otherClass = {
      id: window.btoa('SchoolClassNode:34'),
      name: 'Other Class',
      readOnly: false,
    };
    let selectedClass = me.selectedClass;
    const operations = {
      MeQuery: () => {
        return {
          me: {
            ...me,
            schoolClasses: [...me.schoolClasses, otherClass],
            selectedClass,
          },
        };
      },
      RoomEntriesQuery,
      UpdateSettings() {
        selectedClass = otherClass;
        return {
          updateSettings: {
            success: true,
          },
        };
      },
      ModuleDetailsQuery: {},
      MySchoolClassQuery: () => {
        return {
          me: {
            selectedClass,
          },
        };
      },
      RoomsQuery: {
        rooms: [],
      },
    };

    cy.mockGraphqlOps({
      operations,
    });
    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-title').should('contain', 'A Room');
    cy.selectClass('Other Class');
    cy.url().should('include', 'rooms');
    cy.getByDataCy('current-class-name').should('contain', 'Other Class');
  });
});

describe('The Room Page (student)', () => {
  const slug = 'ein-historisches-festival';
  const MeQuery = getMinimalMe({ isTeacher: false });
  const { me } = MeQuery;
  const id = atob(me.id).split(':')[1];
  const authorId = btoa(`PublicUserNode:${id}`);
  const entrySlug = 'entry-slug';
  const { selectedClass } = me;
  const roomEntry = {
    id: 'entry-id',
    slug: entrySlug,
    title: 'My Entry',
    contents: [
      {
        type: 'text_block',
        value: {
          text: 'some text',
        },
      },
    ],
    comments: [{}, {}],
    author: {
      ...me,
      id: authorId,
      firstName: 'Hans',
      lastName: 'Was Heiri',
      avatarUrl: '',
    },
  };
  const room = {
    id,
    slug,
    schoolClass: selectedClass,
    restricted: false,
    roomEntries: {
      edges: [
        {
          node: roomEntry,
        },
      ],
    },
  };

  const RoomEntriesQuery = {
    room,
  };

  beforeEach(() => {
    cy.setup();
  });

  it('room actions should not exist for student', () => {
    const operations = {
      MeQuery: getMinimalMe({ isTeacher: false }),
      RoomEntriesQuery,
    };

    cy.mockGraphqlOps({
      operations,
    });
    cy.visit(`/room/${slug}`);

    cy.getByDataCy('room-title').should('exist');
    cy.getByDataCy('room-actions').should('not.exist');
  });

  it('creates a room entry', () => {
    const MeQuery = getMinimalMe({ isTeacher: false });
    const room = {
      id: 'some-room',
      roomEntries: {
        edges: [],
      },
    };
    const operations = {
      MeQuery,
      RoomEntriesQuery: {
        room,
      },
    };

    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('add-room-entry-button').click();

    cy.getByDataCy('content-form-section-title').should('have.text', 'Titel (Pflichtfeld)');
  });

  it.only('creates a room entry and presses "Save" twice', () => {
    const MeQuery = getMinimalMe({ isTeacher: false });
    const room = {
      id: 'some-room',
      roomEntries: {
        edges: [],
      },
    };
    const requestTime = 500;
    const operations = {
      MeQuery,
      RoomEntriesQuery: {
        room,
      },
      AddRoomEntry: () => {
        return new Promise((resolve) => {
          // simulate a slow-ish connection
          setTimeout(() => {
            resolve({
              addRoomEntry: {
                roomEntry: {
                  slug: 'entry-slug',
                  title: 'Some Title',
                  contents: [
                    {
                      type: 'text_block',
                      value: {
                        text: 'Redrum!',
                      },
                    },
                  ],
                  author: {
                    firstName: 'Stephen',
                    lastName: 'King',
                    id: window.btoa('PublicUserNode:stephen-king'),
                  },
                },
              },
            });
          }, requestTime);
        });
      },
    };

    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('add-room-entry-button').click();

    cy.getByDataCy('content-form-section-title').should('have.text', 'Titel (Pflichtfeld)');
    cy.getByDataCy('content-block-title').within(() => {
      cy.getByDataCy('input-with-label-input').type('Title');
    });

    cy.getByDataCy('add-content-link').click();
    cy.getByDataCy('choose-text-widget').click();
    cy.get('.tip-tap__editor').type('Some text');
    cy.getByDataCy('save-button').click();
    cy.getByDataCy('save-button').click();
    cy.getByDataCy('room-title').should('contain', 'A Room');
    cy.wait(2 * requestTime); // wait for both requests to finish, if there's more than one
    cy.getByDataCy('room-entry').should('have.length', 1);
  });

  it('edits own room entry', () => {
    const room = {
      id: 'some-room',
      slug,
      // schoolClass: me.selectedClass,
      roomEntries: {
        edges: [
          {
            node: roomEntry,
          },
        ],
      },
    };
    const operations = {
      MeQuery: MeQuery,
      RoomEntriesQuery: {
        room,
      },
      RoomEntryQuery: {
        roomEntry,
      },
    };
    cy.mockGraphqlOps({
      operations,
    });
    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-entry-actions').click();
    cy.getByDataCy('edit-room-entry').click();
    cy.location('pathname').should('include', entrySlug);
  });

  it('deletes room entry', () => {
    const DeleteRoomEntry = {
      deleteRoomEntry: {
        success: true,
        errors: null,
        roomSlug: slug,
      },
    };

    const operations = {
      MeQuery,
      RoomEntriesQuery,
      DeleteRoomEntry,
    };

    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-entry').should('have.length', 1);
    cy.getByDataCy('room-entry-actions').click();
    cy.getByDataCy('delete-room-entry').click();
    cy.getByDataCy('delete-room-entry').should('not.exist');
    cy.getByDataCy('modal-save-button').click();
    cy.getByDataCy('room-entry').should('have.length', 0);
  });

  it('shows room entries with comment count', () => {
    const operations = {
      MeQuery,
      RoomEntriesQuery,
    };
    cy.mockGraphqlOps({
      operations,
    });

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-entry')
      .should('have.length', 1)
      .within(() => {
        cy.getByDataCy('entry-count').should('contain.text', '2');
      });
  });

  it('does not show actions on mobile', () => {
    const operations = {
      MeQuery,
      RoomEntriesQuery,
    };
    cy.mockGraphqlOps({
      operations,
    });
    cy.viewport('iphone-8');

    cy.visit(`/room/${slug}`);
    cy.getByDataCy('room-actions').should('not.exist');
    cy.getByDataCy('room-entry').should('have.length', 1);
    cy.getByDataCy('room-entry-actions').should('not.be.visible');
  });
});
