<?php
namespace boru\ai\Config;

class ConfigResolver
{
    /** @var Config|null */
    protected $config;

    public function __construct(Config $config = null)
    {
        $this->config = $config;
    }

    public function config(Config $config = null)
    {
        if ($config !== null) {
            $this->config = $config;
            return $this;
        }
        return $this->config;
    }

    public function resolveProviderSetting($provider, $key, $providerDefault = null, $globalPath = 'runtime', $envPrefix = 'AI')
    {
        $value = $providerDefault;
        $config = $this->config();

        if ($config instanceof Config) {
            $globalValue = $config->get($globalPath . '.' . $key, '__boru_ai_missing__');
            if ($globalValue !== '__boru_ai_missing__') {
                $value = $globalValue;
            }

            $providerValue = $config->get('providers.' . $provider . '.' . $key, '__boru_ai_missing__');
            if ($providerValue !== '__boru_ai_missing__') {
                $value = $providerValue;
            }
        }

        $globalEnv = Env::get($this->toEnvName($envPrefix, $key), '__boru_ai_missing__');
        if ($globalEnv !== '__boru_ai_missing__') {
            $value = $this->castEnvValue($globalEnv, $value);
        }

        $providerEnv = Env::get($this->toEnvName(strtoupper((string)$provider), $key), '__boru_ai_missing__');
        if ($providerEnv !== '__boru_ai_missing__') {
            $value = $this->castEnvValue($providerEnv, $value);
        }

        return $value;
    }

    protected function toEnvName($prefix, $key)
    {
        $normalized = strtoupper((string)$key);
        $normalized = str_replace(array('.', '-', ' '), '_', $normalized);
        return strtoupper((string)$prefix) . '_' . $normalized;
    }

    protected function castEnvValue($value, $currentValue = null)
    {
        $string = is_string($value) ? trim($value) : $value;

        if ($currentValue === true || $currentValue === false) {
            if (is_string($string)) {
                $lower = strtolower($string);
                if (in_array($lower, array('1', 'true', 'yes', 'on'), true)) {
                    return true;
                }
                if (in_array($lower, array('0', 'false', 'no', 'off'), true)) {
                    return false;
                }
            }
            return (bool)$value;
        }

        if (is_int($currentValue)) {
            return (int)$value;
        }

        if (is_float($currentValue)) {
            return (float)$value;
        }

        return $value;
    }
}
