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

declare(strict_types=1);

namespace BookiFlex\Extensions\BackgroundJobs\Service;

use ActionScheduler_Store;
use BookiFlex\Core\Infrastructure\Storage\CacheRepositoryInterface;
use BookiFlex\Extensions\BackgroundJobs\Contract\HealthStatus;

defined( 'ABSPATH' ) || exit;

/**
 * Health Checker Service
 *
 * Monitors ActionScheduler queue health and provides status information.
 */
class HealthChecker
{
    private const TRANSIENT_LAST_RUN = 'bflex_bgj_last_run';
    private const THRESHOLD_WARNING_SECONDS = 600;  // 10 minutes
    private const THRESHOLD_DELAYED_SECONDS = 1800; // 30 minutes

    public function __construct(
        private readonly CacheRepositoryInterface $cache
    ) {
    }

    /**
     * Record that the queue ran successfully
     */
    public function recordRun(): void
    {
        $this->cache->set(self::TRANSIENT_LAST_RUN, time(), DAY_IN_SECONDS);
    }

    /**
     * Get the timestamp of the last queue run
     *
     * @return int|null Unix timestamp or null if never run
     */
    public function getLastRunTime(): ?int
    {
        $lastRun = $this->cache->get(self::TRANSIENT_LAST_RUN);

        // Accept both int and numeric string (WordPress transients return strings)
        if (is_numeric($lastRun)) {
            return (int) $lastRun;
        }

        return null;
    }

    /**
     * Get time elapsed since last run
     *
     * @return int|null Seconds since last run, or null if never run
     */
    public function getTimeSinceLastRun(): ?int
    {
        $lastRun = $this->getLastRunTime();
        return $lastRun !== null ? (time() - $lastRun) : null;
    }

    /**
     * Get count of pending jobs in ActionScheduler
     *
     * @return int Number of pending jobs
     */
    public function getPendingJobsCount(): int
    {
        if (!function_exists('as_get_scheduled_actions')) {
            return 0;
        }

	    $actions = as_get_scheduled_actions([
		    'group' => 'bookiflex',
		    'status' => ActionScheduler_Store::STATUS_PENDING,
		    'per_page' => -1,
	    ], 'ids');

        return count($actions);
    }

    /**
     * Calculate and return current health status
     *
     * @return HealthStatus Current health status
     */
    public function getHealthStatus(): HealthStatus
    {
        $timeSinceLast = $this->getTimeSinceLastRun();
        $pendingCount = $this->getPendingJobsCount();

        // Determine status based on user requirements
        if ($pendingCount === 0) {
            // No pending jobs = always OK
            $status = HealthStatus::STATUS_OK;
        } elseif ($timeSinceLast === null) {
            // Never run but has pending jobs
            $status = HealthStatus::STATUS_DELAYED;
        } elseif ($timeSinceLast > self::THRESHOLD_DELAYED_SECONDS) {
            // pending > 0 && last_run > 30 min
            $status = HealthStatus::STATUS_DELAYED;
        } elseif ($timeSinceLast > self::THRESHOLD_WARNING_SECONDS) {
            // pending > 0 && last_run 10-30 min
            $status = HealthStatus::STATUS_WARNING;
        } else {
            // pending > 0 && last_run < 10 min
            $status = HealthStatus::STATUS_OK;
        }

        return new HealthStatus(
            status: $status,
            lastRunTime: $this->getLastRunTime(),
            pendingJobsCount: $pendingCount,
            timeSinceLastRun: $timeSinceLast
        );
    }
}
