<?php

declare(strict_types=1);

namespace App\Application\Admin\Development;

use App\Application\Admin\Service\AdminLayoutProcessor;
use App\Framework\Attributes\Route;
use App\Framework\Config\WafConfig as FrameworkWafConfig;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\Percentage;
use App\Framework\DateTime\Clock;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\Method;
use App\Framework\Http\Request;
use App\Framework\Logging\Logger;
use App\Framework\Meta\MetaData;
use App\Framework\Performance\PerformanceService;
use App\Framework\Router\Result\JsonResult;
use App\Framework\Router\Result\ViewResult;
use App\Framework\Waf\Analysis\Analyzers\BodyAnalyzer;
use App\Framework\Waf\Analysis\Analyzers\HeaderAnalyzer;
use App\Framework\Waf\Analysis\Analyzers\ParameterAnalyzer;
use App\Framework\Waf\Analysis\Analyzers\UrlAnalyzer;
use App\Framework\Waf\MachineLearning\Detectors\ClusteringAnomalyDetector;
use App\Framework\Waf\MachineLearning\Detectors\StatisticalAnomalyDetector;
use App\Framework\Waf\MachineLearning\Extractors\FrequencyFeatureExtractor;
use App\Framework\Waf\MachineLearning\Extractors\PatternFeatureExtractor;
use App\Framework\Waf\MachineLearning\MachineLearningEngine;
use App\Framework\Waf\Rules\RuleEngine;
use App\Framework\Waf\ThreatAssessmentService;
use App\Framework\Waf\WafEngine;

/**
 * Test controller for WAF functionality
 */
final class WafTestController
{
    private ?WafEngine $wafEngine = null;

    public function __construct(
        private readonly PerformanceService $performance,
        private readonly Logger $logger,
        private readonly Clock $clock,
        private readonly AdminLayoutProcessor $layoutProcessor,
    ) {
    }

    #[Route(path: '/admin/dev/waf-test', method: Method::GET, name: 'admin.dev.waf-test')]
    public function showTestPage(): ViewResult
    {
        $data = [
            'title' => 'WAF Test Suite',
            'current_year' => $this->clock->now()->format('Y'),
        ];

        $finalData = $this->layoutProcessor->processLayoutFromArray($data);

        return new ViewResult(
            template: 'waf-test',
            metaData: new MetaData('WAF Test Suite', 'Web Application Firewall Testing Interface'),
            data: $finalData
        );
    }

    #[Route(path: '/admin/dev/waf-test/analyze', method: Method::GET)]
    public function analyzeRequest(Request $request): JsonResult
    {
        // Initialize WAF if not already done
        if ($this->wafEngine === null) {
            $this->initializeWaf();
        }

        // Create a test request with the provided parameters
        $httpRequest = $request instanceof HttpRequest ? $request : null;
        if (! $httpRequest) {
            return new JsonResult(['error' => 'Invalid request type']);
        }

        $testPath = $httpRequest->getQuery('test_path', '/');
        $testParams = [];

        // Extract test parameters
        foreach ($httpRequest->queryParams as $key => $value) {
            if (str_starts_with($key, 'param_')) {
                $paramName = substr($key, 6);
                $testParams[$paramName] = $value;
            }
        }

        // Create modified request for testing
        $testRequest = $this->createTestRequest($request, $testPath, $testParams);

        // Analyze with WAF (after null check)
        if ($this->wafEngine === null) {
            return new JsonResult(['error' => 'WAF engine not initialized']);
        }

        $decision = $this->wafEngine->analyzeRequest($testRequest);

        // Get detailed results
        $layerResults = $this->wafEngine->getLayerResults();
        $performanceStats = $this->wafEngine->getPerformanceStats();

        return new JsonResult([
            'allowed' => $decision->isAllowed(),
            'action' => $decision->action->value,
            'reason' => $decision->reason,
            'threat_score' => $decision->assessment->overallThreatScore->getValue(),
            'confidence' => $decision->assessment->averageConfidence->getValue(),
            'matched_rules' => [],
            'layer_results' => $this->formatLayerResults($layerResults),
            'performance' => $performanceStats,
            'test_info' => [
                'path' => $testPath,
                'params' => $testParams,
                'method' => $testRequest->method->value,
            ],
        ]);
    }

    private function initializeWaf(): void
    {
        // Create WAF configuration
        $config = FrameworkWafConfig::default()
            ->enable()
            ->withBlockingThreshold(Percentage::from(70.0));

        // Create threat assessment service
        $threatAssessmentService = new ThreatAssessmentService(
            blockingThreshold: Percentage::from(70.0),
            warningThreshold: Percentage::from(40.0),
            learningMode: false,
            clock: $this->clock
        );

        // Initialize analyzers
        $analyzers = [
            new HeaderAnalyzer(),
            new BodyAnalyzer(),
            new ParameterAnalyzer(),
            new UrlAnalyzer(),
        ];

        // Skip rule engine for now due to missing classes
        // $ruleLoader = new RuleLoader();
        // $ruleEngine = new RuleEngine(
        //     rules: $ruleLoader->loadAll(),
        //     logger: $this->logger,
        //     clock: $this->clock
        // );

        // Initialize ML engine
        $mlEngine = new MachineLearningEngine(
            enabled: true,
            extractors: [
                new FrequencyFeatureExtractor(),
                new PatternFeatureExtractor(),
            ],
            detectors: [
                new StatisticalAnomalyDetector(),
                new ClusteringAnomalyDetector(),
            ],
            clock: $this->clock,
            analysisTimeout: Duration::fromMilliseconds(5000),
            confidenceThreshold: Percentage::from(75.0)
        );

        // Create WAF engine
        $this->wafEngine = new WafEngine(
            config: $config,
            threatAssessmentService: $threatAssessmentService,
            performance: $this->performance,
            logger: $this->logger,
            clock: $this->clock,
            mlEngine: $mlEngine
        );

        // Skip layer registration for now
        // foreach ($analyzers as $analyzer) {
        //     $this->wafEngine->registerLayer($analyzer);
        // }
        // $this->wafEngine->registerLayer($ruleEngine);
    }

    /**
     * @param array<string, mixed> $testParams
     */
    private function createTestRequest(Request $originalRequest, string $testPath, array $testParams): Request
    {
        // For now, just return the original request
        // In a real implementation, we'd create a proper test request wrapper
        return $originalRequest;
    }

    /**
     * @param array<string, mixed> $layerResults
     * @return array<string, mixed>
     */
    private function formatLayerResults(array $layerResults): array
    {
        $formatted = [];

        foreach ($layerResults as $layerName => $result) {
            // Skip formatting for now due to missing LayerResult class
            $formatted[$layerName] = [
                'status' => 'unknown',
                'threat_score' => 0.0,
                'confidence' => 0.0,
                'detections' => [],
                'execution_time_ms' => 0.0,
            ];
        }

        return $formatted;
    }
}
