<?php

declare(strict_types=1);

namespace Drupal\siteimprove_accessibility\Repository;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelTrait;

/**
 * DailyStatsRepository service to operate with DailyStats entity.
 */
final class DailyStatsRepository {

  use LoggerChannelTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * Time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected TimeInterface $time;

  /**
   * Constructs a new DailyStatsRepository object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The entity type manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) {
    $this->entityTypeManager = $entity_type_manager;
    $this->time = $time;
  }

  /**
   * Creates or updates a DailyStats entity.
   *
   * @param int $timestamp
   *   The timestamp representing the date.
   * @param array $stats
   *   The statistics data.
   *
   * @return bool
   *   TRUE if the operation was successful, FALSE otherwise.
   */
  public function createOrUpdateStats(int $timestamp, array $stats): bool {
    $storage = $this->entityTypeManager->getStorage('si_daily_stats');

    $existingStats = $storage->loadByProperties(['created' => $timestamp]);
    $entity = reset($existingStats) ?: $storage->create([
      'created' => $timestamp,
    ]);

    $entity->set('aggregated_stats', json_encode($stats));

    try {
      $entity->save();
      return TRUE;
    }
    catch (EntityStorageException $e) {
      $this->loggerFactory->error('Failed to save daily stats: @message', ['@message' => $e->getMessage()]);
      return FALSE;
    }
  }

  /**
   * Fetches daily aggregated stats within the given date range.
   *
   * @param int|null $timestamp_from
   *   Time to search from.
   * @param int|null $timestamp_to
   *   Time to search to.
   *
   * @return array
   *   DailyStats data.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function findDailyStats(?int $timestamp_from = NULL, ?int $timestamp_to = NULL): array {
    $storage = $this->entityTypeManager->getStorage('si_daily_stats');

    $date_from = $timestamp_from ?? strtotime('midnight -6 months', $this->time->getRequestTime());
    $date_to = $timestamp_to ?? $this->time->getRequestTime();

    $query = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('created', [$date_from, $date_to], 'BETWEEN')
      ->sort('created', 'ASC');

    $entity_ids = $query->execute();

    if (empty($entity_ids)) {
      return [];
    }

    $stats = [];
    $entities = $storage->loadMultiple($entity_ids);

    foreach ($entities as $entity) {
      $stats[] = [
        'date' => $entity->get('created')->value,
        'aggregated_stats' => json_decode($entity->get('aggregated_stats')->value, TRUE),
      ];
    }

    return $stats;
  }

}
