<?php
 namespace App\Core\Currency; use App\Core\Module\ConfigFieldNormalizer; use App\Core\Module\ManageableModuleManager; use App\Core\Module\TestResult; use App\Models\Setting; class CurrencyDriverManager implements ManageableModuleManager { protected array $drivers = []; public function __construct() { $this->loadDrivers(); } private function loadDrivers(): void { $this->drivers = [ 'open_er_api' => \App\Modules\CurrencyDriver\OpenErApi\OpenErApi::class, 'ecb' => \App\Modules\CurrencyDriver\Ecb\Ecb::class, 'fixer' => \App\Modules\CurrencyDriver\Fixer\Fixer::class, 'open_exchange_rates' => \App\Modules\CurrencyDriver\OpenExchangeRates\OpenExchangeRates::class, ]; } public function getAvailableDrivers(): array { $out = []; foreach ($this->drivers as $key => $class) { try { $instance = new $class([]); $out[$key] = [ 'name' => $instance->getName(), 'label' => $instance->getLabel(), 'requires_api_key' => $instance->requiresApiKey(), ]; } catch (\Throwable $e) { } } return $out; } public function driver(string $name, ?array $config = null): CurrencyDriverInterface { if (! isset($this->drivers[$name])) { throw new \InvalidArgumentException("Unknown currency driver: {$name}"); } $class = $this->drivers[$name]; if ($config === null) { $config = $this->configFor($name); } return new $class($config); } protected function configFor(string $name): array { return \App\Helpers\ModuleConfig::resolved('currency', $name, $this->getConfigFields($name)); } public function failoverOrder(): array { $raw = (string) Setting::getValue('fx_provider_failover_order', 'ecb,open_er_api,open_exchange_rates,fixer'); $list = array_values(array_filter(array_map('trim', explode(',', $raw)))); return array_values(array_intersect($list, array_keys($this->drivers))); } public function discover(): array { $out = []; foreach ($this->drivers as $name => $class) { try { $instance = new $class([]); $out[] = [ 'name' => $name, 'label' => method_exists($instance, 'getLabel') ? $instance->getLabel() : strtoupper($name), ]; } catch (\Throwable $e) { } } return $out; } public function getConfigFields(string $name): array { if (! isset($this->drivers[$name])) { return []; } try { $instance = new $this->drivers[$name]([]); $legacy = method_exists($instance, 'getConfigFields') ? $instance->getConfigFields() : []; } catch (\Throwable $e) { return []; } return ConfigFieldNormalizer::normalize(is_array($legacy) ? $legacy : []); } public function test(string $name, array $config): TestResult { if (! isset($this->drivers[$name])) { return TestResult::failure("Unknown driver: {$name}"); } try { $driver = new $this->drivers[$name]($config); $base = (string) ($config['base_currency'] ?? Setting::getValue('default_currency_code', 'USD')); $rates = $driver->fetch(strtoupper($base)); if (empty($rates)) { return TestResult::failure('Driver returned no rates.'); } return TestResult::success(sprintf('OK — %d rates fetched (base %s).', count($rates), $base)); } catch (\Throwable $e) { return TestResult::failure($e->getMessage()); } } } 