<?php
/**
 * BookiFlex NotificationLog Extension
 *
 * @package    BookiFlex
 * @subpackage NotificationLog
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Extensions\NotificationLog\Service;

use BookiFlex\Core\Repository\ReservationRepository;
use BookiFlex\Extensions\Notification\Model\Notification;
use BookiFlex\Extensions\Notification\Repository\NotificationRepository;
use BookiFlex\Extensions\NotificationLog\Admin\QueryFilter\NotificationLogQueryFilter;

defined('ABSPATH') || exit;

class NotificationLogService
{
    public function __construct(
        private readonly NotificationRepository $notificationRepository,
        private readonly ReservationRepository $reservationRepository,
    ) {
    }

    /**
     * Return paginated notifications matching the given filter.
     *
     * @return Notification[]
     */
    public function list(NotificationLogQueryFilter $filter): array
    {
        $reservationId = $this->resolveReservationId($filter);

        if ($filter->reservationNumber !== null && $reservationId === null) {
            return [];
        }

        return $this->notificationRepository->findPaginated(
            reservationId: $reservationId,
            status: $filter->status,
            stakeholder: $filter->stakeholder,
            orderBy: $filter->orderBy,
            order: $filter->order,
            limit: $filter->limit,
            offset: $filter->offset,
        );
    }

    /**
     * Return total count of notifications matching the given filter.
     */
    public function count(NotificationLogQueryFilter $filter): int
    {
        $reservationId = $this->resolveReservationId($filter);

        if ($filter->reservationNumber !== null && $reservationId === null) {
            return 0;
        }

        return $this->notificationRepository->countFiltered(
            reservationId: $reservationId,
            status: $filter->status,
            stakeholder: $filter->stakeholder,
        );
    }

    /**
     * Look up reservation ID by number when the filter contains a reservation number.
     * Returns null if the filter has no reservation number or if no reservation is found.
     */
    private function resolveReservationId(NotificationLogQueryFilter $filter): ?int
    {
        if ($filter->reservationNumber === null) {
            return null;
        }

        $reservation = $this->reservationRepository->findOne(['number' => $filter->reservationNumber]);

        return $reservation?->getId();
    }
}
