<?php
// /docker/whp/web/libs/customer_state.php
// Customer container state file helpers. Single source of truth for whether
// a customer container should be running.

const WHP_STATE_FILE = '/var/lib/whp/customer-state.json';
const WHP_STATE_LOCK = '/var/lib/whp/customer-state.lock';

function whp_state_init(): void {
    $dir = dirname(WHP_STATE_FILE);
    if (!is_dir($dir)) { @mkdir($dir, 0755, true); }
    if (!file_exists(WHP_STATE_FILE)) {
        @file_put_contents(WHP_STATE_FILE, "{}\n");
        @chmod(WHP_STATE_FILE, 0640);
    }
    if (!file_exists(WHP_STATE_LOCK)) {
        @touch(WHP_STATE_LOCK);
        @chmod(WHP_STATE_LOCK, 0640);
    }
}

function whp_state_read(): array {
    whp_state_init();
    $raw = @file_get_contents(WHP_STATE_FILE);
    if ($raw === false || $raw === '') return [];
    $data = json_decode($raw, true);
    return is_array($data) ? $data : [];
}

// Read-modify-write under flock. $mutator receives the current array and
// returns the new array. Returns true on success, false on lock failure or
// write failure.
function whp_state_modify(callable $mutator): bool {
    whp_state_init();
    $fp = fopen(WHP_STATE_LOCK, 'c');
    if (!$fp) return false;
    try {
        if (!flock($fp, LOCK_EX | LOCK_NB)) {
            // Block up to 5s
            $deadline = microtime(true) + 5.0;
            while (microtime(true) < $deadline) {
                if (flock($fp, LOCK_EX | LOCK_NB)) break;
                usleep(50000);
            }
            if (!flock($fp, LOCK_EX | LOCK_NB)) return false;
        }
        $raw = @file_get_contents(WHP_STATE_FILE);
        $data = ($raw !== false && $raw !== '') ? json_decode($raw, true) : [];
        if (!is_array($data)) $data = [];
        $new = $mutator($data);
        if (!is_array($new)) return false;
        $tmp = WHP_STATE_FILE . '.tmp.' . getmypid();
        $payload = json_encode($new, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        if ($payload === false) return false;
        if (file_put_contents($tmp, $payload) === false) return false;
        @chmod($tmp, 0640);
        if (!rename($tmp, WHP_STATE_FILE)) return false;
        return true;
    } finally {
        @flock($fp, LOCK_UN);
        @fclose($fp);
    }
}

function whp_state_get(string $container): array {
    $all = whp_state_read();
    return $all[$container] ?? [
        'autostart' => true,
        'disabled_reason' => null,
        'disabled_at' => null,
        'disabled_by' => null,
    ];
}

function whp_state_autostart(string $container): bool {
    $entry = whp_state_get($container);
    $v = $entry['autostart'] ?? true;
    return $v === true || $v === 'true';
}
