#!/usr/bin/env php
<?php

declare(strict_types=1);

use Ecobalt\Project\Worker\LegacyTaskRunner;
use Ecobalt\Project\Worker\WorkerException;
use Ecobalt\Project\Worker\WorkerRegistry;

require dirname(__DIR__) . '/vendor/autoload.php';

$root = dirname(__DIR__);
$options = getopt('', [
    'help',
    'task:',
    'once',
    'list',
    'list-instances',
    'only:',
    'format:',
    'validate-config',
]);

$help = static function (): void {
    $text = <<<TXT
Rest1C Worker entrypoint

Использование:
  php bin/worker --task=<name> [--once]
  php bin/worker --list [--format=plain|json]
  php bin/worker --list-instances [--only=task1,task2]
  php bin/worker --validate-config

TXT;
    fwrite(STDOUT, $text);
};

try {
    $registry = new WorkerRegistry($root);
    $defaults = $registry->getDefaults();
    $phpBinary = (string)($defaults['php_binary'] ?? PHP_BINARY);

    if (isset($options['help'])) {
        $help();
        exit(0);
    }

    if (isset($options['validate-config'])) {
        $tasks = $registry->getTasks(false);
        fwrite(STDOUT, sprintf("OK: валидировано задач: %d\n", count($tasks)));
        exit(0);
    }

    $only = [];
    if (isset($options['only'])) {
        $parts = array_filter(array_map('trim', explode(',', (string)$options['only'])));
        foreach ($parts as $part) {
            $only[$part] = true;
        }
    }

    $filterTasks = static function (array $tasks, array $only): array {
        if ($only === []) {
            return $tasks;
        }

        return array_filter(
            $tasks,
            static fn ($task, string $name): bool => isset($only[$name]),
            ARRAY_FILTER_USE_BOTH
        );
    };

    if (isset($options['list']) || isset($options['list-instances'])) {
        $tasks = $filterTasks($registry->getTasks(true), $only);
        $format = strtolower((string)($options['format'] ?? 'plain'));

        if (isset($options['list-instances'])) {
            $instances = [];
            foreach ($tasks as $task) {
                foreach ($task->buildInstances() as $instance) {
                    $instances[] = [
                        'task' => $task->name,
                        'instance' => $instance,
                        'mode' => $task->mode,
                    ];
                }
            }

            if ($format === 'json') {
                fwrite(STDOUT, json_encode($instances, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . PHP_EOL);
                exit(0);
            }

            foreach ($instances as $instance) {
                fwrite(STDOUT, $instance['instance'] . PHP_EOL);
            }
            exit(0);
        }

        if ($format === 'json') {
            $payload = [];
            foreach ($tasks as $task) {
                $payload[] = [
                    'name' => $task->name,
                    'description' => $task->description,
                    'mode' => $task->mode,
                    'concurrency' => $task->concurrency,
                    'prefetch' => $task->prefetch,
                    'retry_profile' => $task->retryProfile,
                ];
            }

            fwrite(STDOUT, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . PHP_EOL);
            exit(0);
        }

        foreach ($tasks as $task) {
            fwrite(STDOUT, implode("\t", [
                $task->name,
                $task->mode,
                'concurrency=' . $task->concurrency,
                'prefetch=' . $task->prefetch,
                'retry=' . $task->retryProfile,
            ]) . PHP_EOL);
        }

        exit(0);
    }

    $taskNameRaw = (string)($options['task'] ?? '');
    if ($taskNameRaw === '') {
        $help();
        throw new WorkerException('Не указан параметр --task.');
    }

    $taskName = $taskNameRaw;
    if (preg_match('/^(.+)--([1-9][0-9]*)$/', $taskNameRaw, $m)) {
        $taskName = $m[1];
    }

    $task = $registry->getTask($taskName);
    if (!$task->enabled) {
        throw new WorkerException('Задача выключена в config/workers.php: ' . $taskName);
    }

    $runner = new LegacyTaskRunner($root, $phpBinary);
    $exitCode = $runner->run($task, isset($options['once']));
    exit($exitCode);
} catch (WorkerException $e) {
    fwrite(STDERR, '[worker] ' . $e->getMessage() . PHP_EOL);
    exit(2);
} catch (Throwable $e) {
    fwrite(STDERR, '[worker] Непредвиденная ошибка: ' . $e->getMessage() . PHP_EOL);
    exit(3);
}
