<?php
/**
 * BTC Catch Miner — Database (PDO/MySQL)
 * =======================================
 * Singleton PDO wrapper.
 */

declare(strict_types=1);

class DB {
    private static ?PDO $pdo = null;

    public static function conn(): PDO {
        if (self::$pdo === null) {
            $dsn = sprintf(
                'mysql:host=%s;port=%d;dbname=%s;charset=%s',
                DB_HOST, DB_PORT, DB_NAME, DB_CHARSET
            );
            self::$pdo = new PDO($dsn, DB_USER, DB_PASS, [
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES   => false,
            ]);
        }
        return self::$pdo;
    }

    /** Execute a query and return the statement */
    public static function query(string $sql, array $params = []): PDOStatement {
        $stmt = self::conn()->prepare($sql);
        $stmt->execute($params);
        return $stmt;
    }

    /** Fetch a single row */
    public static function row(string $sql, array $params = []): ?array {
        $row = self::query($sql, $params)->fetch();
        return $row ?: null;
    }

    /** Fetch all rows */
    public static function all(string $sql, array $params = []): array {
        return self::query($sql, $params)->fetchAll();
    }

    /** Execute and return affected rows */
    public static function exec(string $sql, array $params = []): int {
        return self::query($sql, $params)->rowCount();
    }

    /** Fetch a single scalar value (first column of first row) */
    public static function val(string $sql, array $params = []): mixed {
        $row = self::query($sql, $params)->fetch(PDO::FETCH_NUM);
        return $row ? $row[0] : null;
    }

    /** Last insert ID */
    public static function lastId(): string {
        return self::conn()->lastInsertId();
    }
}
