<?php

namespace Drupal\visitors\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\visitors\VisitorsDateRangeInterface;
use Drupal\visitors\VisitorsReportInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Report data.
 *
 * @package visitors
 */
class ReportService implements VisitorsReportInterface {
  use StringTranslationTrait;

  /**
   * The database service.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * Items per page.
   *
   * @var int
   */
  protected $itemsPerPage;

  /**
   * The page number.
   *
   * @var int
   */
  protected $page;

  /**
   * The date range service.
   *
   * @var \Drupal\visitors\VisitorsDateRangeInterface
   */
  protected $dateRange;

  /**
   * Database Service Object.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   The database service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $stack
   *   The request stack service.
   * @param \Drupal\visitors\VisitorsDateRangeInterface $date_range
   *   The date range service.
   */
  public function __construct(
    Connection $database,
    ConfigFactoryInterface $config_factory,
    RequestStack $stack,
    VisitorsDateRangeInterface $date_range,
  ) {

    $this->database = $database;
    $this->itemsPerPage = $config_factory->get('visitors.settings')->get('items_per_page') ?? 10;
    $this->page = $stack->getCurrentRequest()->query->get('page') ?? 0;
    $this->dateRange = $date_range;
  }

  /**
   * {@inheritdoc}
   */
  public function referer(array $header) {
    /** @var \Drupal\Core\Database\Query\SelectInterface $query */
    $query = $this->database->select('visitors_event', 'v')
      ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
      ->extend('Drupal\Core\Database\Query\TableSortExtender');
    // $query->condition('bot', 1, '<>');
    $query->addExpression('COUNT(*)', 'count');
    $query->fields('v', ['referrer_url']);
    $this->addDateFilter($query);
    $query = $this->setReferrersCondition($query);
    $query->condition('referrer_url', '', '<>');
    $query->groupBy('referrer_url');
    $query->orderByHeader($header);
    $query->limit($this->itemsPerPage);

    $count_query = $this->database->select('visitors_event', 'v');
    // $count_query->condition('bot', 1, '<>');
    $count_query->condition('referrer_url', '', '<>');
    $count_query->addExpression('COUNT(DISTINCT referrer_url)');
    $this->addDateFilter($count_query);
    $count_query = $this->setReferrersCondition($count_query);
    $query->setCountQuery($count_query);
    $results = $query->execute();

    $rows = [];
    $i = $this->page * $this->itemsPerPage;
    foreach ($results as $data) {

      $rows[] = [
        empty($data->referrer_url) ? $this->t('No Referer') : $data->referrer_url,
        $data->count,
      ];
    }
    return $rows;
  }

  /**
   * Build sql query from referer type value.
   */
  protected function setReferrersCondition($query) {
    switch ($_SESSION['referer_type']) {
      case VisitorsReportInterface::REFERER_TYPE_INTERNAL_PAGES:
        $query->condition(
          'referrer_url',
          sprintf('%%%s%%', $_SERVER['HTTP_HOST']),
          'LIKE'
        );
        $query->condition('referrer_url', '', '<>');
        break;

      case VisitorsReportInterface::REFERER_TYPE_EXTERNAL_PAGES:
        $query->condition(
          'referrer_url',
          sprintf('%%%s%%', $_SERVER['HTTP_HOST']),
          'NOT LIKE'
        );
        break;

      default:
        break;
    }

    return $query;
  }

  /**
   * Add date filter to the query.
   *
   * @param \Drupal\Core\Database\Query\SelectInterface $query
   *   The query object.
   */
  protected function addDateFilter(&$query) {

    $from = $this->dateRange->getStartTimestamp();
    $to   = $this->dateRange->getEndTimestamp();

    $query->condition('created', [$from, $to], 'BETWEEN');
  }

}
