<?php

namespace classes;

use InvalidArgumentException;

class cron_task_definition
{
    public string $id;
    public string $name;
    public string $description;
    public string $module;
    public string $handler;
    public array $schedule;
    public bool $enabled;
    public int $timeout_seconds;
    public int $estimated_duration_ms;
    public int $priority;
    public ?string $legacy_name;

    public function __construct(array $definition)
    {
        $this->id = self::requiredString($definition, 'id');
        $this->name = self::requiredString($definition, 'name');
        $this->description = (string)($definition['description'] ?? '');
        $this->module = self::requiredString($definition, 'module');
        $this->handler = self::requiredString($definition, 'handler');
        $this->schedule = cron_schedule::normalize($definition['schedule'] ?? []);
        $this->enabled = (bool)($definition['enabled'] ?? true);
        $this->timeout_seconds = max(30, (int)($definition['timeout_seconds'] ?? 600));
        $this->estimated_duration_ms = max(0, (int)($definition['estimated_duration_ms'] ?? 0));
        $this->priority = (int)($definition['priority'] ?? 100);
        $legacy_name = trim((string)($definition['legacy_name'] ?? ''));
        $this->legacy_name = $legacy_name !== '' ? $legacy_name : null;

        if (!preg_match('/^[a-z0-9][a-z0-9_.-]{1,190}$/', $this->id)) {
            throw new InvalidArgumentException('Invalid cron task id: ' . $this->id);
        }
        if (!preg_match('/^[a-z0-9][a-z0-9_-]{1,63}$/', $this->module)) {
            throw new InvalidArgumentException('Invalid cron task module: ' . $this->module);
        }
    }

    public function asArray(?array $state = null, ?int $estimatedDurationMs = null): array
    {
        $schedule = is_array($state['schedule'] ?? null) && ($state['schedule'] ?? []) !== []
            ? $state['schedule']
            : $this->schedule;
        $enabled = array_key_exists('enabled', $state ?? [])
            ? (bool)$state['enabled']
            : $this->enabled;

        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'module' => $this->module,
            'handler' => $this->handler,
            'schedule' => $schedule,
            'default_schedule' => $this->schedule,
            'enabled' => $enabled,
            'default_enabled' => $this->enabled,
            'timeout_seconds' => $this->timeout_seconds,
            'estimated_duration_ms' => $estimatedDurationMs ?? $this->estimated_duration_ms,
            'priority' => $this->priority,
            'legacy_name' => $this->legacy_name,
            'last_run_at' => $state['last_run_at'] ?? null,
            'next_run_at' => $state['next_run_at'] ?? null,
            'locked_until' => $state['locked_until'] ?? null,
            'lock_owner' => $state['lock_owner'] ?? null,
            'current_run_id' => $state['current_run_id'] ?? null,
            'last_status' => $state['last_status'] ?? null,
            'last_error' => $state['last_error'] ?? null,
        ];
    }

    private static function requiredString(array $definition, string $key): string
    {
        $value = trim((string)($definition[$key] ?? ''));
        if ($value === '') {
            throw new InvalidArgumentException('Missing cron task definition field: ' . $key);
        }
        return $value;
    }
}
