<?php

namespace Drupal\eb\Service;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\eb\Entity\EbLogInterface;

/**
 * EbLog manager service.
 *
 * Manages EbLog entities using Drupal's Entity API.
 */
class EbLogManager implements EbLogManagerInterface {

  use DependencySerializationTrait;

  /**
   * Constructs an EbLogManager.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The config factory service.
   * @param \Drupal\Core\Session\AccountInterface $currentUser
   *   The current user.
   */
  public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
    protected TimeInterface $time,
    protected ConfigFactoryInterface $configFactory,
    protected AccountInterface $currentUser,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function log(array $fields): EbLogInterface {
    $storage = $this->entityTypeManager->getStorage('eb_log');

    // Set defaults.
    $fields += [
      'label' => 'Log entry',
      'action' => 'apply',
      'operation_count' => 0,
      'success_count' => 0,
      'failure_count' => 0,
      'status' => 'pending',
      'started' => $this->time->getRequestTime(),
      'uid' => $this->currentUser->id(),
    ];

    /** @var \Drupal\eb\Entity\EbLogInterface $log */
    $log = $storage->create($fields);
    $log->save();

    return $log;
  }

  /**
   * {@inheritdoc}
   */
  public function complete(EbLogInterface $log, string $status, int $successCount, int $failureCount): void {
    $log->setStatus($status);
    $log->setSuccessCount($successCount);
    $log->setFailureCount($failureCount);
    // Use getCurrentTime() instead of getRequestTime() to capture actual
    // completion time, not request start time. This ensures the time window
    // for watchdog queries includes all operations.
    $log->setCompleted($this->time->getCurrentTime());
    $log->save();
  }

  /**
   * {@inheritdoc}
   */
  public function getByDefinitionId(string $definitionId): array {
    $storage = $this->entityTypeManager->getStorage('eb_log');

    $ids = $storage->getQuery()
      ->accessCheck(TRUE)
      ->condition('definition_id', $definitionId)
      ->sort('created', 'DESC')
      ->execute();

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

    /** @var array<int, \Drupal\eb\Entity\EbLogInterface> $entities */
    $entities = $storage->loadMultiple($ids);

    return $entities;
  }

  /**
   * {@inheritdoc}
   */
  public function getById(int $id): ?EbLogInterface {
    $storage = $this->entityTypeManager->getStorage('eb_log');
    $entity = $storage->load($id);

    return $entity instanceof EbLogInterface ? $entity : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function loadLogs(?AccountInterface $account = NULL, array $options = []): array {
    $options += [
      'limit' => 50,
      'status' => NULL,
    ];

    $storage = $this->entityTypeManager->getStorage('eb_log');
    $query = $storage->getQuery()
      ->accessCheck(TRUE)
      ->sort('created', 'DESC');

    if ($account !== NULL) {
      $query->condition('uid', $account->id());
    }

    if ($options['status'] !== NULL) {
      $query->condition('status', $options['status']);
    }

    if ($options['limit'] > 0) {
      $query->range(0, $options['limit']);
    }

    $ids = $query->execute();

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

    /** @var array<int, \Drupal\eb\Entity\EbLogInterface> $entities */
    $entities = $storage->loadMultiple($ids);

    return $entities;
  }

  /**
   * {@inheritdoc}
   */
  public function purge(?int $daysOld = NULL): int {
    if ($daysOld === NULL) {
      $daysOld = $this->configFactory
        ->get('eb.settings')
        ->get('import_history_retention_days') ?? 30;
    }

    $threshold = $this->time->getRequestTime() - ($daysOld * 86400);
    $storage = $this->entityTypeManager->getStorage('eb_log');

    $ids = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('created', $threshold, '<')
      ->execute();

    if (empty($ids)) {
      return 0;
    }

    $entities = $storage->loadMultiple($ids);
    $storage->delete($entities);

    return count($ids);
  }

}
