<?php
namespace ShopyPress\Jobs;
if ( ! defined( 'ABSPATH' ) ) exit;

use ShopyPress\Services\ProductSyncService;

class SyncProducts {
    private $lockFile = null;
    private $lockHandle = null;

    /**
     * Run the product sync job
     */
    public function run(): void {
        // Try to acquire lock
        if (!$this->acquireLock()) {
            // Another process is running, exit gracefully
            return;
        }

        // Register shutdown function to ensure lock is always released
        register_shutdown_function([$this, 'releaseLock']);

        try {
            $service = new ProductSyncService();
            $result = $service->startOrResumeSync();

            if (!$result['success']) {
                // Error already tracked in state
            }
        } finally {
            // Always release the lock when done
            $this->releaseLock();
        }
    }

    /**
     * Acquire file-based lock to prevent concurrent execution
     *
     * @return bool True if lock acquired, false otherwise
     */
    private function acquireLock(): bool {
        $this->lockFile = get_temp_dir() . 'shopypress_sync_products.lock';

        // Open/create lock file
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- fopen required for flock() which has no WP_Filesystem equivalent
        $this->lockHandle = fopen($this->lockFile, 'c');

        if ($this->lockHandle === false) {
            return false;
        }

        // Try to acquire exclusive, non-blocking lock
        // LOCK_EX = exclusive lock
        // LOCK_NB = non-blocking (returns immediately if lock can't be acquired)
        if (!flock($this->lockHandle, LOCK_EX | LOCK_NB)) {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- fclose required for fopen handle
            fclose($this->lockHandle);
            $this->lockHandle = null;
            return false;
        }

        return true;
    }

    /**
     * Release the file lock
     */
    public function releaseLock(): void {
        if ($this->lockHandle !== null) {
            flock($this->lockHandle, LOCK_UN);
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- fclose required for fopen handle
            fclose($this->lockHandle);
            $this->lockHandle = null;
        }

        if ($this->lockFile !== null && file_exists($this->lockFile)) {
            wp_delete_file($this->lockFile);
        }
    }
}
