<?php

declare(strict_types=1);

use App\Framework\Core\ValueObjects\Version;
use App\Framework\Database\NPlusOneDetection\MachineLearning\NPlusOneModelAdapter;
use App\Framework\MachineLearning\ModelManagement\ModelRegistry;
use App\Framework\Queue\MachineLearning\QueueAnomalyModelAdapter;
use App\Framework\Waf\MachineLearning\WafBehavioralModelAdapter;

/**
 * Integration Tests for ML Model Management System
 *
 * Tests the complete integration of all three ML systems with Model Management
 */

describe('ML Model Management Integration', function () {

    test('N+1 Detector model adapter is registered in container', function () {
        $adapter = container()->get(NPlusOneModelAdapter::class);

        expect($adapter)->toBeInstanceOf(NPlusOneModelAdapter::class);
    })->skip('Requires full framework bootstrap');

    test('WAF Behavioral model adapter is registered in container', function () {
        $adapter = container()->get(WafBehavioralModelAdapter::class);

        expect($adapter)->toBeInstanceOf(WafBehavioralModelAdapter::class);
    })->skip('Requires full framework bootstrap');

    test('Queue Anomaly model adapter is registered in container', function () {
        $adapter = container()->get(QueueAnomalyModelAdapter::class);

        expect($adapter)->toBeInstanceOf(QueueAnomalyModelAdapter::class);
    })->skip('Requires full framework bootstrap');

    test('Model registry is accessible', function () {
        $registry = container()->get(ModelRegistry::class);

        expect($registry)->toBeInstanceOf(ModelRegistry::class);
    })->skip('Requires full framework bootstrap');
});

describe('Model Registration', function () {

    test('can register N+1 detector model', function () {
        // This test would require full framework initialization
        // For now, we verify the class structure

        expect(class_exists(NPlusOneModelAdapter::class))->toBeTrue();

        $reflection = new ReflectionClass(NPlusOneModelAdapter::class);
        expect($reflection->hasMethod('registerCurrentModel'))->toBeTrue();
        expect($reflection->hasMethod('analyzeWithTracking'))->toBeTrue();
        expect($reflection->hasMethod('getCurrentPerformanceMetrics'))->toBeTrue();
    });

    test('can register WAF behavioral model', function () {
        expect(class_exists(WafBehavioralModelAdapter::class))->toBeTrue();

        $reflection = new ReflectionClass(WafBehavioralModelAdapter::class);
        expect($reflection->hasMethod('registerCurrentModel'))->toBeTrue();
        expect($reflection->hasMethod('analyzeWithTracking'))->toBeTrue();
        expect($reflection->hasMethod('getCurrentPerformanceMetrics'))->toBeTrue();
    });

    test('can register queue anomaly model', function () {
        expect(class_exists(QueueAnomalyModelAdapter::class))->toBeTrue();

        $reflection = new ReflectionClass(QueueAnomalyModelAdapter::class);
        expect($reflection->hasMethod('registerCurrentModel'))->toBeTrue();
        expect($reflection->hasMethod('analyzeWithTracking'))->toBeTrue();
        expect($reflection->hasMethod('getCurrentPerformanceMetrics'))->toBeTrue();
    });
});

describe('Adapter Class Structure', function () {

    test('N+1 adapter has correct model name constant', function () {
        $reflection = new ReflectionClass(NPlusOneModelAdapter::class);
        $constants = $reflection->getConstants();

        expect($constants)->toHaveKey('MODEL_NAME');
        expect($constants['MODEL_NAME'])->toBe('n1-detector');
        expect($constants)->toHaveKey('CURRENT_VERSION');
        expect($constants['CURRENT_VERSION'])->toBe('1.0.0');
    });

    test('WAF adapter has correct model name constant', function () {
        $reflection = new ReflectionClass(WafBehavioralModelAdapter::class);
        $constants = $reflection->getConstants();

        expect($constants)->toHaveKey('MODEL_NAME');
        expect($constants['MODEL_NAME'])->toBe('waf-behavioral');
        expect($constants)->toHaveKey('CURRENT_VERSION');
        expect($constants['CURRENT_VERSION'])->toBe('1.0.0');
    });

    test('Queue adapter has correct model name constant', function () {
        $reflection = new ReflectionClass(QueueAnomalyModelAdapter::class);
        $constants = $reflection->getConstants();

        expect($constants)->toHaveKey('MODEL_NAME');
        expect($constants['MODEL_NAME'])->toBe('queue-anomaly');
        expect($constants)->toHaveKey('CURRENT_VERSION');
        expect($constants['CURRENT_VERSION'])->toBe('1.0.0');
    });
});

describe('Adapter Method Signatures', function () {

    test('N+1 adapter has correct method signatures', function () {
        $reflection = new ReflectionClass(NPlusOneModelAdapter::class);

        // registerCurrentModel
        $method = $reflection->getMethod('registerCurrentModel');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(1); // Optional performance metrics

        // analyzeWithTracking
        $method = $reflection->getMethod('analyzeWithTracking');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(2); // context, groundTruth

        // getCurrentPerformanceMetrics
        $method = $reflection->getMethod('getCurrentPerformanceMetrics');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(0);

        // checkPerformanceDegradation
        $method = $reflection->getMethod('checkPerformanceDegradation');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(1); // threshold percent
    });

    test('WAF adapter has correct method signatures', function () {
        $reflection = new ReflectionClass(WafBehavioralModelAdapter::class);

        $method = $reflection->getMethod('registerCurrentModel');
        expect($method->isPublic())->toBeTrue();

        $method = $reflection->getMethod('analyzeWithTracking');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(3); // features, baseline, groundTruth

        $method = $reflection->getMethod('getCurrentPerformanceMetrics');
        expect($method->isPublic())->toBeTrue();
    });

    test('Queue adapter has correct method signatures', function () {
        $reflection = new ReflectionClass(QueueAnomalyModelAdapter::class);

        $method = $reflection->getMethod('registerCurrentModel');
        expect($method->isPublic())->toBeTrue();

        $method = $reflection->getMethod('analyzeWithTracking');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(2); // features, groundTruth

        $method = $reflection->getMethod('getCurrentPerformanceMetrics');
        expect($method->isPublic())->toBeTrue();
    });
});

describe('Scheduler Integration', function () {

    test('ML monitoring scheduler class exists', function () {
        $class = 'App\\Framework\\MachineLearning\\Scheduler\\MLMonitoringScheduler';
        expect(class_exists($class))->toBeTrue();
    });

    test('ML monitoring scheduler has scheduleAll method', function () {
        $class = 'App\\Framework\\MachineLearning\\Scheduler\\MLMonitoringScheduler';
        $reflection = new ReflectionClass($class);

        expect($reflection->hasMethod('scheduleAll'))->toBeTrue();

        $method = $reflection->getMethod('scheduleAll');
        expect($method->isPublic())->toBeTrue();
        expect($method->getNumberOfParameters())->toBe(0);
    });

    test('ML monitoring scheduler initializer exists', function () {
        $class = 'App\\Framework\\MachineLearning\\Scheduler\\MLMonitoringSchedulerInitializer';
        expect(class_exists($class))->toBeTrue();

        $reflection = new ReflectionClass($class);
        expect($reflection->isFinal())->toBeTrue();
        expect($reflection->isReadOnly())->toBeTrue();
    });
});

describe('File Structure', function () {

    test('all adapter files exist', function () {
        $files = [
            '/var/www/html/src/Framework/Database/NPlusOneDetection/MachineLearning/NPlusOneModelAdapter.php',
            '/var/www/html/src/Framework/Waf/MachineLearning/WafBehavioralModelAdapter.php',
            '/var/www/html/src/Framework/Queue/MachineLearning/QueueAnomalyModelAdapter.php',
        ];

        foreach ($files as $file) {
            expect(file_exists($file))->toBeTrue("File should exist: {$file}");
        }
    });

    test('scheduler files exist', function () {
        $files = [
            '/var/www/html/src/Framework/MachineLearning/Scheduler/MLMonitoringScheduler.php',
            '/var/www/html/src/Framework/MachineLearning/Scheduler/MLMonitoringSchedulerInitializer.php',
        ];

        foreach ($files as $file) {
            expect(file_exists($file))->toBeTrue("File should exist: {$file}");
        }
    });

    test('deployment documentation exists', function () {
        $file = '/var/www/html/docs/ml-model-management-deployment.md';
        expect(file_exists($file))->toBeTrue();

        $content = file_get_contents($file);
        expect($content)->toContain('ML Model Management System');
        expect($content)->toContain('Production Deployment Guide');
    });

    test('integration example exists', function () {
        $file = '/var/www/html/examples/n1-model-management-integration.php';
        expect(file_exists($file))->toBeTrue();
    });
});
