<?php

declare(strict_types=1);

namespace Drupal\Tests\visitors\Unit\Form;

use Drupal\Tests\UnitTestCase;
use Drupal\visitors\Form\DateFilterForm;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Date filter form test.
 *
 * @group visitors
 * @coversDefaultClass \Drupal\visitors\Form\DateFilterForm
 * @uses \Drupal\visitors\Form\DateFilterForm
 */
class DateFilterFormTest extends UnitTestCase {

  /**
   * The form.
   *
   * @var \Drupal\visitors\Form\DateFilterForm
   */
  protected $form;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $messenger;

  /**
   * The state.
   *
   * @var \Drupal\Core\State\StateInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $state;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $requestStack;

  /**
   * The database.
   *
   * @var \Drupal\Core\Database\Connection|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $database;

  /**
   * The date time.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $dateTime;

  /**
   * The date range service.
   *
   * @var \Drupal\visitors\Service\DateRangeService|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $dateRangeService;

  /**
   * The date formatter.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected $dateFormatter;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $container = new ContainerBuilder();

    $string_translation = $this->getStringTranslationStub();
    $container->set('string_translation', $string_translation);

    $this->dateFormatter = $this->createMock('Drupal\Core\Datetime\DateFormatterInterface');
    $container->set('date.formatter', $this->dateFormatter);

    $this->dateRangeService = $this->createMock('Drupal\visitors\Service\DateRangeService');
    $container->set('visitors.date_range', $this->dateRangeService);

    $language = $this->createMock('Drupal\Core\Language\LanguageInterface');
    $language->method('getId')->willReturn('en');
    $language_manager = $this->createMock('Drupal\Core\Language\LanguageManagerInterface');
    $language_manager->method('getCurrentLanguage')->willReturn($language);
    $container->set('language_manager', $language_manager);

    \Drupal::setContainer($container);

    $this->form = DateFilterForm::create($container);
  }

  /**
   * Tests the create method.
   *
   * @covers ::create
   */
  public function testCreate() {
    $container = \Drupal::getContainer();
    $form = DateFilterForm::create($container);

    $this->assertInstanceOf(DateFilterForm::class, $form);
  }

  /**
   * Test the constructor.
   *
   * @covers ::__construct
   */
  public function testConstructor() {
    $form = new DateFilterForm(
      $this->dateFormatter,
      $this->dateRangeService,
    );
    $this->assertInstanceOf(DateFilterForm::class, $form);
  }

  /**
   * Test the form id.
   *
   * @covers ::getFormId
   */
  public function testGetFormId() {
    $this->assertEquals('visitors_date_filter_form', $this->form->getFormId());
  }

  /**
   * Test the form build.
   *
   * @covers ::buildForm
   */
  public function testBuildForm() {
    $form_state = $this->createMock('Drupal\Core\Form\FormStateInterface');
    $form = $this->form->buildForm([], $form_state);
    $this->assertIsArray($form);
    $this->assertCount(1, $form);
    $this->assertIsArray($form['visitors_date_filter']);
    $this->assertCount(8, $form['visitors_date_filter']);

    $this->assertArrayHasKey('visitors_date_filter', $form);
    $this->assertArrayHasKey('submit', $form['visitors_date_filter']);
  }

  /**
   * Test the submitForm method.
   *
   * @covers ::submitForm
   */
  public function testSubmitForm() {
    $form = [];
    $form_state = $this->createMock('Drupal\Core\Form\FormStateInterface');
    $form_state->expects($this->exactly(3))
      ->method('getValue')
      ->willReturnMap([
        ['from', NULL, '2020-01-01'],
        ['to', NULL, '2020-01-01'],
        ['period', NULL, 'day'],
      ]);

    $this->dateRangeService->expects($this->once())
      ->method('setPeriodAndDates')
      ->with('day', '2020-01-01', '2020-01-01');

    $this->form->submitForm($form, $form_state);
  }

}
