<?php

namespace FleekDash\Controllers;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use FleekDash\Services\TestSuite;
use FleekDash\Core\AuthMiddleware;

/**
 * TestController — exposes TestSuite helpers via REST API.
 */
class TestController
{
    private TestSuite $testSuite;
    private AuthMiddleware $authMiddleware;

    public function __construct()
    {
        $this->testSuite = new TestSuite();
        $this->authMiddleware = new AuthMiddleware();
    }

    /**
     * Run the full TestSuite batch
     */
    public function runAllTests(WP_REST_Request $request)
    {
        try {
            // Verify authentication
            $authResult = $this->authMiddleware->verify_request($request);
            if (is_wp_error($authResult)) {
                return $authResult;
            }

            $results = $this->testSuite->runAllTests();

            return new WP_REST_Response([
                'success' => true,
                'message' => 'All tests completed successfully',
                'data' => $results
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'test_execution_error',
                'Failed to run tests: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Run only test types that exist on TestSuite (whitelist via TestSuite::TEST_TYPES keys).
     */
    private function executeAllowedTestTypes(array $testTypes): array
    {
        $results = [];
        foreach ($testTypes as $type) {
            if (!is_string($type) || !isset(TestSuite::TEST_TYPES[$type])) {
                continue;
            }
            $batch = $this->testSuite->runTestsForType($type);
            if ($batch !== null) {
                $results[$type] = $batch;
            }
        }
        return $results;
    }

    /**
     * Run a whitelist of test types from the request body
     */
    public function runSpecificTests(WP_REST_Request $request)
    {
        $authResult = $this->authMiddleware->verify_request($request);
        if (is_wp_error($authResult)) {
            return $authResult;
        }

        $testTypes = $request->get_param('test_types');
        $invalidTypes = !$testTypes || !is_array($testTypes);
        if ($invalidTypes) {
            return new WP_Error(
                'invalid_test_types',
                'test_types must be a non-empty array',
                ['status' => 400],
            );
        }

        try {
            $results = $this->executeAllowedTestTypes($testTypes);
            $response = new WP_REST_Response([
                'success' => true,
                'message' => 'Selected test types completed',
                'data' => $results
            ], 200);
        } catch (\Exception $e) {
            $response = new WP_Error(
                'specific_test_error',
                'Failed to run selected test types: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
        return $response;
    }

    /**
     * Build aggregated TestSuite report JSON
     */
    public function generateTestReport(WP_REST_Request $request)
    {
        try {
            // Verify authentication
            $authResult = $this->authMiddleware->verify_request($request);
            if (is_wp_error($authResult)) {
                return $authResult;
            }

            $report = $this->testSuite->generateTestReport();

            return new WP_REST_Response([
                'success' => true,
                'message' => 'Test report generated',
                'data' => $report
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'report_generation_error',
                'Failed to generate test report: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Return TestSuite metadata (types, thresholds)
     */
    public function getTestStats(WP_REST_Request $request)
    {
        try {
            // Verify authentication
            $authResult = $this->authMiddleware->verify_request($request);
            if (is_wp_error($authResult)) {
                return $authResult;
            }

            $stats = [
                'total_test_types' => count(TestSuite::TEST_TYPES),
                'performance_thresholds' => TestSuite::PERFORMANCE_THRESHOLDS,
                'available_tests' => array_keys(TestSuite::TEST_TYPES)
            ];

            return new WP_REST_Response([
                'success' => true,
                'message' => 'Test statistics retrieved',
                'data' => $stats
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'stats_error',
                'Failed to load test statistics: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Lightweight probe for a named REST route (simulated timing)
     */
    public function testEndpoint(WP_REST_Request $request)
    {
        $response = null;
        try {
            $authResult = $this->authMiddleware->verify_request($request);
            if (is_wp_error($authResult)) {
                $response = $authResult;
            } else {
                $endpoint = $request->get_param('endpoint');
                if (!$endpoint) {
                    $response = new WP_Error(
                        'missing_endpoint',
                        'endpoint parameter is required',
                        ['status' => 400],
                    );
                } else {
                    $testResult = [
                    'endpoint' => $endpoint,
                    'status' => 'tested',
                    'response_time' => random_int(10, 500) / 1000, // 10-500ms, cryptographically secure
                    'success' => true
                ];
                    $response = new WP_REST_Response([
                        'success' => true,
                        'message' => 'Endpoint probe completed',
                        'data' => $testResult
                    ], 200);
                }
            }
        } catch (\Throwable $e) {
            $response = new WP_Error(
                'endpoint_test_error',
                'Endpoint probe failed: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
        // Fallback: never return null to REST layer (defense against catch-block failures)
        return $response ?? new WP_Error(
            'internal_error',
            'Unexpected error processing endpoint test',
            ['status' => 500],
        );
    }

    /**
     * Run synthetic latency check against PERFORMANCE_THRESHOLDS
     */
    public function runPerformanceTest(WP_REST_Request $request)
    {
        try {
            // Verify authentication
            $authResult = $this->authMiddleware->verify_request($request);
            if (is_wp_error($authResult)) {
                return $authResult;
            }

            $testType = $request->get_param('test_type') ?? 'api_response';

            $startTime = microtime(true);

            // Simulate different test types
            switch ($testType) {
                case 'api_response':
                    sleep(0.1); // Simulate 100ms
                    break;
                case 'query_execution':
                    sleep(0.05); // Simulate 50ms
                    break;
                case 'cache_performance':
                    sleep(0.02); // Simulate 20ms
                    break;
                default:
                    sleep(0.1);
            }

            $executionTime = microtime(true) - $startTime;
            $threshold = TestSuite::PERFORMANCE_THRESHOLDS[$testType] ?? 0.5;

            $result = [
                'test_type' => $testType,
                'execution_time' => $executionTime,
                'threshold' => $threshold,
                'passed' => $executionTime <= $threshold,
                'performance_grade' => $this->calculatePerformanceGrade($executionTime, $threshold)
            ];

            return new WP_REST_Response([
                'success' => true,
                'message' => 'Performance test completed',
                'data' => $result
            ], 200);

        } catch (\Exception $e) {
            return new WP_Error(
                'performance_test_error',
                'Performance test failed: ' . $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Map execution time vs threshold to a letter grade
     */
    private function calculatePerformanceGrade(float $executionTime, float $threshold): string
    {
        $ratio = $executionTime / $threshold;
        $grades = [
            0.5 => 'A+',
            0.7 => 'A',
            0.9 => 'B',
            1.0 => 'C',
            1.2 => 'D',
        ];
        foreach ($grades as $limit => $grade) {
            if ($ratio <= $limit) {
                return $grade;
            }
        }
        return 'F';
    }
}
