<?php

namespace App\Services\Fraud;

use App\Models\FraudModuleSetting;
use App\Services\Fraud\Contracts\FraudModuleInterface;
use Illuminate\Support\Facades\File;

class FraudModuleManager
{
    protected array $modules = [];

    /**
     * Discover all available fraud modules
     */
    public function discoverModules(): array
    {
        $modulesPath = app_path('Modules/Fraud');
        $discovered = [];

        if (!File::exists($modulesPath)) {
            return $discovered;
        }

        $directories = File::directories($modulesPath);

        foreach ($directories as $directory) {
            $moduleName = basename($directory);

            // Skip Contracts directory
            if ($moduleName === 'Contracts') {
                continue;
            }

            $moduleJsonPath = $directory . '/module.json';
            $moduleClassPath = $directory . '/' . $moduleName . '.php';

            if (File::exists($moduleJsonPath) && File::exists($moduleClassPath)) {
                $moduleJson = json_decode(File::get($moduleJsonPath), true);
                $className = "App\\Modules\\Fraud\\{$moduleName}\\{$moduleName}";

                if (class_exists($className)) {
                    $instance = new $className();

                    if ($instance instanceof FraudModuleInterface) {
                        $discovered[$moduleJson['slug']] = [
                            'class' => $className,
                            'instance' => $instance,
                            'metadata' => $instance->getMetadata(),
                            'config_fields' => $instance->getConfigFields(),
                        ];
                    }
                }
            }
        }

        $this->modules = $discovered;
        return $discovered;
    }

    /**
     * Get all available fraud modules
     */
    public function getAvailableModules(): array
    {
        if (empty($this->modules)) {
            $this->discoverModules();
        }

        return $this->modules;
    }

    /**
     * Get a specific module instance
     */
    public function getModule(string $slug): ?FraudModuleInterface
    {
        $modules = $this->getAvailableModules();
        return $modules[$slug]['instance'] ?? null;
    }

    /**
     * Get enabled modules from database
     */
    public function getEnabledModules(): array
    {
        $settings = FraudModuleSetting::enabled()->byPriority()->get();
        $modules = [];

        foreach ($settings as $setting) {
            $module = $this->getModule($setting->module_slug);
            if ($module && $module->isEnabled($setting->config ?? [])) {
                $modules[] = [
                    'module' => $module,
                    'setting' => $setting,
                    'config' => $setting->config ?? [],
                ];
            }
        }

        return $modules;
    }

    /**
     * Get or create module setting
     */
    public function getModuleSetting(string $slug): FraudModuleSetting
    {
        return FraudModuleSetting::firstOrCreate(
            ['module_slug' => $slug],
            [
                'enabled' => false,
                'priority' => 0,
                'config' => [],
            ]
        );
    }

    /**
     * Update module configuration
     */
    public function updateModuleConfig(string $slug, array $config, ?bool $enabled = null): FraudModuleSetting
    {
        $setting = $this->getModuleSetting($slug);
        $setting->config = $config;

        if ($enabled !== null) {
            $setting->enabled = $enabled;
        }

        $setting->save();

        return $setting;
    }

    /**
     * Test module connection
     */
    public function testModule(string $slug): array
    {
        $module = $this->getModule($slug);

        if (!$module) {
            return [
                'success' => false,
                'message' => 'Module not found',
            ];
        }

        $setting = $this->getModuleSetting($slug);
        $config = $setting->config ?? [];

        if (!$module->isEnabled($config)) {
            return [
                'success' => false,
                'message' => 'Module is not properly configured',
            ];
        }

        try {
            // Create a test order to check module
            // This is a basic test - in production you might want to use test API endpoints
            $setting->last_tested_at = now();
            $setting->save();

            return [
                'success' => true,
                'message' => 'Module configuration is valid',
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Connection failed: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * Sync module settings with discovered modules
     */
    public function syncModules(): void
    {
        $discovered = $this->discoverModules();

        foreach ($discovered as $slug => $moduleData) {
            $this->getModuleSetting($slug);
        }
    }
}
