<?php

declare(strict_types=1);

namespace App\Framework\Database\Profiling\Reports;

/**
 * Optimization analysis report with suggestions and recommendations
 */
final readonly class OptimizationReport
{
    public function __construct(
        public array $optimizationData
    ) {
    }

    /**
     * Get optimization summary
     */
    public function getOptimizationSummary(): array
    {
        $summary = [
            'total_connections' => count($this->optimizationData),
            'optimization_priorities' => [],
            'top_recommendations' => [],
            'total_issues' => 0,
            'critical_issues' => 0,
            'index_suggestions_count' => 0,
            'slow_query_patterns_count' => 0,
        ];

        $allRecommendations = [];

        foreach ($this->optimizationData as $connectionName => $data) {
            $priority = $data['optimization_priority'];
            $summary['optimization_priorities'][$priority] = ($summary['optimization_priorities'][$priority] ?? 0) + 1;
            $summary['total_issues'] += $data['total_issues'];
            $summary['index_suggestions_count'] += count($data['index_suggestions']);
            $summary['slow_query_patterns_count'] += count($data['slow_query_patterns']);

            if ($priority === 'critical') {
                $summary['critical_issues']++;
            }

            // Collect all recommendations
            foreach ($data['recommendations'] as $recommendation) {
                $key = md5($recommendation);
                if (! isset($allRecommendations[$key])) {
                    $allRecommendations[$key] = [
                        'text' => $recommendation,
                        'count' => 0,
                        'connections' => [],
                    ];
                }
                $allRecommendations[$key]['count']++;
                $allRecommendations[$key]['connections'][] = $connectionName;
            }
        }

        // Sort recommendations by frequency
        uasort($allRecommendations, fn ($a, $b) => $b['count'] <=> $a['count']);
        $summary['top_recommendations'] = array_slice($allRecommendations, 0, 10);

        return $summary;
    }

    /**
     * Get connections by optimization priority
     */
    public function getConnectionsByPriority(string $priority): array
    {
        $connections = [];

        foreach ($this->optimizationData as $connectionName => $data) {
            if ($data['optimization_priority'] === $priority) {
                $connections[$connectionName] = $data;
            }
        }

        return $connections;
    }

    /**
     * Get most common slow query patterns across all connections
     */
    public function getTopSlowQueryPatterns(int $limit = 10): array
    {
        $patterns = [];

        foreach ($this->optimizationData as $connectionName => $data) {
            foreach ($data['slow_query_patterns'] as $pattern => $count) {
                if (! isset($patterns[$pattern])) {
                    $patterns[$pattern] = [
                        'pattern' => $pattern,
                        'total_count' => 0,
                        'connections' => [],
                    ];
                }
                $patterns[$pattern]['total_count'] += $count;
                $patterns[$pattern]['connections'][$connectionName] = $count;
            }
        }

        // Sort by total count
        uasort($patterns, fn ($a, $b) => $b['total_count'] <=> $a['total_count']);

        return array_slice($patterns, 0, $limit);
    }

    /**
     * Get all unique index suggestions
     */
    public function getAllIndexSuggestions(): array
    {
        $suggestions = [];

        foreach ($this->optimizationData as $connectionName => $data) {
            foreach ($data['index_suggestions'] as $suggestion) {
                if (! isset($suggestions[$suggestion])) {
                    $suggestions[$suggestion] = [
                        'suggestion' => $suggestion,
                        'connections' => [],
                    ];
                }
                $suggestions[$suggestion]['connections'][] = $connectionName;
            }
        }

        return array_values($suggestions);
    }

    /**
     * Get performance issues by severity
     */
    public function getPerformanceIssuesBySeverity(): array
    {
        $issues = [
            'very_slow_query' => [],
            'n_plus_one' => [],
            'missing_index' => [],
            'full_table_scan' => [],
        ];

        foreach ($this->optimizationData as $connectionName => $data) {
            foreach ($data['performance_issues'] as $issue) {
                $type = $issue['type'];
                if (isset($issues[$type])) {
                    $issue['connection'] = $connectionName;
                    $issues[$type][] = $issue;
                }
            }
        }

        // Sort each category by execution time
        foreach ($issues as &$categoryIssues) {
            usort(
                $categoryIssues,
                fn ($a, $b) =>
                ($b['execution_time_ms'] ?? 0) <=> ($a['execution_time_ms'] ?? 0)
            );
        }

        return $issues;
    }

    /**
     * Get optimization roadmap with prioritized actions
     */
    public function getOptimizationRoadmap(): array
    {
        $roadmap = [
            'immediate_actions' => [],
            'short_term_actions' => [],
            'long_term_actions' => [],
        ];

        foreach ($this->optimizationData as $connectionName => $data) {
            $priority = $data['optimization_priority'];

            switch ($priority) {
                case 'critical':
                    $roadmap['immediate_actions'][] = [
                        'connection' => $connectionName,
                        'action' => 'Critical performance issues detected - investigate immediately',
                        'issues' => $data['total_issues'],
                        'recommendations' => array_slice($data['recommendations'], 0, 3),
                    ];

                    break;

                case 'high':
                    $roadmap['short_term_actions'][] = [
                        'connection' => $connectionName,
                        'action' => 'Performance optimization needed within days',
                        'issues' => $data['total_issues'],
                        'recommendations' => array_slice($data['recommendations'], 0, 3),
                    ];

                    break;

                case 'medium':
                case 'low':
                    $roadmap['long_term_actions'][] = [
                        'connection' => $connectionName,
                        'action' => 'Schedule optimization during maintenance window',
                        'issues' => $data['total_issues'],
                        'recommendations' => array_slice($data['recommendations'], 0, 2),
                    ];

                    break;
            }
        }

        return $roadmap;
    }

    /**
     * Get optimization impact estimation
     */
    public function getOptimizationImpact(): array
    {
        $impact = [
            'potential_time_savings' => 0,
            'queries_to_optimize' => 0,
            'connections_needing_optimization' => 0,
            'estimated_improvement_percentage' => 0,
        ];

        $totalConnections = count($this->optimizationData);
        $connectionsNeedingWork = 0;
        $totalSlowPatterns = 0;

        foreach ($this->optimizationData as $data) {
            if ($data['optimization_priority'] !== 'low') {
                $connectionsNeedingWork++;
            }

            $totalSlowPatterns += count($data['slow_query_patterns']);
            $impact['queries_to_optimize'] += array_sum($data['slow_query_patterns']);
        }

        $impact['connections_needing_optimization'] = $connectionsNeedingWork;

        // Rough estimation based on priority distribution
        $criticalCount = count($this->getConnectionsByPriority('critical'));
        $highCount = count($this->getConnectionsByPriority('high'));

        $impact['estimated_improvement_percentage'] = min(
            ($criticalCount * 30 + $highCount * 20) / max($totalConnections, 1),
            80
        );

        // Estimate potential time savings (very rough approximation)
        $impact['potential_time_savings'] = $totalSlowPatterns * 0.5; // seconds per pattern

        return $impact;
    }

    /**
     * Convert to array
     */
    public function toArray(): array
    {
        return [
            'optimization_summary' => $this->getOptimizationSummary(),
            'top_slow_query_patterns' => $this->getTopSlowQueryPatterns(),
            'all_index_suggestions' => $this->getAllIndexSuggestions(),
            'performance_issues_by_severity' => $this->getPerformanceIssuesBySeverity(),
            'optimization_roadmap' => $this->getOptimizationRoadmap(),
            'optimization_impact' => $this->getOptimizationImpact(),
            'detailed_data' => $this->optimizationData,
        ];
    }
}
