<?php // Vocal secours — WebRTC P2P + signalisation PHP + participants + PTT + VOX (gating via GainNode)
// Mutualisé OVH : nécessite ./data écrivable.
declare(strict_types=1);
require_once "auth/session.php";
header("X-Content-Type-Options: nosniff");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");

$DATA_DIR = __DIR__ . "/data";
if (!is_dir($DATA_DIR)) @mkdir($DATA_DIR, 0775, true);

$user = getCurrentUser();
$current_user_id = $user ? (int)$user["id"] : 0;

function room_id(string $s): string {
    $s = preg_replace("~[^a-zA-Z0-9_\-]~", "", $s);
    return $s !== "" ? $s : "secours";
}

function peer_id(): string {
    return bin2hex(random_bytes(8));
}

function room_log_file(string $room): string {
    return __DIR__ . "/data/" . $room . ".log";
}

function room_participants_file(string $room): string {
    return __DIR__ . "/data/" . $room . ".participants.json";
}

function chat_log_file_for_today(): string {
    // Un fichier par jour : YYYY-MM-DD.chat.log
    $d = date("Y-m-d");
    return __DIR__ . "/data/" . $d . ".chat.log";
}

function now_ms(): int {
    return (int) floor(microtime(true) * 1000);
}

function json_out($data, int $code = 200): void {
    http_response_code($code);
    header("Content-Type: application/json; charset=utf-8");
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function read_json_file(string $path): array {
    if (!file_exists($path)) return [];
    $raw = @file_get_contents($path);
    if ($raw === false || $raw === "") return [];
    $j = json_decode($raw, true);
    return is_array($j) ? $j : [];
}

function write_json_file(string $path, array $data): void {
    file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), LOCK_EX);
}

function tail_lines(string $path, int $maxLines = 120): array {
    if (!is_file($path)) return [];
    $fp = fopen($path, "rb");
    if (!$fp) return [];
    
    $lines = [];
    fseek($fp, 0, SEEK_END);
    $pos = ftell($fp);
    $buffer = "";
    
    while ($pos > 0 && count($lines) < $maxLines) {
        $readSize = min($pos, 4096);
        $pos -= $readSize;
        fseek($fp, $pos);
        $chunk = fread($fp, $readSize);
        $buffer = $chunk . $buffer;
        
        $chunkLines = explode("\n", $buffer);
        $buffer = array_shift($chunkLines);
        
        while (!empty($chunkLines)) {
            $line = array_pop($chunkLines);
            if (trim($line) !== "") {
                array_unshift($lines, trim($line));
                if (count($lines) >= $maxLines) break;
            }
        }
    }
    fclose($fp);
    return $lines;
}

// Logic for signaling
$action = $_REQUEST["action"] ?? "";
$room = room_id($_REQUEST["room"] ?? "secours");
$my_id = $_REQUEST["peer_id"] ?? "";

if ($action === "join") {
    $name = $_REQUEST["name"] ?? "User";
    $p_file = room_participants_file($room);
    $ps = read_json_file($p_file);
    
    // Cleanup old participants (> 10s)
    $stale_time = now_ms() - 10000;
    foreach ($ps as $id => $p) {
        if (($p["last_seen"] ?? 0) < $stale_time) unset($ps[$id]);
    }
    
    $new_id = peer_id();
    $ps[$new_id] = [
        "id" => $new_id,
        "user_id" => $current_user_id,
        "name" => $name,
        "avatar_url" => $user["avatar_url"] ?? "",
        "last_seen" => now_ms()
    ];
    write_json_file($p_file, $ps);
    
    // DB Integration for sidebar
    if ($current_user_id > 0) {
        try {
            $stmt = db()->prepare("INSERT INTO voice_sessions (user_id, channel_id, last_seen) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE channel_id = ?, last_seen = ?");
            $stmt->execute([$current_user_id, $room, now_ms(), $room, now_ms()]);
        } catch (Exception $e) {}
    }
    
    json_out(["success" => true, "peer_id" => $new_id, "participants" => $ps]);
}

if ($action === "poll") {
    if (!$my_id) json_out(["error" => "Missing peer_id"], 400);
    $p_file = room_participants_file($room);
    $ps = read_json_file($p_file);
    
    if (isset($ps[$my_id])) {
        $ps[$my_id]["last_seen"] = now_ms();
    }
    
    $stale_time = now_ms() - 10000;
    foreach ($ps as $id => $p) {
        if (($p["last_seen"] ?? 0) < $stale_time) unset($ps[$id]);
    }
    write_json_file($p_file, $ps);

    // Update DB last_seen
    if ($current_user_id > 0) {
        try {
            $stmt = db()->prepare("UPDATE voice_sessions SET last_seen = ? WHERE user_id = ?");
            $stmt->execute([now_ms(), $current_user_id]);
        } catch (Exception $e) {}
    }
    
    // Read signals
    $log_file = room_log_file($room);
    $signals = [];
    if (file_exists($log_file)) {
        $lines = file($log_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $remaining = [];
        $now = now_ms();
        foreach ($lines as $line) {
            $sig = json_decode($line, true);
            if ($sig && isset($sig["to"]) && $sig["to"] === $my_id) {
                $signals[] = $sig;
            } elseif ($sig && ($now - ($sig["time"] ?? 0) < 30000)) {
                $remaining[] = $line;
            }
        }
        file_put_contents($log_file, implode("\n", $remaining) . (empty($remaining) ? "" : "\n"), LOCK_EX);
    }
    
    json_out(["success" => true, "participants" => $ps, "signals" => $signals]);
}

if ($action === "signal") {
    if (!$my_id) json_out(["error" => "Missing peer_id"], 400);
    $to = $_REQUEST["to"] ?? "";
    $data = $_REQUEST["data"] ?? "";
    if (!$to || !$data) json_out(["error" => "Missing to/data"], 400);
    
    $sig = [
        "from" => $my_id,
        "to" => $to,
        "data" => json_decode($data, true),
        "time" => now_ms()
    ];
    
    file_put_contents(room_log_file($room), json_encode($sig) . "\n", FILE_APPEND | LOCK_EX);
    json_out(["success" => true]);
}

if ($action === "list_all") {
    // Periodic cleanup of the DB table (stale sessions > 15s)
    if (rand(1, 10) === 1) {
        try {
            $stale_db_time = now_ms() - 15000;
            $stmt = db()->prepare("DELETE FROM voice_sessions WHERE last_seen < ?");
            $stmt->execute([$stale_db_time]);
        } catch (Exception $e) {}
    }

    try {
        $stmt = db()->prepare("
            SELECT vs.channel_id, vs.user_id, u.username, u.display_name, u.avatar_url 
            FROM voice_sessions vs
            JOIN users u ON vs.user_id = u.id
            WHERE vs.last_seen > ?
        ");
        $stale_db_time = now_ms() - 15000;
        $stmt->execute([$stale_db_time]);
        $sessions = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $by_channel = [];
        foreach ($sessions as $s) {
            $by_channel[$s['channel_id']][] = $s;
        }
        json_out(["success" => true, "channels" => $by_channel]);
    } catch (Exception $e) {
        json_out(["error" => $e->getMessage()], 500);
    }
}

if ($action === "leave") {
    if ($my_id) {
        $p_file = room_participants_file($room);
        $ps = read_json_file($p_file);
        unset($ps[$my_id]);
        write_json_file($p_file, $ps);
    }
    if ($current_user_id > 0) {
        try {
            $stmt = db()->prepare("DELETE FROM voice_sessions WHERE user_id = ?");
            $stmt->execute([$current_user_id]);
        } catch (Exception $e) {}
    }
    json_out(["success" => true]);
}

json_out(["error" => "Unknown action"], 404);