<?php
/**
 * Flexia — identificador de instancia/instalación (sobrevive formateos).
 * Permite que los navegadores detecten una nueva instalación y borren persistencia local obsoleta.
 */
declare(strict_types=1);

const ANTARA_FLEXIA_INSTANCE_BASENAME = 'flexia_instance.json';

/**
 * @return string Ruta absoluta a storage/config/flexia_instance.json
 */
function antara_flexia_instance_path(): string
{
    if (!defined('ANTARA_ROOT')) {
        define('ANTARA_ROOT', dirname(__DIR__));
    }
    require_once ANTARA_ROOT . '/core/security/paths.php';
    AntaraPaths::ensureDirs();

    return AntaraPaths::config() . DIRECTORY_SEPARATOR . ANTARA_FLEXIA_INSTANCE_BASENAME;
}

/**
 * @return array{generation:string,format_count:int,created_at:string,updated_at:string,reason?:string}|null
 */
function antara_flexia_read_instance_raw(): ?array
{
    $path = antara_flexia_instance_path();
    if (!is_file($path)) {
        return null;
    }
    $raw = @file_get_contents($path);
    if ($raw === false || $raw === '') {
        return null;
    }
    $data = json_decode($raw, true);
    if (!is_array($data) || empty($data['generation']) || !is_string($data['generation'])) {
        return null;
    }

    return $data;
}

/**
 * @return string UUID v4
 */
function antara_flexia_new_generation_id(): string
{
    $bytes = random_bytes(16);
    $bytes[6] = chr(ord($bytes[6]) & 0x0f | 0x40);
    $bytes[8] = chr(ord($bytes[8]) & 0x3f | 0x80);

    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}

/**
 * @param array{generation:string,format_count:int,created_at:string,updated_at:string,reason?:string} $payload
 */
function antara_flexia_write_instance(array $payload): bool
{
    require_once ANTARA_ROOT . '/includes/settings_helpers.php';
    $path = antara_flexia_instance_path();
    $dir = dirname($path);
    if (!is_dir($dir) && !@mkdir($dir, 0755, true)) {
        return false;
    }
    $json = json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($json === false) {
        return false;
    }

    return grid_atomic_write_file($path, $json . "\n");
}

/**
 * Crea el fichero de instancia si no existe (migración de instalaciones previas).
 *
 * @return array{generation:string,format_count:int,created_at:string,updated_at:string,reason?:string}
 */
function antara_flexia_ensure_instance(string $reason = 'bootstrap'): array
{
    $existing = antara_flexia_read_instance_raw();
    if ($existing !== null) {
        return $existing;
    }
    require_once __DIR__ . '/install_checks.php';
    $formatCount = antara_install_read_format_count();

    return antara_flexia_regenerate_instance($reason, $formatCount);
}

/**
 * Genera un nuevo identificador de instancia (formateo o instalación completada).
 *
 * @return array{generation:string,format_count:int,created_at:string,updated_at:string,reason?:string}
 */
function antara_flexia_regenerate_instance(string $reason, ?int $formatCount = null): array
{
    if ($formatCount === null) {
        require_once __DIR__ . '/install_checks.php';
        $formatCount = antara_install_read_format_count();
    }
    $now = gmdate('c');
    $prev = antara_flexia_read_instance_raw();
    $payload = [
        'generation' => antara_flexia_new_generation_id(),
        'format_count' => max(0, $formatCount),
        'created_at' => is_array($prev) && isset($prev['created_at']) ? (string) $prev['created_at'] : $now,
        'updated_at' => $now,
        'reason' => $reason,
    ];
    antara_flexia_write_instance($payload);

    return $payload;
}

/**
 * Datos mínimos para el cliente (null si no hay evidencia de instancia en servidor).
 *
 * @return array{generation:string,formatCount:int}|null
 */
function antara_flexia_instance_for_client(): ?array
{
    if (!is_file(antara_flexia_instance_path())) {
        require_once __DIR__ . '/install_public.php';
        if (!antara_install_is_locked()) {
            return null;
        }
    }
    $inst = antara_flexia_ensure_instance('bootstrap');

    return [
        'generation' => (string) $inst['generation'],
        'formatCount' => max(0, (int) ($inst['format_count'] ?? 0)),
    ];
}

/**
 * Emite window.FLEXIA_INSTANCE en HTML (script inline, antes de otros JS).
 */
function antara_flexia_emit_instance_script(): void
{
    $payload = antara_flexia_instance_for_client();
    if ($payload === null) {
        return;
    }
    $jsonFlags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT;
    echo '<script>window.FLEXIA_INSTANCE=' . json_encode($payload, $jsonFlags) . ';</script>' . "\n";
}
