import React from 'react';
import { describe, beforeEach, it } from 'mocha';
import { Accordion as Interactor, Keyboard } from '@folio/stripes-testing';
import sinon from 'sinon';
import { mountWithContext } from '../../../tests/helpers';

import Accordion from '../Accordion';
import AccordionSet from '../AccordionSet';

describe('Accordion', () => {
  const accordion = Interactor('test');

  beforeEach(async () => {
    await mountWithContext(
      <Accordion label="test">
        <div style={{ height: 100 }}>
          Test Content.
        </div>
      </Accordion>
    );
  });

  it('is open by default', () => accordion.is({ open: true }));

  it('sets the appropriate content height', () => accordion.has({ contentHeight: 100 }));

  it('has a label', () => accordion.has({ label: 'test' }));

  describe('when closed', () => {
    beforeEach(async () => {
      await mountWithContext(
        <Accordion label="test" open={false}>
          <div style={{ height: 100 }}>
            Test Content.
          </div>
        </Accordion>
      );
    });

    it('content is hidden', () => accordion.has({ open: false }));
  });

  describe('clicking the header', () => {
    beforeEach(() => accordion.clickHeader());

    it('closes the accordion', () => accordion.is({ open: false }));

    describe('clicking the header again', () => {
      beforeEach(() => accordion.clickHeader());

      it('opens the accordion', () => accordion.is({ open: true }));
    });
  });

  describe('when the accordion is closed by default', () => {
    beforeEach(async () => {
      await mountWithContext(
        <Accordion label="test" closedByDefault>
          <div style={{ height: 100 }}>
            Test Content
          </div>
        </Accordion>
      );
    });

    it('is closed by default', () => accordion.is({ open: false }));

    describe('clicking the header', () => {
      beforeEach(() => accordion.clickHeader());

      it('opens the accordion', () => accordion.is({ open: true }));

      describe('clicking the header again', () => {
        beforeEach(() => accordion.clickHeader());

        it('closes the accordion', () => accordion.is({ open: false }));
      });
    });
  });

  describe('with an id', () => {
    beforeEach(async () => {
      await mountWithContext(
        <Accordion label="test" id="accordion-test">
          <div style={{ height: 100 }} />
        </Accordion>
      );
    });

    it('has an id on the root element', () => accordion.has({ id: 'accordion-test' }));

    it('is open by default', () => accordion.is({ open: true }));
  });

  describe('with a content id', () => {
    beforeEach(async () => {
      await mountWithContext(
        <Accordion label="test" open contentId="content-test">
          <div style={{ height: 100 }} />
        </Accordion>
      );
    });

    it('has an id on the accordion-wrapper element', () => accordion.has({ contentId: 'content-test' }));
  });

  describe('without a content id', () => {
    beforeEach(async () => {
      await mountWithContext(
        <Accordion label="test">
          <div style={{ height: 100 }} />
        </Accordion>
      );
    });

    it('creates an id on the accordion-wrapper element', async () => {
      await accordion.has({ contentId: '@@autogenerated@@' });
    });
  });

  describe('onToggle callback', () => {
    const testToggle = sinon.spy();
    beforeEach(async () => {
      await mountWithContext(
        <Accordion
          id="testId"
          label="test"
          onToggle={testToggle}
          open
        >
          <div style={{ height: 100 }}>
            Test Content.
          </div>
        </Accordion>
      );
    });

    describe('clicking the header', () => {
      beforeEach(async () => {
        await accordion.clickHeader();
      });

      it('supplies id and label parameters to onToggle()', async () => {
        await testToggle.withArgs({ id: 'testId', label: 'test' }).calledOnce;
      });
    });
  });

  describe('as part of an AccordionSet', () => {
    const first = Interactor({ index: 0 });
    const second = Interactor({ index: 1 });
    const last = Interactor({ index: 3 });

    beforeEach(async () => {
      await mountWithContext(
        <AccordionSet>
          <Accordion label="test">
            <input />
          </Accordion>
          <Accordion label="test">
            <input />
          </Accordion>
          <Accordion label="test">
            <input />
          </Accordion>
          <Accordion label="test">
            <input />
          </Accordion>
        </AccordionSet>
      );
    });

    describe('keyboard navigation: next accordion', () => {
      beforeEach(async () => {
        await first.focus();
        await Keyboard.arrowDown();
      });

      it('second accordion is in focus', () => second.is({ focused: true }));
    });

    describe('keyboard navigation: previous accordion', () => {
      beforeEach(async () => {
        await second.focus();
        await Keyboard.arrowUp();
      });

      it('first accordion is in focus', () => first.is({ focused: true }));
    });

    describe('keyboard navigation: last accordion', () => {
      beforeEach(async () => {
        await first.focus();
        await Keyboard.end();
      });

      it('Last accordion is in focus', () => last.is({ focused: true }));
    });

    describe('keyboard navigation: first accordion', () => {
      beforeEach(async () => {
        await last.focus();
        await Keyboard.home();
      });

      it('First accordion is in focus', () => first.is({ focused: true }));
    });
  });
});
