<?php

namespace Drupal\straker_translate\Plugin\StrakerTranslateFormComponent\Filter;

use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\straker_translate\FormComponent\StrakerTranslateFormComponentBundleTrait;
use Drupal\straker_translate\FormComponent\StrakerTranslateFormComponentFilterBase;

/**
 * Defines a Straker Translate form-filter plugin for the entity bundle.
 *
 * @StrakerTranslateFormComponentFilter(
 *   id = "bundle",
 *   title = @Translation("Bundle"),
 *   form_ids = {
 *     "straker_translate_management",
 *   },
 *   weight = 50,
 * )
 */
class Bundle extends StrakerTranslateFormComponentFilterBase {

  use DependencySerializationTrait;
  use StrakerTranslateFormComponentBundleTrait;

  /**
   * {@inheritdoc}
   */
  public function isApplicable(array $arguments = []) {
    $entity_type_id = $arguments['entity_type_id'] ?? NULL;
    return $this->hasBundles($entity_type_id);
  }

  /**
   * {@inheritdoc}
   */
  public function buildElement($default_value = NULL) {
    return [
      '#type' => 'select',
      '#title' => $this->getEntityType($this->entityTypeId)->getBundleLabel(),
      '#default_value' => (array) $default_value,
      '#options' => ['' => $this->t('All')] + $this->getAllBundles(),
      '#multiple' => TRUE,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function filter(string $entity_type_id, array $entities, $value, SelectInterface &$query = NULL) {
    if ($this->hasBundles($entity_type_id) && !in_array('', $value, TRUE)) {
      parent::filter($entity_type_id, $entities, $value, $query);
      $query->condition('entity_table.' . $this->getEntityType($entity_type_id)->getKey('bundle'), $value, 'IN');
      if ($unions = $query->getUnion()) {
        foreach ($unions as $union) {
          $union['query']->condition('entity_table.' . $this->getEntityType($entity_type_id)->getKey('bundle'), $value, 'IN');
        }
      }
    }
    else {
      $bundle_key = $this->getEntityType($entity_type_id)->getKey('bundle');

      // Get StrakerTranslate-enabled bundles.
      $straker_translate_bundles = array_filter(
        array_keys($this->getBundleInfo($entity_type_id)),
        fn($bundle) => \Drupal::service('straker_translate.configuration')->isEnabled($entity_type_id, $bundle)
      );

      if (!empty($straker_translate_bundles)) {
        $query->condition("entity_table.$bundle_key", $straker_translate_bundles, 'IN');

        // Apply the same filter to union queries if they exist.
        if ($unions = $query->getUnion()) {
          foreach ($unions as $union) {
            $union['query']->condition("entity_table.$bundle_key", $straker_translate_bundles, 'IN');
          }
        }
      }
    }
  }

  /**
   * Gets all the bundles as options.
   *
   * @return array
   *   The bundles as a valid options array.
   */
  protected function getAllBundles() {
    $bundles = $this->getBundleInfo($this->entityTypeId);
    $options = [];

    foreach ($bundles as $id => $bundle) {
      $options[$id] = $bundle['label'];
    }

    asort($options);

    return $options;
  }

}
