<?php

declare(strict_types=1);

namespace App\Framework\Database;

use App\Framework\Database\Migration\MigrationLoader;
use App\Framework\Database\Migration\MigrationRunner;

final class DatabaseManager
{
    private array $config;
    private ?ConnectionPool $connectionPool = null;
    private ?ReadWriteConnection $readWriteConnection = null;

    public function __construct(
        array $config = [],
        private readonly string $migrationsPath = 'database/migrations'
    ){
        $this->config = $config;
    }

    public function getConnection(): ConnectionInterface
    {
        if (isset($this->config['pool']) && $this->config['pool']['enabled']) {
            return $this->getPooledConnection();
        }

        if (isset($this->config['read_write']) && $this->config['read_write']['enabled']) {
            return $this->getReadWriteConnection();
        }

        return DatabaseFactory::createConnection($this->config);
    }

    public function getPooledConnection(): PooledConnection
    {
        if ($this->connectionPool === null) {
            $poolConfig = $this->config['pool'] ?? [];
            $this->connectionPool = new ConnectionPool(
                $this->config,
                $poolConfig['max_connections'] ?? 10,
                $poolConfig['min_connections'] ?? 2
            );
        }

        return $this->connectionPool->getConnection();
    }

    public function getReadWriteConnection(): ReadWriteConnection
    {
        if ($this->readWriteConnection === null) {
            $writeConnection = DatabaseFactory::createConnection($this->config);

            $readConnections = [];
            foreach ($this->config['read_write']['read_connections'] as $readConfig) {
                $readConnections[] = DatabaseFactory::createConnection(
                    array_merge($this->config, $readConfig)
                );
            }

            $this->readWriteConnection = new ReadWriteConnection($writeConnection, $readConnections);
        }

        return $this->readWriteConnection;
    }

    public function migrate(?string $migrationsPath = null): array
    {
        $migrationsPath = $migrationsPath ?? $this->migrationsPath;

        $loader = new MigrationLoader($migrationsPath);
        $migrations = $loader->loadMigrations();

        $runner = new MigrationRunner($this->getConnection());
        return $runner->migrate($migrations);
    }

    public function rollback(?string $migrationsPath = null, int $steps = 1): array
    {
        $migrationsPath = $migrationsPath ?? $this->migrationsPath;

        $loader = new MigrationLoader($migrationsPath);
        $migrations = $loader->loadMigrations();

        $runner = new MigrationRunner($this->getConnection());
        return $runner->rollback($migrations, $steps);
    }

    public function getMigrationStatus(?string $migrationsPath = null): array
    {
        $migrationsPath = $migrationsPath ?? $this->migrationsPath;

        $loader = new MigrationLoader($migrationsPath);
        $migrations = $loader->loadMigrations();

        $runner = new MigrationRunner($this->getConnection());
        return $runner->getStatus($migrations);
    }

    public function getConnectionPoolStats(): array
    {
        return $this->connectionPool?->getStats() ?? [];
    }
}
