<?php

namespace FleekDash\Controllers;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use FleekDash\Services\QueryOptimizer;
use FleekDash\Services\CacheOptimizer;
use FleekDash\Core\AuthMiddleware;

class OptimizationController
{
    private const MSG_UNAUTHORIZED = 'Unauthorized access';
    private const MSG_CACHE_OPTIMIZER_UNAVAILABLE = 'Cache optimizer unavailable';

    private ?QueryOptimizer $queryOptimizer;
    private ?CacheOptimizer $cacheOptimizer;
    private AuthMiddleware $authMiddleware;

    public function __construct()
    {
        try {
            $this->queryOptimizer = new QueryOptimizer();
        } catch (\Exception $e) {
            $this->queryOptimizer = null;
        }

        try {
            $this->cacheOptimizer = new CacheOptimizer();
        } catch (\Exception $e) {
            $this->cacheOptimizer = null;
        }

        $this->authMiddleware = new AuthMiddleware();
    }

    /**
     * Aggregate query + cache optimization metrics
     */
    public function getOptimizationStats()
    {
        if (!$this->checkAuth()) {
            return new WP_Error('unauthorized', self::MSG_UNAUTHORIZED, ['status' => 401]);
        }

        try {
            $query_stats = $this->queryOptimizer ? $this->queryOptimizer->getOptimizationStats() : [];
            $cache_stats = $this->cacheOptimizer ? $this->cacheOptimizer->getCacheStats() : [];

            $response = [
                'success' => true,
                'data' => [
                    'query_optimization' => $query_stats,
                    'cache_optimization' => $cache_stats,
                    'overall_performance' => $this->calculateOverallPerformance($query_stats, $cache_stats)
                ],
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'execution_time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']
                ]
            ];

            return new WP_REST_Response($response, 200);

        } catch (\Exception $e) {
            return new WP_Error('optimization_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Apply CREATE INDEX statements from QueryOptimizer recommendations
     */
    public function createRecommendedIndexes()
    {
        $authResult = $this->validateAuthAndOptimizer(true, false);
        if ($authResult !== null) {
            return $authResult;
        }

        try {
            $result = $this->queryOptimizer->createRecommendedIndexes();
            $response = [
                'success' => true,
                'data' => $result,
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'message' => 'Index creation completed'
                ]
            ];
            return new WP_REST_Response($response, 200);
        } catch (\Exception $e) {
            return new WP_Error('index_creation_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Run analyzer on a SQL string from the request body
     */
    public function analyzeQueryPerformance(WP_REST_Request $request)
    {
        $query = $request->get_param('query');
        $validationError = $this->getAuthErrorIfUnauthorized()
            ?? (!$query ? new WP_Error('missing_query', 'Query parameter is required', ['status' => 400]) : null)
            ?? (!$this->queryOptimizer ? new WP_Error('optimizer_unavailable', 'Query optimizer unavailable', ['status' => 500]) : null);
        if ($validationError !== null) {
            return $validationError;
        }

        try {
            $analysis = $this->queryOptimizer->analyzeQueryPerformance($query);
            $response = [
                'success' => true,
                'data' => $analysis,
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'query_length' => strlen($query)
                ]
            ];
            return new WP_REST_Response($response, 200);
        } catch (\Exception $e) {
            return new WP_Error('analysis_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Run cache usage optimization + auto cleanup
     */
    public function optimizeCache()
    {
        $validationError = $this->validateAuthAndOptimizer(false, true);
        if ($validationError !== null) {
            return $validationError;
        }
        try {
            $optimizations = $this->cacheOptimizer->optimizeCacheUsage();
            $cleanup_result = $this->cacheOptimizer->autoCleanupCache();

            $response = [
                'success' => true,
                'data' => [
                    'optimizations' => $optimizations,
                    'cleanup' => $cleanup_result
                ],
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'optimizations_count' => count($optimizations)
                ]
            ];

            return new WP_REST_Response($response, 200);

        } catch (\Exception $e) {
            return new WP_Error('cache_optimization_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Invalidate cache entries by pattern and strategy
     */
    public function invalidateCache(WP_REST_Request $request)
    {
        $pattern = $request->get_param('pattern');
        $strategy = $request->get_param('strategy') ?? 'pattern';
        $validationError = $this->validateAuthAndOptimizer(false, true)
            ?? (!$pattern ? new WP_Error('missing_pattern', 'Pattern parameter is required', ['status' => 400]) : null);
        if ($validationError !== null) {
            return $validationError;
        }

        try {
            $invalidated = $this->cacheOptimizer->invalidateCache($pattern, $strategy);

            $response = [
                'success' => true,
                'data' => [
                    'pattern' => $pattern,
                    'strategy' => $strategy,
                    'invalidated_count' => $invalidated
                ],
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'message' => "Cache invalidation completed for pattern: {$pattern}"
                ]
            ];

            return new WP_REST_Response($response, 200);

        } catch (\Exception $e) {
            return new WP_Error('cache_invalidation_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Apply cache optimizer runtime configuration
     */
    public function configureOptimizations(WP_REST_Request $request)
    {
        $config = $request->get_json_params();
        $validationError = $this->validateAuthAndOptimizer(false, true)
            ?? (!$config ? new WP_Error('missing_config', 'Configuration data is required', ['status' => 400]) : null);
        if ($validationError !== null) {
            return $validationError;
        }
        try {
            $cache_config = $config['cache'] ?? [];
            $this->cacheOptimizer->configureCacheOptimizations($cache_config);

            $response = [
                'success' => true,
                'data' => [
                    'cache_config' => $cache_config,
                    'message' => 'Optimizations configured successfully'
                ],
                'meta' => [
                    'timestamp' => \current_time('mysql')
                ]
            ];

            return new WP_REST_Response($response, 200);

        } catch (\Exception $e) {
            return new WP_Error('configuration_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Run built-in optimization smoke tests
     */
    public function testOptimizations()
    {
        if (!$this->checkAuth()) {
            return new WP_Error('unauthorized', self::MSG_UNAUTHORIZED, ['status' => 401]);
        }

        try {
            $test_results = $this->runOptimizationTests();

            $response = [
                'success' => true,
                'data' => $test_results,
                'meta' => [
                    'timestamp' => \current_time('mysql'),
                    'tests_count' => count($test_results)
                ]
            ];

            return new WP_REST_Response($response, 200);

        } catch (\Exception $e) {
            return new WP_Error('test_error', $e->getMessage(), ['status' => 500]);
        }
    }

    /**
     * Run built-in optimization diagnostics.
     */
    private function runOptimizationTests()
    {
        $tests = [];

        // Query optimization sample
        $test_query = "SELECT * FROM wp_fleekdash_pageviews WHERE date >= '2024-01-01' ORDER BY date DESC LIMIT 100";
        $query_analysis = $this->queryOptimizer ? $this->queryOptimizer->analyzeQueryPerformance($test_query) : [];
        $tests['query_optimization'] = [
            'test_query' => $test_query,
            'analysis' => $query_analysis,
            'status' => 'completed'
        ];

        // Cache optimization stats
        $cache_stats = $this->cacheOptimizer ? $this->cacheOptimizer->getCacheStats() : [];
        $tests['cache_optimization'] = [
            'stats' => $cache_stats,
            'status' => 'completed'
        ];

        // Overall performance composite score
        $overall_performance = $this->calculateOverallPerformance(
            $this->queryOptimizer ? $this->queryOptimizer->getOptimizationStats() : [],
            $cache_stats,
        );
        $tests['overall_performance'] = [
            'metrics' => $overall_performance,
            'status' => 'completed'
        ];

        return $tests;
    }

    /**
     * Calculate overall performance
     */
    private function calculateOverallPerformance(array $query_stats, array $cache_stats): array
    {
        $performance = [
            'cache_hit_rate' => $cache_stats['overall_hit_rate'] ?? 0,
            'avg_query_time' => $query_stats['avg_query_time'] ?? 0,
            'slow_queries_count' => count($query_stats['slow_queries'] ?? []),
            'recommended_indexes' => $query_stats['recommended_indexes'] ?? 0,
            'cache_size_mb' => $cache_stats['total_size_mb'] ?? 0
        ];

        // Weighted overall score (0–100)
        $score = 0;

        // Cache hit rate (40% weight)
        $score += min(40, ($performance['cache_hit_rate'] / 100) * 40);

        // Query time (30% weight)
        $score += max(0, 30 - ($performance['avg_query_time'] * 100));

        // Slow queries (20% weight)
        $score += max(0, 20 - ($performance['slow_queries_count'] * 2));

        // Recommended indexes (10% weight)
        $score += min(10, ($performance['recommended_indexes'] / 10) * 10);

        $performance['overall_score'] = round($score, 2);
        $performance['grade'] = $this->getPerformanceGrade($score);

        return $performance;
    }

    /**
     * Map numeric score to letter grade.
     */
    private function getPerformanceGrade(float $score): string
    {
        $grade = 'F';
        if ($score >= 90) {
            $grade = 'A+';
        } elseif ($score >= 80) {
            $grade = 'A';
        } elseif ($score >= 70) {
            $grade = 'B';
        } elseif ($score >= 60) {
            $grade = 'C';
        } elseif ($score >= 50) {
            $grade = 'D';
        }
        return $grade;
    }

    /**
     * Returns auth error if unauthorized, null otherwise
     */
    private function getAuthErrorIfUnauthorized()
    {
        if (!$this->checkAuth()) {
            return new WP_Error('unauthorized', self::MSG_UNAUTHORIZED, ['status' => 401]);
        }
        return null;
    }

    /**
     * Validates auth and optimizer availability. Returns WP_Error or null.
     * @param bool $requireQueryOptimizer
     * @param bool $requireCacheOptimizer
     */
    private function validateAuthAndOptimizer($requireQueryOptimizer, $requireCacheOptimizer)
    {
        $error = null;
        if (!$this->checkAuth()) {
            $error = new WP_Error('unauthorized', self::MSG_UNAUTHORIZED, ['status' => 401]);
        } elseif ($requireQueryOptimizer && !$this->queryOptimizer) {
            $error = new WP_Error('optimizer_unavailable', 'Query optimizer unavailable', ['status' => 500]);
        } elseif ($requireCacheOptimizer && !$this->cacheOptimizer) {
            $error = new WP_Error('cache_optimizer_unavailable', self::MSG_CACHE_OPTIMIZER_UNAVAILABLE, ['status' => 500]);
        }
        return $error;
    }

    /**
     * Whether the current REST user passes authenticated check
     */
    private function checkAuth()
    {
        return $this->authMiddleware->check_auth('authenticated');
    }
}
