<?php
// app/db/Db.php

declare(strict_types=1);

namespace ScMedia\Db;

use PDO;
use PDOException;

final class Db {
  private PDO $pdo;

  public function __construct(string $dsn, string $user, string $pass) {
    $this->pdo = new PDO($dsn, $user, $pass, [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
      PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",
    ]);
  }

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

  public function prepare(string $sql): \PDOStatement {
    return $this->pdo->prepare($sql);
  }

  public function query(string $sql): \PDOStatement {
    return $this->pdo->query($sql);
  }

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

  public function fetchOne(string $sql, array $params = []): ?array {
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute($params);
    $row = $stmt->fetch();
    return $row === false ? null : $row;
  }

  public function fetchAll(string $sql, array $params = []): array {
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute($params);
    return $stmt->fetchAll();
  }

  public function exec(string $sql, array $params = []): int {
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute($params);
    return $stmt->rowCount();
  }

  public function begin(): void {
    $this->pdo->beginTransaction();
  }

  public function beginTransaction(): void {
    $this->begin();
  }

  public function commit(): void {
    $this->pdo->commit();
  }

  public function rollBack(): void {
    if ($this->pdo->inTransaction()) {
      $this->pdo->rollBack();
    }
  }
}
