<?php

namespace MintyPHP\Service\Scheduler;

use MintyPHP\Service\Audit\SystemAuditService;
use MintyPHP\Service\Scheduler\Handler\ScheduledJobHandlerInterface;
use MintyPHP\Service\Scheduler\Handler\SystemAuditPurgeJobHandler;
use MintyPHP\Service\Scheduler\Handler\UserLifecycleJobHandler;
use MintyPHP\Service\User\UserLifecycleService;

class ScheduledJobRegistry
{
    public const USER_LIFECYCLE_RUN = 'user_lifecycle_run';
    public const SYSTEM_AUDIT_PURGE = 'system_audit_purge';

    /**
     * Maps job_key => handler instance (must implement ScheduledJobHandlerInterface).
     *
     * To register a new job:
     *   1. Create lib/Service/Scheduler/Handler/YourJobHandler.php implementing the interface.
     *   2. Add a public const for the job key above.
     *   3. Add one line in __construct(): self::YOUR_JOB_KEY => new YourJobHandler(...),
     *
     * No other file needs to be changed.
     *
     * @var array<string, ScheduledJobHandlerInterface>
     */
    private array $handlers;

    public function __construct(
        UserLifecycleService $userLifecycleService,
        SystemAuditService $systemAuditService
    ) {
        $this->handlers = [
            self::USER_LIFECYCLE_RUN => new UserLifecycleJobHandler($userLifecycleService),
            self::SYSTEM_AUDIT_PURGE => new SystemAuditPurgeJobHandler($systemAuditService),
        ];
    }

    /**
     * Returns all job definitions keyed by job_key.
     * Consumed by ScheduledJobService->ensureSystemJobs() to sync registry with the database.
     */
    public function definitions(): array
    {
        $result = [];
        foreach ($this->handlers as $jobKey => $handler) {
            $result[$jobKey] = $handler->definition();
        }
        return $result;
    }

    /**
     * Returns the definition for a single job key, or null if not registered.
     */
    public function get(string $jobKey): ?array
    {
        $jobKey = trim($jobKey);
        if ($jobKey === '') {
            return null;
        }
        return isset($this->handlers[$jobKey]) ? $this->handlers[$jobKey]->definition() : null;
    }

    /**
     * Dispatches execution to the registered handler for the given job key and returns
     * a normalized result envelope. Unknown job keys return status 'failed' with
     * error_code 'job_not_supported' rather than throwing an exception.
     *
     * @param string   $jobKey      Registered job identifier (see class constants).
     * @param int|null $actorUserId Null for scheduler-triggered runs; user ID for manual runs.
     * @return array{status:string,error_code:?string,error_message:?string,result:array}
     */
    public function execute(string $jobKey, ?int $actorUserId): array
    {
        if (!isset($this->handlers[$jobKey])) {
            return [
                'status'        => 'failed',
                'error_code'    => 'job_not_supported',
                'error_message' => null,
                'result'        => [],
            ];
        }
        return $this->handlers[$jobKey]->execute($actorUserId);
    }
}
