<?php

declare(strict_types=1);

namespace App\Core;

use PDO;

final class SchemaInspector
{
    /**
     * Request-level schema cache.
     *
     * Reports hub and menus check permissions many times on the same request.
     * RBAC checks ask whether roles/permissions tables exist; without caching this
     * turns into hundreds of INFORMATION_SCHEMA queries.
     *
     * @var array<string,bool>
     */
    private static array $tableExistsCache = [];

    /** @var array<string,bool> */
    private static array $columnExistsCache = [];

    public static function tableExists(PDO $pdo, string $table): bool
    {
        $key = strtolower(trim($table));
        if ($key !== '' && array_key_exists($key, self::$tableExistsCache)) {
            return self::$tableExistsCache[$key];
        }

        $st = $pdo->prepare('SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? LIMIT 1');
        $st->execute([$table]);
        $exists = (bool) $st->fetchColumn();

        if ($key !== '') {
            self::$tableExistsCache[$key] = $exists;
        }
        return $exists;
    }

    public static function columnExists(PDO $pdo, string $table, string $column): bool
    {
        $key = strtolower(trim($table)) . '.' . strtolower(trim($column));
        if ($key !== '.' && array_key_exists($key, self::$columnExistsCache)) {
            return self::$columnExistsCache[$key];
        }

        $st = $pdo->prepare('SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1');
        $st->execute([$table, $column]);
        $exists = (bool) $st->fetchColumn();

        if ($key !== '.') {
            self::$columnExistsCache[$key] = $exists;
        }
        return $exists;
    }

    public static function tableHasColumn(PDO $pdo, string $table, string $column): bool
    {
        return self::columnExists($pdo, $table, $column);
    }

    public static function ensureColumn(PDO $pdo, string $table, string $column, string $definitionSql): void
    {
        if (!self::columnExists($pdo, $table, $column)) {
            $pdo->exec("ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definitionSql}");
        }
    }
}
