<?php

declare(strict_types=1);

namespace App\Core;

use InvalidArgumentException;
use PDO;
use Throwable;

final class SchemaRuntime
{
    private static array $executed = [];
    private static array $warnings = [];
    private static array $requested = [];

    public static function ensure(PDO $pdo, string $key, callable $callback, ?string $migrationHint = null): void
    {
        self::$requested[$key] = [
            'key' => $key,
            'migration' => $migrationHint,
            'requested_at' => date('c'),
        ];

        if (isset(self::$executed[$key])) {
            return;
        }

        self::$executed[$key] = true;

        if (!self::runtimePatchesAllowed()) {
            throw new InvalidArgumentException(
                self::disabledMessage($migrationHint)
            );
        }

        try {
            $callback();
            self::warnOnce($key, $migrationHint);
        } catch (Throwable $e) {
            throw $e;
        }
    }

    public static function ensureMany(PDO $pdo, array $operations): void
    {
        foreach ($operations as $operation) {
            self::ensure(
                $pdo,
                (string) ($operation['key'] ?? 'unknown'),
                $operation['callback'] ?? static function (): void {},
                $operation['migration'] ?? null
            );
        }
    }

    public static function runtimePatchesAllowed(): bool
    {
        return Config::get('app.runtime_schema_patches', true);
    }

    public static function warnings(): array
    {
        return array_values(self::$warnings);
    }

    public static function requested(): array
    {
        return array_values(self::$requested);
    }

    public static function statusReport(): array
    {
        $manifest = SchemaManifest::byKey();
        $report = [];

        foreach (self::$requested as $key => $row) {
            $meta = $manifest[$key] ?? [];
            $report[] = [
                'key' => $key,
                'migration' => $row['migration'] ?? ($meta['migration'] ?? null),
                'module' => $meta['module'] ?? 'unknown',
                'description' => $meta['description'] ?? '',
                'executed' => isset(self::$executed[$key]),
                'warning' => self::$warnings[$key] ?? null,
            ];
        }

        return $report;
    }

    private static function warnOnce(string $key, ?string $migrationHint): void
    {
        if (isset(self::$warnings[$key])) {
            return;
        }

        $message = 'Runtime schema patch executed: ' . $key;
        if ($migrationHint) {
            $message .= ' | preferred migration: ' . $migrationHint;
        }

        self::$warnings[$key] = $message;
        error_log('[schema-runtime] ' . $message);
    }

    private static function disabledMessage(?string $migrationHint): string
    {
        $message = 'تم تعطيل تعديلات قاعدة البيانات أثناء التشغيل. '; 
        if ($migrationHint) {
            $message .= 'شغّل ملف التحديث: ' . $migrationHint;
        } else {
            $message .= 'شغّل ملفات الـ migrations المطلوبة أولًا.';
        }

        return $message;
    }
}
