<?php
// Partnership page data helpers

require_once __DIR__ . '/config.php';
require_once __DIR__ . '/arrs.php';   // vv_arr_known_hosts(), vv_arr_scalar()

// ── Config ────────────────────────────────────────────────────────────────────

function vv_pt_config(): array {
    $v = vv_conf_vars();
    return [
        'enabled'           => ($v['PARTNERSHIP_ENABLED']          ?? 'false') === 'true',
        'owner_host'        => $v['PARTNERSHIP_OWNER_HOST']         ?? '',
        'sync_min'          => (int)($v['PARTNERSHIP_SYNC_INTERVAL']   ?? 15),
        'grace_hours'       => (int)($v['PARTNERSHIP_GRACE_HOURS']     ?? 6),
        'offline_threshold' => (int)($v['PARTNERSHIP_OFFLINE_THRESHOLD'] ?? 30),
        'remove_tailscale'  => ($v['PARTNERSHIP_REMOVE_TAILSCALE']  ?? 'true') === 'true',
        'folderview3'       => ($v['PARTNERSHIP_FOLDERVIEW3']       ?? 'false') === 'true',
        'tailscale_configured' => !empty($v['TAILSCALE_API_KEY']) && !empty($v['TAILSCALE_TAILNET']),
    ];
}

// ── State file parser ─────────────────────────────────────────────────────────

function vv_pt_read_db(string $path): array {
    if (!file_exists($path)) return [];
    $out = [];
    foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
        [$k, $v] = array_pad(explode('=', trim($line), 2), 2, '');
        if ($k) $out[trim($k)] = trim($v, '"\'');
    }
    return $out;
}

// ── Tailscale peers ───────────────────────────────────────────────────────────

function vv_pt_ts_peers(): array {
    $raw   = shell_exec('tailscale status --json 2>/dev/null') ?: '{}';
    $data  = json_decode($raw, true) ?: [];
    $peers = [];

    // Self
    $self = $data['Self'] ?? [];
    $selfLabel = strtolower(explode('.', $self['DNSName'] ?? '')[0]);
    if ($selfLabel) {
        $peers[$selfLabel] = [
            'online' => true,
            'active' => true,
            'ip'     => $self['TailscaleIPs'][0] ?? null,
        ];
    }

    // Peers
    foreach ($data['Peer'] ?? [] as $peer) {
        $label = strtolower(explode('.', $peer['DNSName'] ?? '')[0]);
        if (!$label) continue;
        $peers[$label] = [
            'online' => (bool)($peer['Online'] ?? false),
            'active' => (bool)($peer['Active'] ?? false),
            'ip'     => $peer['TailscaleIPs'][0] ?? null,
        ];
    }
    return $peers;
}

// ── SSH helper — run a single command on a remote host ────────────────────────

function vv_pt_ssh(string $ip, string $sshKey, string $cmd, int $timeout = 4): string {
    if (!$ip || !$sshKey || !file_exists($sshKey)) return '';
    $full = sprintf(
        'ssh -i %s -o ConnectTimeout=%d -o StrictHostKeyChecking=no -o BatchMode=yes root@%s %s 2>/dev/null',
        escapeshellarg($sshKey), $timeout, escapeshellarg($ip), escapeshellarg($cmd)
    );
    return shell_exec($full) ?: '';
}

// ── System info ───────────────────────────────────────────────────────────────

function vv_pt_local_system(): array {
    $ver = '';
    if (file_exists('/etc/unraid-version')) {
        preg_match('/VERSION="([^"]+)"/', file_get_contents('/etc/unraid-version'), $m);
        $ver = $m[1] ?? '';
    }
    $uptime = 0;
    if (file_exists('/proc/uptime')) {
        $uptime = (int)explode(' ', file_get_contents('/proc/uptime'))[0];
    }
    return ['unraid_version' => $ver, 'uptime_sec' => $uptime];
}

function vv_pt_remote_system(string $ip, string $sshKey): array {
    $out = vv_pt_ssh($ip, $sshKey,
        'printf "%s\nUPTIME:%s\n" "$(cat /etc/unraid-version 2>/dev/null)" "$(cat /proc/uptime 2>/dev/null)"');
    $ver = '';
    preg_match('/VERSION="([^"]+)"/', $out, $m);
    if ($m) $ver = $m[1];
    $uptime = 0;
    if (preg_match('/UPTIME:([\d.]+)/', $out, $m)) $uptime = (int)$m[1];
    return ['unraid_version' => $ver, 'uptime_sec' => $uptime];
}

// ── Per-node data ─────────────────────────────────────────────────────────────

function vv_pt_nodes(): array {
    $currentHost = vv_detect_host();
    $hosts       = vv_arr_known_hosts();        // ['host1' => 'hostname', ...]
    $vars        = vv_conf_vars();
    $tsPeers     = vv_pt_ts_peers();
    $ownerSlot   = strtolower($vars['PARTNERSHIP_OWNER_HOST'] ?? '');

    // SSH key for this host
    $myId     = strtoupper($currentHost);
    $myRaw    = vv_read_conf_raw($currentHost . '.conf');
    $mySshKey = vv_arr_scalar($myRaw, $myId . '_SSH_KEY');

    $nodes = [];
    foreach ($hosts as $slot => $hostname) {
        $isMe    = ($slot === $currentHost || $currentHost === 'unknown');
        $isOwner = (strtolower($ownerSlot) === $slot);

        // Tailscale
        $tsLabel = strtolower($hostname);
        $ts = $tsPeers[$tsLabel] ?? ['online' => null, 'active' => false, 'ip' => null];

        // Fallback state
        $fbState = 'UNKNOWN';
        $fbPath  = '/boot/config/fallback_state.db';
        if ($isMe) {
            $fb = vv_pt_read_db($fbPath);
            $fbState = $fb['state'] ?? 'UNKNOWN';
        } elseif ($ts['online'] && $ts['ip'] && $mySshKey) {
            $out = vv_pt_ssh($ts['ip'], $mySshKey, 'cat /boot/config/fallback_state.db 2>/dev/null');
            if ($out) {
                $fb = [];
                foreach (explode("\n", $out) as $line) {
                    [$k, $v] = array_pad(explode('=', trim($line), 2), 2, '');
                    if ($k) $fb[trim($k)] = trim($v, '"\'');
                }
                $fbState = $fb['state'] ?? 'UNKNOWN';
            }
        }

        // Partnership DB — local only (each server writes its own)
        $dbPath = "/boot/config/partnership_{$hostname}.db";
        $ptDb   = vv_pt_read_db($dbPath);

        // System info
        $system = $isMe
            ? vv_pt_local_system()
            : ($ts['online'] && $ts['ip'] && $mySshKey ? vv_pt_remote_system($ts['ip'], $mySshKey) : []);

        $nodes[] = [
            'slot'        => $slot,
            'id'          => strtoupper($slot),
            'hostname'    => $hostname,
            'is_me'       => $isMe,
            'is_owner'    => $isOwner,
            'ts_online'   => $ts['online'],
            'ts_active'   => $ts['active'],
            'ts_ip'       => $ts['ip'],
            'fallback'    => $fbState,
            'partnership' => $ptDb,
            'system'      => $system,
        ];
    }
    return $nodes;
}

// ── Entry point ───────────────────────────────────────────────────────────────

function vv_partnership_all(): array {
    return [
        'config' => vv_pt_config(),
        'nodes'  => vv_pt_nodes(),
        'ts'     => time(),
    ];
}
