<?php

namespace AC_SYNC\Includes\Classes\Async;

if (!defined('ABSPATH')) exit;

use AC_SYNC\Includes\Classes\Logger\Action_Wear_Log as Log;
use AC_SYNC\Includes\Classes\Differential\Entities\Action_Wear_Price as DiffPrice;
use AC_SYNC\Includes\Classes\Differential\Entities\Action_Wear_Quantity as DiffQuantity;
use AC_SYNC\Includes\Classes\Differential\Entities\Action_Wear_Product_Differential as DiffCatalog;

class Action_Wear_Job_Scheduler
{
    /**
     * Recurring job definitions: type => [priority, conflict_group, update_timing_seconds]
     */
    private static $recurringJobs = [
        'diff_price'    => ['priority' => 50, 'conflict_group' => 'price_sync',    'timing_class' => DiffPrice::class],
        'diff_quantity' => ['priority' => 60, 'conflict_group' => 'quantity_sync', 'timing_class' => DiffQuantity::class],
        'diff_catalog'  => ['priority' => 70, 'conflict_group' => 'catalog_sync',  'timing_class' => DiffCatalog::class],
        'sku_cleanup'   => ['priority' => 90, 'conflict_group' => null, 'timing_seconds' => 21600],
    ];

    /**
     * Ensure all recurring jobs have at least one pending/claimed instance.
     * Called on plugins_loaded (idempotent) and as weekly safety net.
     */
    public static function ensureRecurringJobs(): void
    {
        foreach (self::$recurringJobs as $jobType => $config) {
            if (Action_Wear_Job_Queue::hasPending($jobType)) {
                continue;
            }

            // Calculate next available_at
            if (isset($config['timing_class'])) {
                $timingClass = $config['timing_class'];
                $entity = new $timingClass();
                $lastExecution = $entity->getExecutionTime();
                $updateTiming = $entity->getUpdateTiming();
            } else {
                $lastExecution = 0;
                $updateTiming = $config['timing_seconds'];
            }

            $nextRun = $lastExecution + $updateTiming;
            $now = time();

            if ($lastExecution === 0 || $lastExecution === null) {
                // First install or after purge — schedule with full delay
                $availableAt = gmdate('Y-m-d H:i:s', $now + $updateTiming);
            } elseif ($nextRun <= $now) {
                $availableAt = gmdate('Y-m-d H:i:s', $now);
            } else {
                $availableAt = gmdate('Y-m-d H:i:s', $nextRun);
            }

            Action_Wear_Job_Queue::push(
                $jobType,
                null,
                $config['priority'],
                $availableAt,
                $config['conflict_group'],
                5
            );

            Log::write("JobScheduler: Seeded recurring job '{$jobType}' available at {$availableAt}", Log::INFO, Log::CONTEXT_CRONJOB);
        }
    }
}
