<?php

declare(strict_types=1);

namespace System\Database;

use PDO;
use PDOException;
use RuntimeException;
use System\Contracts\DatabaseInterface;

final class Database implements DatabaseInterface
{
    private ?PDO $connection = null;

    public function connect(): PDO
    {
        if ($this->connection instanceof PDO) {
            return $this->connection;
        }

        $dsn = sprintf(
            '%s:host=%s;port=%s;dbname=%s;charset=utf8mb4',
            config('database.default'),
            config('database.host'),
            config('database.port'),
            config('database.database')
        );

        try {

            $this->connection = new PDO(
                $dsn,
                config('database.username'),
                config('database.password'),
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ]
            );

        } catch (PDOException $exception) {

            throw new RuntimeException(
                'Database connection failed: ' . $exception->getMessage()
            );
        }

        return $this->connection;
    }

    public function getConnection(): PDO
    {
        return $this->connect();
    }

    public function disconnect(): void
    {
        $this->connection = null;
    }

    public function isConnected(): bool
    {
        return $this->connection instanceof PDO;
    }
}