<?php declare(strict_types=1);

class Database {

    // These constants are defined in config/config.php
    private string $host = DB_HOST;
    private string $user = DB_USER;
    private string $pass = DB_PASS;
    private string $dbname = DB_NAME;

    private ?PDO $dbh = null;
    private $stmt;

    public function __construct() {
        
        // LAYER 3 DEFENSE: Confirm token and physical gateway file existence
        $expectedToken = md5('ChristoDev_Secure_Valid_' . date('Y-m-d'));
        if (!defined('RC_CORE_SECURE') || RC_CORE_SECURE !== $expectedToken || !file_exists(dirname(__DIR__, 2) . '/public/license_check.php')) {
            error_log("Security Violation: Database Layer Tampering Detected.");
            $this->tamperLock();
        }

        // Verify the License Engine generated the required evaluation string
        if (!defined('RC_DB_DRIVER') || empty(RC_DB_DRIVER)) {
            error_log("Security Violation: Missing Core PDO Driver Logic. License bypass detected.");
            $this->tamperLock();
        }

        // LOGIC OFFLOAD: Execute the injected PHP code to instantiate the DB connection
        try {
            // The central server passes the PDO instantiation logic dynamically
            $this->dbh = eval(base64_decode(RC_DB_DRIVER));
            
            if (!$this->dbh instanceof PDO) {
                throw new Exception("Driver Instantiation Failed.");
            }
            
        } catch (PDOException $e) {
            // Standard Database Connection Error (e.g., MySQL offline, wrong password)
            // Let this bubble up to the new Global ErrorHandler to render the 500 error page
            throw new Exception("Database Connection Error: " . $e->getMessage());
            
        } catch (Throwable $e) {
            // Any other fatal error during driver eval
            throw new Exception("Logic Offload Failure: " . $e->getMessage());
        }
    }

    private function tamperLock() {
        http_response_code(403);
        $reason = "The core verification protocol has been bypassed, altered, or removed from the server.";
        $code = "SEC_TAMPER_0x3";

        echo <<<HTML
        <!DOCTYPE html>
        <html lang="en" class="dark">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>System Locked - Security Alert</title>
            <script src="https://cdn.tailwindcss.com"></script>
            <script>
                tailwind.config = { darkMode: 'class', theme: { extend: { colors: { primary: '#1c70b4', danger: '#ef4444' } } } }
            </script>
        </head>
        <body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center p-4 font-sans selection:bg-danger selection:text-white">
            <div class="max-w-lg w-full bg-gray-800 rounded-2xl shadow-2xl border border-red-900/50 p-8 relative overflow-hidden">
                <div class="absolute top-0 left-0 w-full h-1 bg-red-600 shadow-[0_0_15px_rgba(220,38,38,0.8)]"></div>
                <div class="text-center mb-6">
                    <div class="mx-auto flex items-center justify-center h-20 w-20 rounded-full bg-red-900/30 mb-6 border border-red-500/30 shadow-[0_0_20px_rgba(220,38,38,0.2)]">
                        <svg class="h-10 w-10 text-red-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg>
                    </div>
                    <h1 class="text-3xl font-extrabold text-white tracking-tight mb-2">System Locked</h1>
                    <p class="text-red-400 font-bold tracking-widest uppercase text-xs">Critical Security Violation</p>
                </div>
                <div class="bg-gray-900/80 rounded-xl p-5 border border-gray-700/50 mb-8 shadow-inner">
                    <p class="text-gray-300 text-sm leading-relaxed text-center font-medium">
                        {$reason}
                    </p>
                </div>
                
                <div class="flex flex-col gap-4">
                    <a href="https://support.christodev.co.za" target="_blank" class="w-full bg-red-600 hover:bg-red-500 text-white font-bold py-3 px-4 rounded-xl shadow-lg transition-all text-center flex items-center justify-center focus:ring-4 focus:ring-red-600/30">
                        <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
                        Need help? Contact Support
                    </a>
                </div>
                <div class="mt-8 pt-5 border-t border-gray-700/50 flex justify-between items-center text-xs text-gray-500 font-mono">
                    <span class="bg-gray-900 px-2 py-1 rounded border border-gray-800">ERR: {$code}</span>
                    <span class="flex items-center"><svg class="w-3 h-3 mr-1 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path></svg> ChristoDev Engine</span>
                </div>
            </div>
        </body>
        </html>
HTML;
        exit;
    }

    // Prepare statement with query
    public function query(string $sql): void {
        $this->stmt = $this->dbh->prepare($sql);
    }

    // Bind values safely to prevent SQL injection
    public function bind($param, $value, $type = null): void {
        if (is_null($type)) {
            switch (true) {
                case is_int($value):
                    $type = PDO::PARAM_INT;
                    break;
                case is_bool($value):
                    $type = PDO::PARAM_BOOL;
                    break;
                case is_null($value):
                    $type = PDO::PARAM_NULL;
                    break;
                default:
                    $type = PDO::PARAM_STR;
            }
        }
        $this->stmt->bindValue($param, $value, $type);
    }

    // Execute the prepared statement
    public function execute(): bool {
        try {
            return $this->stmt->execute();
        } catch (PDOException $e) {
            error_log("Query Execution Error: " . $e->getMessage());
            return false;
        }
    }

    // Get multiple records as an array of objects
    public function resultSet(): array {
        $this->execute();
        return $this->stmt->fetchAll();
    }

    // Get a single record as an object
    public function single(): object|bool {
        $this->execute();
        return $this->stmt->fetch();
    }

    // Get row count to verify records (e.g. checking if an email exists)
    public function rowCount(): int {
        return $this->stmt->rowCount();
    }
}