<?php

declare(strict_types=1);

namespace Drupal\sobki_background_image\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\file\FileInterface;
use Drupal\image\ImageStyleInterface;
use Drupal\media\MediaInterface;
use Drupal\sobki_background_image\Form\SettingsForm;

/**
 * Provides the default background image style generator.
 */
class BackgroundImageStyle implements BackgroundImageStyleInterface {

  public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
    protected FileUrlGeneratorInterface $fileUrlGenerator,
    protected ConfigFactoryInterface $configFactory,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function getBackgroundImageStyle(array $settings): array {
    if (empty($settings)) {
      return [];
    }

    $mediaUuid = $settings['media'] ?? '';
    if (!$mediaUuid) {
      return [];
    }

    /** @var \Drupal\media\MediaInterface[] $medias */
    $medias = $this->entityTypeManager->getStorage('media')->loadByProperties([
      'uuid' => $mediaUuid,
    ]);
    if (empty($medias)) {
      return [];
    }

    $media = \array_shift($medias);
    $fileUri = $this->getFileUri($media);
    if (!$fileUri) {
      return [];
    }

    return [
      'background-image: url("' . $this->getBackgroundImageUrl($fileUri, $settings) . '");',
      (!empty($settings['position_x']) && \is_string($settings['position_x'])) ? 'background-position-x: ' . $settings['position_x'] . ';' : '',
      (!empty($settings['position_y']) && \is_string($settings['position_y'])) ? 'background-position-y: ' . $settings['position_y'] . ';' : '',
      (!empty($settings['attachment']) && \is_string($settings['attachment'])) ? 'background-attachment: ' . $settings['attachment'] . ';' : '',
      (!empty($settings['repeat']) && \is_string($settings['repeat'])) ? 'background-repeat: ' . $settings['repeat'] . ';' : '',
      (!empty($settings['size']) && \is_string($settings['size'])) ? 'background-size: ' . $settings['size'] . ';' : '',
      (!empty($settings['size']) && \is_string($settings['size'])) ? '-webkit-background-size: ' . $settings['size'] . ';' : '',
      (!empty($settings['size']) && \is_string($settings['size'])) ? '-moz-background-size: ' . $settings['size'] . ';' : '',
      (!empty($settings['size']) && \is_string($settings['size'])) ? '-o-background-size: ' . $settings['size'] . ';' : '',
    ];
  }

  /**
   * Get the file URI of the background image.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The referenced media.
   *
   * @return string
   *   The file URI or empty string of not found.
   */
  protected function getFileUri(MediaInterface $media): string {
    $config = $this->configFactory->get(SettingsForm::CONFIG_NAME);
    $mapping = $config->get('media_bundle_mapping');

    $mediaType = $media->bundle();
    if (!\is_array($mapping) || !isset($mapping[$mediaType])) {
      return '';
    }

    /** @var string $fieldName */
    $fieldName = $mapping[$mediaType];
    if (!($media->hasField($fieldName))) {
      return '';
    }

    $field = $media->get($fieldName);
    if (!($field instanceof EntityReferenceFieldItemListInterface)) {
      return '';
    }

    foreach ($field->referencedEntities() as $file) {
      if ($file instanceof FileInterface) {
        $fileUri = $file->getFileUri();
        if (\is_string($fileUri)) {
          return $fileUri;
        }
      }
    }
    return '';
  }

  /**
   * Get the background image URL.
   *
   * @param string $fileUri
   *   The file URI.
   * @param array $settings
   *   The background image settings.
   *
   * @return string
   *   The background image URL.
   */
  protected function getBackgroundImageUrl(string $fileUri, array $settings): string {
    $style = NULL;
    if (!empty($settings['image_style']) && \is_string($settings['image_style'])) {
      $style = $this->entityTypeManager->getStorage('image_style')
        ->load($settings['image_style']);
    }

    if ($style instanceof ImageStyleInterface) {
      return $this->fileUrlGenerator->transformRelative($style->buildUrl($fileUri));
    }

    return $this->fileUrlGenerator->transformRelative($this->fileUrlGenerator->generateString($fileUri));
  }

}
