<?php

declare(strict_types=1);

namespace System\Application;

use App\Repositories\MigrationRepository;
use System\Contracts\ApplicationInterface;
use System\Contracts\DatabaseInterface;
use System\Database\Database;
use System\Database\QueryBuilder;
use System\Http\Request;
use System\Http\Response;
use System\Migration\MigrationManager;
use System\Routing\Dispatcher;
use System\Routing\Router;
use System\View\View;
final class Application implements ApplicationInterface
{
    private string $version = '1.0.0';

    private float $startTime;

    private Container $container;

    public function __construct()
    {
        $this->startTime = microtime(true);

        $this->container = new Container();

        $this->registerCoreServices();
    }

    private function registerCoreServices(): void
    {
        $this->container->singleton(
            self::class,
            $this
        );
$this->container->singleton(
    View::class,
    fn() => new View()
);
$this->container->singleton(
    View::class,
    fn() => new View()
);
$this->container->singleton(
    \System\Migration\MigrationRunner::class,
    function ($container) {

        return new \System\Migration\MigrationRunner(

            $container->make(
                \System\Contracts\DatabaseInterface::class
            )

        );

    }
);
        $this->container->singleton(
            Container::class,
            $this->container
        );

$this->container->singleton(
    Database::class,
    Database::class
);

$this->container->singleton(
    DatabaseInterface::class,
    fn($container) => $container->make(Database::class)
);

        $this->container->singleton(
            QueryBuilder::class,
            fn($container) => new QueryBuilder(
                $container->make(DatabaseInterface::class)
            )
        );

        $this->container->singleton(
            MigrationManager::class,
            fn($container) => new MigrationManager(
                $container->make(DatabaseInterface::class)
            )
        );

        $this->container->singleton(
            MigrationRepository::class,
            fn($container) => new MigrationRepository(
                $container->make(QueryBuilder::class)
            )
        );

        $this->container->singleton(
            Router::class,
            fn() => new Router()
        );

$this->container->singleton(
    Dispatcher::class,
    fn($container) => new Dispatcher(
        $container->make(Container::class)
    )
);

        $this->container->singleton(
            Request::class,
            fn() => new Request()
        );

        $this->container->singleton(
            Response::class,
            fn() => new Response()
        );
    }

    public function container(): Container
    {
        return $this->container;
    }

    public function version(): string
    {
        return $this->version;
    }

    public function environment(): string
    {
        return env('APP_ENV', 'production');
    }

    public function debug(): bool
    {
        return filter_var(
            env('APP_DEBUG', false),
            FILTER_VALIDATE_BOOLEAN
        );
    }

    public function uptime(): float
    {
        return microtime(true) - $this->startTime;
    }
}