<?php
namespace App;

use PDO;
use PDOException;

final class DB
{
    /** @var PDO|null */
    private static $pdo = null;

    /** اتصال PDO واحد (singleton) */
    public static function pdo()
    {
        if (self::$pdo instanceof PDO) return self::$pdo;

        $host    = Env::get('DB_HOST', '127.0.0.1');
        $port    = Env::get('DB_PORT', '3306');
        $name    = Env::get('DB_NAME', 'bot_db');
        $charset = Env::get('DB_CHARSET', 'utf8mb4');
        $user    = Env::get('DB_USER', 'root');
        $pass    = Env::get('DB_PASS', '');
        $socket  = Env::get('DB_SOCKET'); // اختیاری: اگر روی یونیکس‌سوکت هستی

        // DSN سازگار
        if ($socket) {
            $dsn = "mysql:unix_socket={$socket};dbname={$name};charset={$charset}";
        } else {
            $dsn = "mysql:host={$host};port={$port};dbname={$name};charset={$charset}";
        }

        $options = [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES   => false,
            PDO::ATTR_TIMEOUT            => 5,
        ];

        try {
            $pdo = new PDO($dsn, $user, $pass, $options);
            // برای اطمینان از کُدپیج
            $pdo->exec("SET NAMES {$charset}");
        } catch (PDOException $e) {
            error_log('[DB] connect error: ' . $e->getMessage());
            throw $e;
        }

        self::$pdo = $pdo;
        return self::$pdo;
    }

    /**
     * اجرای امن داخل تراکنش
     * usage:
     * DB::tx(function(PDO $pdo){ ... return $result; });
     */
    public static function tx($fn)
    {
        $pdo = self::pdo();
        try {
            $pdo->beginTransaction();
            $out = $fn($pdo);
            $pdo->commit();
            return $out;
        } catch (PDOException $e) {
            if ($pdo->inTransaction()) $pdo->rollBack();
            throw $e;
        }
    }

    /** بستن اتصال (اختیاری) */
    public static function close()
    {
        self::$pdo = null;
    }
}
