<?php

namespace Drupal\basket\Query;

use Drupal\views\Views;

/**
 * Determination of product balances according to the settings.
 */
class BasketGetNodeCountsQuery {

  /**
   * Set getQuery.
   *
   * @var object
   */
  protected static $getQuery;

  /**
   * Set getNodeTypesFields.
   *
   * @var array
   */
  protected static $getNodeTypesFields;

  /**
   * {@inheritdoc}
   */
  public static function getQuery() {
    if (!self::$getQuery) {
      self::$getQuery = NULL;
      $getNodeTypesFields = self::getNodeTypesFields();
      if (!empty($getNodeTypesFields)) {
        $queries = [];
        foreach ($getNodeTypesFields as $countField => $keyNodeTypes) {
          $countFields = explode('->', $countField);
          $isAddPrice = FALSE;
          switch (count($countFields)) {
            case 1:
              $countFields = reset($countFields);
              if (\Drupal::database()->schema()->tableExists('node__' . $countFields)) {
                $queries[$countField] = \Drupal::database()->select('node__' . $countFields, $countFields);
                $queries[$countField]->addExpression($countFields . '.entity_id', 'nid');
                $queries[$countField]->addExpression('SUM(' . $countFields . '.' . $countFields . '_value)', 'count');
                $queries[$countField]->groupBy($countFields . '.entity_id');
              }
              break;

            case 2:
              if (\Drupal::database()->schema()->tableExists("node__$countFields[0]") && \Drupal::database()->schema()->tableExists("paragraph__$countFields[1]")) {
                $queries[$countField] = \Drupal::database()->select("node__$countFields[0]", $countFields[0]);
                $queries[$countField]->addExpression("$countFields[0].entity_id", 'nid');
                $queries[$countField]->leftJoin("paragraph__$countFields[1]", $countFields[1], "$countFields[1].entity_id = $countFields[0].$countFields[0]_target_id");
                $queries[$countField]->addExpression("SUM(IF($countFields[1].$countFields[1]_value > 0, $countFields[1].$countFields[1]_value, 0))", 'count');
                $queries[$countField]->groupBy("$countFields[0].entity_id");
              }
              break;
          }
        }
        if (!empty($queries)) {
          $priceQuery = NULL;
          foreach ($queries as $subQuery) {
            if (is_null($priceQuery)) {
              $priceQuery = $subQuery;
            }
            else {
              $priceQuery->union($subQuery, 'ALL');
            }
          }
          self::$getQuery = $priceQuery;
        }
      }
    }
    return self::$getQuery;
  }

  /**
   * {@inheritdoc}
   */
  public static function getNodeTypesFields() {
    if (!self::$getNodeTypesFields) {
      self::$getNodeTypesFields = [];
      $results = \Drupal::database()->select('basket_node_types', 'n')
        ->fields('n', ['type', 'count_field'])
        ->isNotNull('n.count_field')
        ->execute()->fetchAll();
      if (!empty($results)) {
        foreach ($results as $result) {
          self::$getNodeTypesFields[$result->count_field][$result->type] = $result->type;
        }
      }
    }
    return self::$getNodeTypesFields;
  }

  /**
   * {@inheritdoc}
   */
  public static function viewsJoin(&$view) {
    if (empty($view->query->relationships[$view->field . '_getCountsQuery'])) {
      $subQueryCount = self::getQuery();
      if (!empty($subQueryCount)) {
        // ---
        $subQuery = \Drupal::database()->select('node_field_data', 'n');
        $subQuery->leftJoin($subQueryCount, 'getCountQuery', 'getCountQuery.nid = n.nid');
        $subQuery->addExpression('n.nid', 'nid');
        $subQuery->addExpression("COALESCE(getCountQuery.count, 0)", 'count');
        // ---
        $join = Views::pluginManager('join')->createInstance('standard', [
          'type'          => 'LEFT',
          'table'         => $subQuery,
          'field'         => 'nid',
          'left_table'    => 'node_field_data',
          'left_field'    => 'nid',
          'operator'      => '=',
        ]);
        $rel = $view->query->addRelationship($view->field . '_getCountsQuery', $join, 'node_field_data');
        $view->query->addField($view->field . '_getCountsQuery', 'count', 'basket_node_counts');
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function viewsJoinSort(&$view, $order) {
    self::viewsJoin($view);
    if (!empty($view->query->relationships[$view->field . '_getCountsQuery'])) {
      $view->query->addOrderBy(NULL, $view->field . '_getCountsQuery.count', $order, '_getCountsSort');
    }
  }

}
