<?php

declare(strict_types=1);

namespace App\Framework\Database\Monitoring\Dashboard;

use App\Framework\Attributes\Route;
use App\Framework\Database\DatabaseManager;
use App\Framework\Database\Driver\Optimization\MySQLOptimizer;
use App\Framework\Database\Driver\Optimization\PostgreSQLOptimizer;
use App\Framework\Database\Driver\Optimization\SQLiteOptimizer;
use App\Framework\Database\Profiling\ProfilingDashboard;
use App\Framework\Database\Profiling\QueryProfiler;
use App\Framework\Database\Profiling\SlowQueryDetector;
use App\Framework\Http\Controller;
use App\Framework\Http\Response\JsonResponse;
use App\Framework\Http\Response\Response;
use App\Framework\Http\Response\ViewResponse;
use App\Framework\View\ViewRenderer;

/**
 * Controller for the database performance dashboard
 */
final readonly class DatabaseDashboardController implements Controller
{
    public function __construct(
        private DatabaseManager $databaseManager,
        private QueryProfiler $queryProfiler,
        private SlowQueryDetector $slowQueryDetector,
        private ProfilingDashboard $profilingDashboard,
        private ViewRenderer $viewRenderer
    ) {
    }

    /**
     * Dashboard home page
     */
    #[Route('/admin/database/dashboard', name: 'database_dashboard')]
    public function dashboard(): Response
    {
        $connections = $this->databaseManager->getConnectionNames();
        $activeConnection = $connections[0] ?? 'default';

        return new ViewResponse(
            $this->viewRenderer->render('admin/database/dashboard', [
                'connections' => $connections,
                'activeConnection' => $activeConnection,
                'stats' => $this->getConnectionStats($activeConnection),
            ])
        );
    }

    /**
     * Get database statistics for a specific connection
     */
    #[Route('/admin/database/stats/{connection}', name: 'database_stats')]
    public function stats(string $connection = 'default'): Response
    {
        return new JsonResponse($this->getConnectionStats($connection));
    }

    /**
     * Get query statistics
     */
    #[Route('/admin/database/queries', name: 'database_queries')]
    public function queries(): Response
    {
        $stats = $this->queryProfiler->getStatistics();
        $slowQueries = $this->slowQueryDetector->getSlowQueries();

        return new JsonResponse([
            'total_queries' => $stats->totalQueries,
            'total_time' => $stats->totalTime,
            'average_time' => $stats->averageTime,
            'slow_queries' => count($slowQueries),
            'recent_queries' => $this->queryProfiler->getRecentQueries(10),
            'slow_query_list' => array_map(fn ($q) => [
                'sql' => $q->sql,
                'parameters' => $q->parameters,
                'time' => $q->time,
                'timestamp' => $q->timestamp,
                'connection' => $q->connection,
            ], array_slice($slowQueries, 0, 10)),
        ]);
    }

    /**
     * Get table statistics for a specific connection
     */
    #[Route('/admin/database/tables/{connection}', name: 'database_tables')]
    public function tables(string $connection = 'default'): Response
    {
        $optimizer = $this->getOptimizer($connection);

        if ($optimizer === null) {
            return new JsonResponse(['error' => 'Unsupported database driver'], 400);
        }

        return new JsonResponse([
            'tables' => $optimizer->getTableStatus(),
        ]);
    }

    /**
     * Get index statistics for a specific connection
     */
    #[Route('/admin/database/indexes/{connection}', name: 'database_indexes')]
    public function indexes(string $connection = 'default'): Response
    {
        $optimizer = $this->getOptimizer($connection);

        if ($optimizer === null) {
            return new JsonResponse(['error' => 'Unsupported database driver'], 400);
        }

        return new JsonResponse([
            'indexes' => $optimizer->getIndexStatistics(),
        ]);
    }

    /**
     * Get database-specific statistics
     */
    #[Route('/admin/database/specific/{connection}', name: 'database_specific')]
    public function specificStats(string $connection = 'default'): Response
    {
        $conn = $this->databaseManager->getConnection($connection);
        $driver = $conn->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);

        $stats = [];

        switch ($driver) {
            case 'mysql':
                $optimizer = new MySQLOptimizer($conn);
                $stats['query_cache'] = $optimizer->getQueryCacheStatistics();
                $stats['buffer_pool'] = $optimizer->getBufferPoolStatistics();
                $stats['slow_query_log'] = $optimizer->getSlowQueryLogStatus();

                break;

            case 'pgsql':
                $optimizer = new PostgreSQLOptimizer($conn);
                $stats['cache'] = $optimizer->getCacheStatistics();
                $stats['settings'] = $optimizer->getDatabaseSettings('shared_buffers|work_mem|maintenance_work_mem|effective_cache_size');
                $stats['long_running'] = $optimizer->getLongRunningQueries(5);

                break;

            case 'sqlite':
                $optimizer = new SQLiteOptimizer($conn);
                $stats['database'] = $optimizer->getDatabaseStatistics();
                $stats['pragmas'] = $optimizer->getPragmaSettings();

                break;

            default:
                return new JsonResponse(['error' => 'Unsupported database driver'], 400);
        }

        return new JsonResponse($stats);
    }

    /**
     * Get profiling data
     */
    #[Route('/admin/database/profiling', name: 'database_profiling')]
    public function profiling(): Response
    {
        return new JsonResponse([
            'summary' => $this->profilingDashboard->getSummary(),
            'top_queries' => $this->profilingDashboard->getTopQueries(10),
            'query_types' => $this->profilingDashboard->getQueryTypeDistribution(),
            'hourly_stats' => $this->profilingDashboard->getHourlyStatistics(),
        ]);
    }

    /**
     * Get connection statistics
     * @return array<string, mixed>
     */
    private function getConnectionStats(string $connection): array
    {
        $conn = $this->databaseManager->getConnection($connection);
        $driver = $conn->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);

        $stats = [
            'driver' => $driver,
            'version' => $conn->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION),
            'connection_status' => $conn->getPdo()->getAttribute(\PDO::ATTR_CONNECTION_STATUS),
        ];

        // Get optimizer-specific stats
        $optimizer = $this->getOptimizer($connection);

        if ($optimizer !== null) {
            // Get table count
            $tableStatus = $optimizer->getTableStatus();
            $stats['table_count'] = count($tableStatus);

            // Get total row count (approximate)
            $totalRows = 0;
            foreach ($tableStatus as $table) {
                if (isset($table['row_count'])) {
                    $totalRows += $table['row_count'];
                } elseif (isset($table['Rows'])) {
                    $totalRows += $table['Rows'];
                }
            }
            $stats['total_rows'] = $totalRows;

            // Get index count
            $indexStats = $optimizer->getIndexStatistics();
            $indexCount = 0;
            foreach ($indexStats as $tableIndexes) {
                $indexCount += count($tableIndexes);
            }
            $stats['index_count'] = $indexCount;
        }

        return $stats;
    }

    /**
     * Get the appropriate optimizer for the database connection
     */
    private function getOptimizer(string $connection)
    {
        $conn = $this->databaseManager->getConnection($connection);
        $driver = $conn->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);

        return match ($driver) {
            'mysql' => new MySQLOptimizer($conn),
            'pgsql' => new PostgreSQLOptimizer($conn),
            'sqlite' => new SQLiteOptimizer($conn),
            default => null
        };
    }
}
