<?php

namespace Drupal\Tests\acquia_dam\FunctionalJavascript;

use Drupal\acquia_dam\Entity\MediaSourceField;
use Drupal\image\Entity\ImageStyle;
use Drupal\media\Entity\Media;
use Drupal\Tests\ckeditor5\Traits\CKEditor5TestTrait;

/**
 * Focal point element test.
 *
 * @requires module focal_point
 * @requires module crop
 * @requires module ckeditor
 *
 * @group acquia_dam_functional_javascript_integration
 */
class FocalPointMediaLibraryTest extends AcquiaDamWebDriverTestBase {

  use CKEditor5TestTrait;

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'starterkit_theme';

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'focal_point',
  ];

  /**
   * Test DAM media with focal point.
   */
  public function testFocalPointElement() {
    $this->createAndLoginContentCreator();
    $this->grantSiteRegistrationToken();
    $this->grantCurrentUserDamToken();

    $image_style = ImageStyle::create(['name' => 'Focal Point']);
    $image_style->addImageEffect([
      'id' => 'focal_point_crop',
      'data' => [
        'width' => 200,
        'height' => 200,
        'crop_type' => 'focal_point',
      ],
    ]);
    $image_style->save();

    $this->drupalGet('/node/add/page');
    $this->waitForEditor();
    $this->pressEditorButton('Insert Media');

    $modal = $this->assertSession()->waitForElement('css', '#drupal-modal');
    $modal->clickLink('Image');
    $this->assertSession()->assertWaitOnAjaxRequest();

    $media_select_checkbox = $this->assertSession()->waitForElementVisible('css', '[value="f2a9c03d-3664-477c-8013-e84504ed5adc"]');
    $media_select_checkbox->check();

    $this->pressDialogButton('Next: Select Format');
    $this->assertSession()->waitForText('Choose a format for your media');
    $this->getSession()->getPage()->selectFieldOption('embed_code', 'Focal Point');

    $this->assertSession()->waitForElementVisible('css', '.focal-point-indicator');
    $elements = $this->getSession()->getPage()->findAll('css', '.focal-point-indicator');
    $this->assertTrue(count($elements) === 1);

    $this->getSession()->getPage()->selectFieldOption('embed_code', 'large');
    $this->assertSession()->waitForElementRemoved('css', '.focal-point-indicator');
    $elements = $this->getSession()->getPage()->findAll('css', '.focal-point-indicator');
    $this->assertTrue(count($elements) === 0);
  }

  /**
   * Tests form submit updates crop entity.
   */
  public function testDamAssetEditFormSubmitUpdatesCropAndFlushesStyle(): void {
    $user = $this->drupalCreateUser([
      'use text format test_format',
      'access media overview',
      'create page content',
      'edit any page content',
      'edit any acquia_dam_image_asset media',
    ]);

    $this->drupalLogin($user);
    $this->grantSiteRegistrationToken();
    $this->grantCurrentUserDamToken();

    // Create image style with focal point crop effect.
    $image_style = ImageStyle::create([
      'name' => 'test',
      'label' => 'Test image style',
    ]);
    $image_style->save();
    $image_style->addImageEffect([
      'id' => 'focal_point_crop',
      'data' => [
        'width' => 50,
        'height' => 50,
        'crop_type' => 'focal_point',
      ],
    ]);
    $image_style->save();

    // Create image media type and DAM media.
    $media = Media::create([
      'bundle' => 'acquia_dam_image_asset',
      MediaSourceField::SOURCE_FIELD_NAME => [
        'asset_id' => '56ff14de-02cd-41b5-9a73-c917eab19abf',
        'version_id' => '7b67948f-ee7e-405c-a0cd-344a24d8afb2',
      ],
    ]);
    $media->save();

    // Seed initial crop at 80,60.
    $image_style_helper = $this->container->get('acquia_dam.image_style_support');
    $image_style_helper->saveCropEntity(80, 60, $media, $image_style->id());

    // Visit media edit form.
    $this->drupalGet($media->toUrl('edit-form'));
    $this->assertSession()->pageTextContains('Test image style');

    // Assert initial focal point value.
    $this->assertSession()->elementExists('css', '[name="focal_points[test][focal_point]"]');
    $field = $this->getSession()->getPage()->find('css', '[name="focal_points[test][focal_point]"]');
    $this->assertNotNull($field, 'Focal point field exists.');
    $this->assertEquals('80,60', $field->getValue(), 'Initial focal point value is 80,60.');

    // Submit new focal point 30,70.
    $page = $this->getSession()->getPage();
    $field = $page->find('css', '[name="focal_points[test][focal_point]"]');
    $this->getSession()->executeScript("document.querySelector('[name=\"focal_points[test][focal_point]\"]').value = '30,70';");
    $page->pressButton('Save');
    // Reload media and verify crop updated.
    $media = \Drupal::entityTypeManager()
      ->getStorage('media')
      ->load($media->id());
    $crops = $image_style_helper->getCrops($media);
    $this->assertCount(1, $crops, 'One crop entity exists for the media.');
    $crop = reset($crops);

    $image_properties = $media->getSource()->getMetadata($media, 'image_properties');
    $position = $crop->position();
    $relative = $image_style_helper->absoluteToRelative(
      $position['x'],
      $position['y'],
      $image_properties['width'],
      $image_properties['height']
    );

    $this->assertEquals(30, $relative['x'], 'Crop X position updated to 30.');
    $this->assertEquals(70, $relative['y'], 'Crop Y position updated to 70.');
  }

}
