<?php

namespace classes;

use RuntimeException;
use Throwable;

class replication_bootstrap_config
{
    public static function snapshotPath(): string
    {
        return self::storageDir() . DIRECTORY_SEPARATOR . 'replication-bootstrap.json';
    }

    public static function loadSnapshot(?string $path = null): array
    {
        $path = $path ?: self::snapshotPath();
        if (!is_file($path) || !is_readable($path)) {
            return [];
        }

        $decoded = json_decode((string)file_get_contents($path), true);
        return is_array($decoded) ? $decoded : [];
    }

    public static function writeSnapshot(array $snapshot, ?string $path = null): void
    {
        $path = $path ?: self::snapshotPath();
        $dir = dirname($path);
        if (!is_dir($dir) && !mkdir($dir, 0770, true) && !is_dir($dir)) {
            throw new RuntimeException('Could not create replication bootstrap snapshot directory.');
        }

        $snapshot = array_replace([
            'version' => 1,
            'generated_at' => date('c'),
        ], $snapshot);

        $json = json_encode($snapshot, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        if ($json === false) {
            throw new RuntimeException('Could not encode replication bootstrap snapshot.');
        }

        $tempPath = tempnam($dir, 'replication-bootstrap-');
        if ($tempPath === false) {
            throw new RuntimeException('Could not create replication bootstrap snapshot temp file.');
        }

        try {
            if (file_put_contents($tempPath, $json . PHP_EOL, LOCK_EX) === false) {
                throw new RuntimeException('Could not write replication bootstrap snapshot.');
            }

            if (!rename($tempPath, $path)) {
                throw new RuntimeException('Could not atomically replace replication bootstrap snapshot.');
            }
        } finally {
            if (is_file($tempPath)) {
                @unlink($tempPath);
            }
        }
    }

    public static function applyToGlobals(array $snapshot): void
    {
        try {
            $active = is_array($snapshot['active'] ?? null) ? $snapshot['active'] : [];
            $database = self::activeDatabaseConfigFromSnapshot($active['database'] ?? null);
            $redis = self::activeRedisConfigFromSnapshot($active['redis'] ?? null);
            $minio = self::activeMinioConfigFromSnapshot($active['minio'] ?? null);

            if ($database !== null) {
                $GLOBALS['CONFIG_DB'] = array_merge($GLOBALS['CONFIG_DB'] ?? [], $database);
            }

            if ($redis !== null) {
                $GLOBALS['REDIS_CONFIG'] = array_merge($GLOBALS['REDIS_CONFIG'] ?? [], $redis);
            }

            if ($minio !== null) {
                $GLOBALS['MINIO'] = array_merge($GLOBALS['MINIO'] ?? [], $minio);
            }
        } catch (Throwable $throwable) {
            error_log('[replication-bootstrap] Falling back to environment configuration: ' . $throwable->getMessage());
        }
    }

    public static function activeDatabaseConfigFromSnapshot(mixed $config): ?array
    {
        if (!is_array($config)) {
            return null;
        }

        $host = trim((string)($config['host'] ?? ''));
        $database = trim((string)($config['database'] ?? ''));
        $user = trim((string)($config['user'] ?? ''));
        if ($host === '' || $database === '' || $user === '') {
            return null;
        }

        return [
            'host' => $host,
            'user' => $user,
            'password' => replication_secret_box::decrypt($config['password_secret'] ?? ''),
            'database' => $database,
            'port' => (int)($config['port'] ?? 3306) ?: 3306,
            'ssl_mode' => (string)($config['ssl_mode'] ?? 'DISABLED'),
        ];
    }

    public static function activeRedisConfigFromSnapshot(mixed $config): ?array
    {
        if (!is_array($config)) {
            return null;
        }

        $host = trim((string)($config['host'] ?? ''));
        if ($host === '') {
            return null;
        }

        return [
            'host' => $host,
            'user' => (string)($config['user'] ?? ''),
            'password' => replication_secret_box::decrypt($config['password_secret'] ?? ''),
            'database' => (int)($config['database'] ?? 0),
            'port' => (int)($config['port'] ?? 6379) ?: 6379,
        ];
    }

    public static function activeMinioConfigFromSnapshot(mixed $config): ?array
    {
        if (!is_array($config)) {
            return null;
        }

        $endpoint = trim((string)($config['endpoint'] ?? ''));
        $accessKey = trim((string)($config['access_key'] ?? $config['user'] ?? ''));
        if ($endpoint === '' || $accessKey === '') {
            return null;
        }

        return [
            'endpoint' => $endpoint,
            'access_key' => $accessKey,
            'secret_key' => replication_secret_box::decrypt($config['secret_key_secret'] ?? $config['password_secret'] ?? ''),
            'buckets' => is_array($config['buckets'] ?? null) ? array_values($config['buckets']) : ($config['buckets'] ?? null),
        ];
    }

    private static function storageDir(): string
    {
        $root = defined('WD') ? WD : dirname(__DIR__);
        return $root . DIRECTORY_SEPARATOR . 'storage';
    }
}
