<?php

declare(strict_types=1);

namespace App\Framework\Database;


use App\Framework\Database\Exception\DatabaseException;

final class PdoConnection implements ConnectionInterface
{
    private \PDO $pdo;

    public function __construct(\PDO $pdo)
    {
        $this->pdo = $pdo;

        # SOllte bereits aus den Options kommen!
        #$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        #$this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
    }

    public function execute(string $sql, array $parameters = []): int
    {
        try {
            $statement = $this->pdo->prepare($sql);
            $statement->execute($parameters);
            return $statement->rowCount();
        } catch (\PDOException $e) {
            throw new DatabaseException("Failed to execute query: {$e->getMessage()}", 0, $e);
        }
    }

    public function query(string $sql, array $parameters = []): ResultInterface
    {
        try {
            $statement = $this->pdo->prepare($sql);
            $statement->execute($parameters);
            return new PdoResult($statement);
        } catch (\PDOException $e) {
            throw new DatabaseException("Failed to execute query: {$e->getMessage()} --- SQL: {$sql} PARAMETERS: {".implode(", ", $parameters)."}", 0, $e);
        }
    }

    public function queryOne(string $sql, array $parameters = []): ?array
    {
        $result = $this->query($sql, $parameters);
        return $result->fetch();
    }

    public function queryColumn(string $sql, array $parameters = []): array
    {
        $result = $this->query($sql, $parameters);
        return $result->fetchColumn();
    }

    public function queryScalar(string $sql, array $parameters = []): mixed
    {
        $result = $this->query($sql, $parameters);
        return $result->fetchScalar();
    }

    public function beginTransaction(): void
    {
        try {
            $this->pdo->beginTransaction();
        } catch (\PDOException $e) {
            throw new DatabaseException("Failed to begin transaction: {$e->getMessage()}", 0, $e);
        }
    }

    public function commit(): void
    {
        try {
            $this->pdo->commit();
        } catch (\PDOException $e) {
            throw new DatabaseException("Failed to commit transaction: {$e->getMessage()}", 0, $e);
        }
    }

    public function rollback(): void
    {
        try {
            $this->pdo->rollBack();
        } catch (\PDOException $e) {
            throw new DatabaseException("Failed to rollback transaction: {$e->getMessage()}", 0, $e);
        }
    }

    public function inTransaction(): bool
    {
        return $this->pdo->inTransaction();
    }

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

    public function getPdo(): \PDO
    {
        return $this->pdo;
    }
}
