<?php

declare(strict_types=1);

namespace app\common\service;

use think\Config;
use think\Db;

/**
 * 工单云控同步相关系统配置读取
 */
class SplitSyncConfigService
{
    private const DEFAULT_NODE_HOST = 'http://127.0.0.1:3001';

    /**
     * Node Headless 服务根地址
     */
    public static function getNodeHost(): string
    {
        $value = self::getConfigValue('split_scrm_node_host');
        $value = trim($value);
        return $value !== '' ? rtrim($value, '/') : self::DEFAULT_NODE_HOST;
    }

    /**
     * 连续同步失败多少次后自动暂停工单（0 表示不因失败暂停）
     */
    public static function getFailPauseThreshold(): int
    {
        $value = self::getConfigValue('split_sync_fail_pause_threshold');
        if ($value === '') {
            return 5;
        }
        return max(0, (int) $value);
    }

    /**
     * 指定工单类型的自动同步周期（分钟），0 表示不自动同步
     */
    public static function getIntervalMinutes(string $ticketType): int
    {
        $ticketType = trim($ticketType);
        if ($ticketType === '') {
            return 0;
        }
        $key = 'split_sync_interval_' . $ticketType;
        $value = self::getConfigValue($key);
        return max(0, (int) $value);
    }

    /**
     * 单次 cron 最多处理几条到期工单，避免一分钟内打满 Node Browser 槽位
     */
    public static function getMaxTicketsPerCronRun(): int
    {
        $value = self::getConfigValue('split_sync_max_per_cron');
        if ($value === '') {
            return 5;
        }
        return max(1, min(50, (int) $value));
    }

    /**
     * Node 通道候选池倍数（候选数 = maxPerRun × 本值）
     */
    public static function getNodeCandidatePoolMultiplier(): int
    {
        $value = self::getConfigValue('split_sync_node_candidate_multiplier');
        if ($value === '') {
            return 10;
        }
        return max(3, min(50, (int) $value));
    }

    /**
     * 全局 cron 锁过期秒数，防止异常退出后永久占锁
     */
    public static function getCronLockTtlSeconds(): int
    {
        $value = self::getConfigValue('split_sync_cron_lock_ttl');
        if ($value === '') {
            return 1800;
        }
        return max(300, (int) $value);
    }

    /**
     * Node 排队数达到该阈值时，本轮 cron 不再提交新任务
     */
    public static function getNodeQueueSkipThreshold(): int
    {
        $value = self::getConfigValue('split_sync_node_queue_threshold');
        if ($value === '') {
            return 2;
        }
        return max(0, (int) $value);
    }

    /**
     * 后台投递 / Cron 使用的 PHP CLI 可执行文件路径
     *
     * Web(FPM) 环境下 PHP_BINARY 指向 php-fpm，不能用于 think 命令。
     */
    public static function getCliPhpBinary(): string
    {
        $configured = trim(self::getConfigValue('split_sync_cli_php'));
        if ($configured !== '' && self::isUsableCliPhp($configured)) {
            return $configured;
        }

        if (defined('PHP_BINDIR') && PHP_BINDIR !== '') {
            $candidate = rtrim(PHP_BINDIR, '/\\') . DIRECTORY_SEPARATOR . 'php';
            if (self::isUsableCliPhp($candidate)) {
                return $candidate;
            }
        }

        if (PHP_SAPI === 'cli' && defined('PHP_BINARY') && PHP_BINARY !== '' && self::isUsableCliPhp(PHP_BINARY)) {
            return PHP_BINARY;
        }

        foreach (['/usr/bin/php', '/usr/local/bin/php'] as $candidate) {
            if (self::isUsableCliPhp($candidate)) {
                return $candidate;
            }
        }

        return 'php';
    }

    /**
     * 判断路径是否为可用的 PHP CLI（排除 php-fpm）
     */
    private static function isUsableCliPhp(string $path): bool
    {
        if (stripos($path, 'fpm') !== false) {
            return false;
        }
        if ($path === 'php') {
            return true;
        }

        return is_file($path) && is_executable($path);
    }

    private static function getConfigValue(string $name): string
    {
        $site = Config::get('site.' . $name);
        if ($site !== null && $site !== '') {
            return (string) $site;
        }
        $db = Db::name('config')->where('name', $name)->value('value');
        return $db !== null ? (string) $db : '';
    }
}
