<?php
declare(strict_types=1);

require_once __DIR__ . '/bootstrap.php';
require_once __DIR__ . '/admin_auth_lib.php';

mocker_admin_require_permission('chat');

require_once __DIR__ . '/db.php';
require_once __DIR__ . '/admin_audit_lib.php';

try {
    $pdo = mocker_db();
} catch (Throwable $e) {
    http_response_code(503);
    echo json_encode(['ok' => false, 'error' => 'db', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));

if ($method === 'GET') {
    $systemUid = mocker_chat_system_user_id($pdo);
    $st = $pdo->query(
        'SELECT m.id, m.user_id, m.body, m.created_at, m.deleted_at, m.deleted_by_operator_id, m.posted_by_operator_id,
                u.username
         FROM chat_messages m
         INNER JOIN users u ON u.id = m.user_id
         ORDER BY m.id DESC
         LIMIT 300'
    );
    $rows = $st->fetchAll(PDO::FETCH_ASSOC);
    $messages = [];
    foreach ($rows as $r) {
        $delAt = isset($r['deleted_at']) ? (int) $r['deleted_at'] : 0;
        $messages[] = [
            'id' => (int) $r['id'],
            'userId' => (int) $r['user_id'],
            'username' => (string) $r['username'],
            'displayName' => mocker_chat_display_name($pdo, [
                'username' => (string) $r['username'],
                'user_id' => (int) $r['user_id'],
                'posted_by_operator_id' => isset($r['posted_by_operator_id']) ? (int) $r['posted_by_operator_id'] : null,
            ]),
            'body' => (string) $r['body'],
            'createdAt' => (int) $r['created_at'],
            'deleted' => $delAt > 0,
            'deletedAt' => $delAt > 0 ? $delAt : null,
            'deletedByOperatorId' => isset($r['deleted_by_operator_id']) && (int) $r['deleted_by_operator_id'] > 0
                ? (int) $r['deleted_by_operator_id']
                : null,
            'fromManagement' => (isset($r['posted_by_operator_id']) && (int) $r['posted_by_operator_id'] > 0)
                || (int) $r['user_id'] === $systemUid,
        ];
    }
    $messages = array_reverse($messages);

    $muteRows = $pdo->query(
        'SELECT cm.user_id, cm.muted_until, cm.created_at, cm.created_by_operator_id, u.username
         FROM chat_mutes cm
         INNER JOIN users u ON u.id = cm.user_id
         ORDER BY cm.muted_until DESC'
    )->fetchAll(PDO::FETCH_ASSOC);
    $mutes = [];
    $now = time();
    foreach ($muteRows as $mr) {
        $until = (int) $mr['muted_until'];
        $mutes[] = [
            'userId' => (int) $mr['user_id'],
            'username' => (string) $mr['username'],
            'mutedUntil' => $until,
            'active' => $until > $now,
            'createdAt' => (int) $mr['created_at'],
        ];
    }

    echo json_encode(
        [
            'ok' => true,
            'systemUserId' => $systemUid,
            'messages' => $messages,
            'mutes' => $mutes,
            'csrfToken' => mocker_csrf_token(),
        ],
        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
    );
    exit;
}

if ($method !== 'POST') {
    http_response_code(405);
    echo json_encode(['ok' => false, 'error' => 'method', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

mocker_require_csrf_post();

$input = json_decode((string) file_get_contents('php://input'), true) ?: [];
$action = trim((string) ($input['action'] ?? ''));

if ($action === 'delete') {
    $mid = (int) ($input['messageId'] ?? 0);
    if ($mid <= 0) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'messageId', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $chk = $pdo->prepare('SELECT id, deleted_at FROM chat_messages WHERE id = :id LIMIT 1');
    $chk->execute([':id' => $mid]);
    $row = $chk->fetch(PDO::FETCH_ASSOC);
    if (!$row) {
        http_response_code(404);
        echo json_encode(['ok' => false, 'error' => 'not_found', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    if ((int) ($row['deleted_at'] ?? 0) > 0) {
        echo json_encode(['ok' => true, 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $t = time();
    $opId = isset($_SESSION['mocker_admin_id']) ? (int) $_SESSION['mocker_admin_id'] : 0;
    if (($_SESSION['mocker_admin_kind'] ?? '') !== 'staff') {
        $opId = 0;
    }
    $upd = $pdo->prepare(
        'UPDATE chat_messages SET deleted_at = :t, deleted_by_operator_id = :op WHERE id = :id AND deleted_at IS NULL'
    );
    $upd->execute([':t' => $t, ':op' => $opId > 0 ? $opId : null, ':id' => $mid]);
    mocker_admin_audit_write($pdo, null, 'chat_message_delete', ['messageId' => $mid]);

    echo json_encode(['ok' => true, 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

if ($action === 'mute') {
    $userId = (int) ($input['userId'] ?? 0);
    $minutes = (int) ($input['minutes'] ?? 60);
    if ($userId <= 0) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'userId', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    if ($userId === mocker_chat_system_user_id($pdo)) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'invalid_user', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    if ($minutes < 1) {
        $minutes = 1;
    }
    if ($minutes > 10080) {
        $minutes = 10080;
    }
    $u = $pdo->prepare('SELECT id FROM users WHERE id = :id LIMIT 1');
    $u->execute([':id' => $userId]);
    if (!$u->fetch(PDO::FETCH_ASSOC)) {
        http_response_code(404);
        echo json_encode(['ok' => false, 'error' => 'user_not_found', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $now = time();
    $until = $now + $minutes * 60;
    $opId = isset($_SESSION['mocker_admin_id']) ? (int) $_SESSION['mocker_admin_id'] : 0;
    if (($_SESSION['mocker_admin_kind'] ?? '') !== 'staff') {
        $opId = 0;
    }
    $ins = $pdo->prepare(
        'INSERT INTO chat_mutes (user_id, muted_until, created_at, created_by_operator_id)
         VALUES (:uid, :u, :c, :op)
         ON CONFLICT(user_id) DO UPDATE SET
            muted_until = excluded.muted_until,
            created_at = excluded.created_at,
            created_by_operator_id = excluded.created_by_operator_id'
    );
    $ins->execute([
        ':uid' => $userId,
        ':u' => $until,
        ':c' => $now,
        ':op' => $opId > 0 ? $opId : null,
    ]);
    mocker_admin_audit_write($pdo, $userId, 'chat_user_mute', ['minutes' => $minutes, 'mutedUntil' => $until]);

    echo json_encode(['ok' => true, 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

if ($action === 'unmute') {
    $userId = (int) ($input['userId'] ?? 0);
    if ($userId <= 0) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'userId', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $del = $pdo->prepare('DELETE FROM chat_mutes WHERE user_id = :uid');
    $del->execute([':uid' => $userId]);
    mocker_admin_audit_write($pdo, $userId, 'chat_user_unmute', []);

    echo json_encode(['ok' => true, 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

if ($action === 'announce') {
    $body = (string) ($input['body'] ?? '');
    $body = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/u', '', $body);
    $body = trim($body);
    if ($body === '' || mocker_utf8_len($body) > 600) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'body', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $now = time();
    $sysUid = mocker_chat_system_user_id($pdo);
    $opId = isset($_SESSION['mocker_admin_id']) ? (int) $_SESSION['mocker_admin_id'] : 0;
    if (($_SESSION['mocker_admin_kind'] ?? '') !== 'staff') {
        $opId = 0;
    }
    $ins = $pdo->prepare(
        'INSERT INTO chat_messages (user_id, body, created_at, posted_by_operator_id) VALUES (:uid, :body, :t, :op)'
    );
    $ins->execute([
        ':uid' => $sysUid,
        ':body' => $body,
        ':t' => $now,
        ':op' => $opId > 0 ? $opId : null,
    ]);
    $mid = (int) $pdo->lastInsertId();
    mocker_admin_audit_write($pdo, null, 'chat_announce', ['messageId' => $mid, 'length' => strlen($body)]);

    echo json_encode(['ok' => true, 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
    exit;
}

http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'action', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
