<?php

namespace Drupal\basket\Query;

use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\views\Views;

class BasketGetNodeCountsQuery{

    protected static $getQuery;
    protected static $getNodeTypesFields;

    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($countFields[1].$countFields[1]_value)", '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;
    }
    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;
    }
    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');
            }
        }
    }
    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');
        }
    }
}