<?php

declare(strict_types=1);

namespace Drupal\farm_input\Plugin\views\filter;

use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormStateInterface;
use Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid;
use Drupal\views\Attribute\ViewsFilter;
use Drupal\views\Plugin\views\query\Sql;

/**
 * Filter handler for log quantity material type terms.
 */
#[ViewsFilter("log_quantity_material_type")]
class LogQuantityMaterialType extends TaxonomyIndexTid {

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    // Hard code the material_type vocabulary.
    $options['vid'] = ['default' => 'material_type'];
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildExtraOptionsForm($form, $form_state);
    // Remove the vocabulary form element, use the hard coded default.
    unset($form['vid']);
  }

  /**
   * {@inheritdoc}
   */
  public function query() {

    // Bail if not a SQL query.
    if (!$this->query instanceof Sql) {
      return;
    }

    // Bail if there are no filter values.
    if (count($this->value) == 0) {
      return;
    }
    elseif (count($this->value) == 1) {
      // Sometimes $this->value is an array with a single element so convert it.
      // @see TaxonomyIndexTidDepth::query().
      if (is_array($this->value)) {
        $this->value = current($this->value);
      }
      $operator = '=';
    }
    else {
      $operator = 'IN';
    }

    // Build a subquery to find logs that reference a quantity with the
    // specified material type.
    $subquery = Database::getConnection()->select('log', 'l');
    $subquery->addField('l', 'id');
    $subquery->innerJoin('log__quantity', 'lq', 'l.id = lq.entity_id');
    $subquery->innerJoin('quantity__material_type', 'qmt', 'lq.quantity_target_id = qmt.entity_id AND lq.quantity_target_revision_id = qmt.revision_id');
    $subquery->condition('qmt.material_type_target_id', $this->value, $operator);

    // Get the table alias for log_field_data.
    $this->tableAlias = $this->query->ensureTable($this->view->storage->get('base_table'));

    // Use the subquery in a condition on the views query to prevent duplicates.
    // PHPStan throws the following error on the next line:
    // Parameter #3 $value of method
    // Drupal\views\Plugin\views\query\Sql::addWhere() expects
    // array|string|null, Drupal\Core\Database\Query\SelectInterface given.
    // We ignore this because subqueries are also accepted, even though they are
    // not documented.
    // @phpstan-ignore argument.type
    $this->query->addWhere($this->options['group'], "$this->tableAlias.id", $subquery, 'IN');
  }

}
