<?php
namespace EasyChat\Library\Queue;

 
class SchedulerHealthService {
    private $db;
    private $prefix;

    public function __construct($registry) {
        $this->db = $registry->get('db');
        $this->prefix = function_exists('easychat_db_prefix') ? (string)easychat_db_prefix() : '';
    }

    public function started(string $runner): string {
        $run_id = bin2hex(random_bytes(8));
        $this->write(array(
            'chat_scheduler_last_started_at' => date('c'),
            'chat_scheduler_last_runner' => $this->normalizeRunner($runner),
            'chat_scheduler_last_run_id' => $run_id,
        ));
        return $run_id;
    }

    public function succeeded(string $run_id, array $result): void {
        $this->write(array(
            'chat_scheduler_last_ok_at' => date('c'),
            'chat_scheduler_last_ok_run_id' => $run_id,
            'chat_scheduler_last_duration_ms' => (string)max(0, (int)round(((float)($result['elapsed'] ?? 0)) * 1000)),
            'chat_scheduler_last_processed' => (string)max(0, (int)($result['processed'] ?? 0)),
            'chat_scheduler_last_error_code' => '',
        ));
    }

    public function failed(string $run_id, \Throwable $error): void {
        $code = $error instanceof \PDOException ? 'database_error' : 'worker_error';
        $this->write(array(
            'chat_scheduler_last_error_at' => date('c'),
            'chat_scheduler_last_error_run_id' => $run_id,
            'chat_scheduler_last_error_code' => $code,
        ));
    }

    public static function state(array $settings): array {
        $last_ok = self::timestamp($settings['chat_scheduler_last_ok_at'] ?? '');
        $last_error = self::timestamp($settings['chat_scheduler_last_error_at'] ?? '');
        $age = $last_ok > 0 ? time() - $last_ok : null;
        $status = $last_ok === 0 ? 'waiting' : (($age !== null && $age <= 180) ? 'healthy' : 'stale');
        if ($last_error > $last_ok) {
            $status = 'error';
        }
        return array(
            'status' => $status,
            'last_ok_at' => $last_ok > 0 ? date('c', $last_ok) : '',
            'age_seconds' => $age,
            'runner' => (string)($settings['chat_scheduler_last_runner'] ?? ''),
            'error_code' => (string)($settings['chat_scheduler_last_error_code'] ?? ''),
        );
    }

    private function normalizeRunner(string $runner): string {
        $runner = strtolower(trim($runner));
        return in_array($runner, array('standalone', 'wordpress_org', 'opencart_cron', 'bitrix_agent', 'webasyst_cli'), true)
            ? $runner
            : 'standalone';
    }

    private function write(array $values): void {
        if (!$this->db || $this->prefix === '' || !preg_match('/^[A-Za-z0-9_]+$/', $this->prefix)) {
            throw new \RuntimeException('scheduler_health_storage_unavailable');
        }
        $rows = array();
        foreach ($values as $key => $value) {
            $rows[] = "('" . $this->db->escape((string)$key) . "','" . $this->db->escape((string)$value) . "')";
        }
        $this->db->query(
            "INSERT INTO `{$this->prefix}settings` (`key`,`value`) VALUES " . implode(',', $rows)
            . ' ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)'
        );
    }

    private static function timestamp($value): int {
        $value = trim((string)$value);
        $timestamp = $value !== '' ? strtotime($value) : false;
        return $timestamp === false ? 0 : (int)$timestamp;
    }
}
