<?php
require_once __DIR__ . '/helpers/functions.php';

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

    public static function connection(): PDO
    {
        if (self::$pdo === null) {
            $dsn = sprintf(
                'mysql:host=%s;port=%d;dbname=%s;charset=%s',
                config('db.host'),
                config('db.port'),
                config('db.database'),
                config('db.charset', 'utf8mb4')
            );
            try {
                self::$pdo = new PDO($dsn, config('db.username'), config('db.password'), [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                ]);
            } catch (PDOException $e) {
                throw new PDOException($e->getMessage(), (int)$e->getCode(), $e);
            }
        }
        return self::$pdo;
    }
}

abstract class Model
{
    protected PDO $db;

    public function __construct()
    {
        $this->db = Database::connection();
    }
}

abstract class Controller
{
    protected function view(string $view, array $data = [], string $layout = 'default'): void
    {
        extract($data);
        $viewFile = __DIR__ . '/views/' . $view . '.php';
        if ($layout === 'auth') {
            include __DIR__ . '/views/layouts/auth_header.php';
            include $viewFile;
            include __DIR__ . '/views/layouts/auth_footer.php';
            return;
        }
        include __DIR__ . '/views/layouts/header.php';
        include $viewFile;
        include __DIR__ . '/views/layouts/footer.php';
    }

    protected function json(array $payload, int $status = 200): void
    {
        http_response_code($status);
        header('Content-Type: application/json');
        echo json_encode($payload);
        exit;
    }

    protected function isPost(): bool
    {
        return ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST';
    }
}
