<?php

namespace classes;

class module_usage_registry
{
    public const DEFAULT_SOFT_LIMIT_PERCENT = 90.0;

    public function all(): array
    {
        return array_map(
            fn(array $descriptor): array => $this->withDefaults($descriptor),
            [
                [
                    'module_key' => 'motorapi',
                    'module_label' => 'MotorAPI',
                    'metric_key' => 'lookup_calls',
                    'metric_label' => 'License plate lookups',
                    'unit' => 'calls',
                    'period' => 'day',
                    'source' => 'internal_counter',
                    'default_enforce_mode' => 'block',
                    'config_module' => 'motorapi',
                    'config_variable' => 'daily_limit',
                    'config_type' => 'int',
                    'legacy_count_table' => 'motorapi_lookups',
                    'primary' => true,
                    'writable_limit' => true,
                ],
                [
                    'module_key' => 'motorapi',
                    'module_label' => 'MotorAPI',
                    'metric_key' => 'provider_usage',
                    'metric_label' => 'Provider usage',
                    'unit' => 'calls',
                    'period' => 'provider',
                    'source' => 'provider_snapshot',
                ],
                [
                    'module_key' => 'fxratesapi',
                    'module_label' => 'FXRatesAPI',
                    'metric_key' => 'rate_fetch_calls',
                    'metric_label' => 'Currency rate fetches',
                    'unit' => 'calls',
                    'period' => 'day',
                    'source' => 'internal_counter',
                    'default_enforce_mode' => 'block',
                    'config_module' => 'fxratesapi',
                    'config_variable' => 'daily_limit',
                    'config_type' => 'int',
                    'legacy_count_table' => 'fxratesapi_conversion_rates',
                    'primary' => true,
                    'writable_limit' => true,
                ],
                [
                    'module_key' => 'virkdata',
                    'module_label' => 'VirkData',
                    'metric_key' => 'company_search_calls',
                    'metric_label' => 'Company searches',
                    'unit' => 'calls',
                    'period' => 'month',
                    'source' => 'internal_counter',
                    'default_enforce_mode' => 'observe',
                    'config_module' => 'virkdata',
                    'config_variable' => 'monthly_limit',
                    'config_type' => 'int',
                    'legacy_log_module' => 'VIRKDATA',
                    'legacy_log_action' => 'VIRKDATA_SEARCH',
                    'primary' => true,
                    'writable_limit' => true,
                ],
                [
                    'module_key' => 'licenseplaterecognizer',
                    'module_label' => 'License Plate Recognizer',
                    'metric_key' => 'plate_recognition_calls',
                    'metric_label' => 'Plate recognition calls',
                    'unit' => 'calls',
                    'period' => 'provider',
                    'source' => 'provider_snapshot',
                    'default_enforce_mode' => 'observe',
                    'primary' => true,
                ],
                [
                    'module_key' => 'email',
                    'module_label' => 'Email',
                    'metric_key' => 'mailersend_messages',
                    'metric_label' => 'MailerSend messages',
                    'unit' => 'messages',
                    'period' => 'provider',
                    'source' => 'provider_snapshot',
                ],
                ['module_key' => 'openai', 'module_label' => 'OpenAI', 'metric_key' => 'api_calls', 'metric_label' => 'API calls', 'unit' => 'calls', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'openai', 'module_label' => 'OpenAI', 'metric_key' => 'total_tokens', 'metric_label' => 'Total tokens', 'unit' => 'tokens', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'weatherapi', 'module_label' => 'WeatherAPI', 'metric_key' => 'requests', 'metric_label' => 'Weather requests', 'unit' => 'calls', 'period' => 'day', 'source' => 'internal_counter'],
                ['module_key' => 'gatewayapi', 'module_label' => 'GatewayAPI', 'metric_key' => 'sms_messages', 'metric_label' => 'SMS messages', 'unit' => 'messages', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'bird', 'module_label' => 'Bird', 'metric_key' => 'messages_and_calls', 'metric_label' => 'Messages and calls', 'unit' => 'events', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'ocrspace', 'module_label' => 'OCRSpace', 'metric_key' => 'ocr_requests', 'metric_label' => 'OCR requests', 'unit' => 'calls', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'limble', 'module_label' => 'Limble', 'metric_key' => 'api_requests', 'metric_label' => 'API requests', 'unit' => 'calls', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'workfeed', 'module_label' => 'Workfeed', 'metric_key' => 'api_requests', 'metric_label' => 'API requests', 'unit' => 'calls', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'stripe', 'module_label' => 'Stripe', 'metric_key' => 'payment_events', 'metric_label' => 'Payment events', 'unit' => 'events', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'coolify', 'module_label' => 'Coolify', 'metric_key' => 'operations', 'metric_label' => 'Operations', 'unit' => 'events', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'backups', 'module_label' => 'Backups', 'metric_key' => 'backup_jobs', 'metric_label' => 'Backup jobs', 'unit' => 'jobs', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'backups', 'module_label' => 'Backups', 'metric_key' => 'stored_bytes', 'metric_label' => 'Stored backup data', 'unit' => 'bytes', 'period' => 'all_time', 'source' => 'derived'],
                ['module_key' => 'selfserve', 'module_label' => 'Self Serve', 'metric_key' => 'wash_sessions', 'metric_label' => 'Wash sessions', 'unit' => 'sessions', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'selfserve', 'module_label' => 'Self Serve', 'metric_key' => 'lane_commands', 'metric_label' => 'Lane commands', 'unit' => 'events', 'period' => 'month', 'source' => 'internal_counter', 'legacy_log_module' => 'SELFSERVE'],
                ['module_key' => 'xlvask', 'module_label' => 'XLVask', 'metric_key' => 'usage_rows', 'metric_label' => 'Usage rows', 'unit' => 'rows', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'attachments', 'module_label' => 'Attachments', 'metric_key' => 'stored_files', 'metric_label' => 'Stored files', 'unit' => 'files', 'period' => 'all_time', 'source' => 'derived'],
                ['module_key' => 'dynamicimages', 'module_label' => 'Dynamic Images', 'metric_key' => 'renders', 'metric_label' => 'Image renders', 'unit' => 'renders', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'html2pdf', 'module_label' => 'HTML2PDF', 'metric_key' => 'pdf_jobs', 'metric_label' => 'PDF jobs', 'unit' => 'jobs', 'period' => 'month', 'source' => 'internal_counter'],
                ['module_key' => 'forms', 'module_label' => 'Forms', 'metric_key' => 'submissions', 'metric_label' => 'Submissions', 'unit' => 'submissions', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'notifications', 'module_label' => 'Notifications', 'metric_key' => 'notification_sends', 'metric_label' => 'Notification sends', 'unit' => 'notifications', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'shelly', 'module_label' => 'Shelly', 'metric_key' => 'relay_commands', 'metric_label' => 'Relay commands', 'unit' => 'commands', 'period' => 'month', 'source' => 'internal_counter', 'legacy_log_module' => 'SHELLY'],
                ['module_key' => 'edgegateway', 'module_label' => 'Edge Gateway', 'metric_key' => 'relay_commands', 'metric_label' => 'Relay commands', 'unit' => 'commands', 'period' => 'month', 'source' => 'derived'],
                ['module_key' => 'system', 'module_label' => 'System', 'metric_key' => 'cron_runs', 'metric_label' => 'Cron runs', 'unit' => 'runs', 'period' => 'day', 'source' => 'derived'],
            ]
        );
    }

    public function find(string $moduleKey, string $metricKey): ?array
    {
        $moduleKey = $this->normalizeModuleKey($moduleKey);
        $metricKey = $this->normalizeMetricKey($metricKey);

        foreach ($this->all() as $descriptor) {
            if ($descriptor['module_key'] === $moduleKey && $descriptor['metric_key'] === $metricKey) {
                return $descriptor;
            }
        }

        return null;
    }

    public function forModule(string $moduleKey): array
    {
        $moduleKey = $this->normalizeModuleKey($moduleKey);
        return array_values(array_filter(
            $this->all(),
            static fn(array $descriptor): bool => $descriptor['module_key'] === $moduleKey
        ));
    }

    public function normalizeModuleKey(string $moduleKey): string
    {
        return strtolower(trim($moduleKey));
    }

    public function normalizeMetricKey(string $metricKey): string
    {
        return strtolower(trim($metricKey));
    }

    private function withDefaults(array $descriptor): array
    {
        $descriptor['module_key'] = $this->normalizeModuleKey((string)$descriptor['module_key']);
        $descriptor['metric_key'] = $this->normalizeMetricKey((string)$descriptor['metric_key']);
        $descriptor['module_label'] = (string)($descriptor['module_label'] ?? $descriptor['module_key']);
        $descriptor['metric_label'] = (string)($descriptor['metric_label'] ?? $descriptor['metric_key']);
        $descriptor['unit'] = (string)($descriptor['unit'] ?? 'count');
        $descriptor['period'] = (string)($descriptor['period'] ?? 'all_time');
        $descriptor['scope_type'] = (string)($descriptor['scope_type'] ?? 'global');
        $descriptor['scope_id'] = (string)($descriptor['scope_id'] ?? '');
        $descriptor['source'] = (string)($descriptor['source'] ?? 'internal_counter');
        $descriptor['default_enforce_mode'] = (string)($descriptor['default_enforce_mode'] ?? 'observe');
        $descriptor['soft_limit_percent'] = (float)($descriptor['soft_limit_percent'] ?? self::DEFAULT_SOFT_LIMIT_PERCENT);
        $descriptor['writable_limit'] = (bool)($descriptor['writable_limit'] ?? false);
        $descriptor['primary'] = (bool)($descriptor['primary'] ?? false);
        return $descriptor;
    }
}
