<?php
declare(strict_types=1);

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

header('Content-Type: application/json; charset=utf-8');

$uid = isset($_SESSION['mocker_user_id']) ? (int) $_SESSION['mocker_user_id'] : 0;
$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));

if ($method === 'GET') {
    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;
    }

    $hasAfter = array_key_exists('after', $_GET);
    if (!$hasAfter) {
        $st = $pdo->query(
            'SELECT m.id, m.user_id AS userId, m.body, m.created_at AS createdAt, m.posted_by_operator_id,
                    u.username
             FROM chat_messages m
             INNER JOIN users u ON u.id = m.user_id
             WHERE m.deleted_at IS NULL
             ORDER BY m.id DESC
             LIMIT 100'
        );
        $rows = $st->fetchAll(PDO::FETCH_ASSOC);
        $rows = array_reverse($rows);
    } else {
        $after = (int) ($_GET['after'] ?? 0);
        if ($after < 0) {
            $after = 0;
        }
        $st = $pdo->prepare(
            'SELECT m.id, m.user_id AS userId, m.body, m.created_at AS createdAt, m.posted_by_operator_id,
                    u.username
             FROM chat_messages m
             INNER JOIN users u ON u.id = m.user_id
             WHERE m.id > :after AND m.deleted_at IS NULL
             ORDER BY m.id ASC
             LIMIT 150'
        );
        $st->execute([':after' => $after]);
        $rows = $st->fetchAll(PDO::FETCH_ASSOC);
    }

    $sysUid = mocker_chat_system_user_id($pdo);
    $out = [];
    foreach ($rows as $r) {
        $uidRow = mocker_chat_row_int($r, 'userId', 'userid', 'user_id');
        $postedRaw = mocker_chat_row_nullable_int($r, 'posted_by_operator_id');
        $postedBy = $postedRaw !== null && $postedRaw > 0 ? $postedRaw : 0;
        $rawUsername = mocker_chat_row_string($r, 'username');
        $rowForName = [
            'username' => $rawUsername,
            'user_id' => $uidRow,
            'posted_by_operator_id' => $postedBy > 0 ? $postedBy : null,
        ];
        $displayName = mocker_chat_display_name($pdo, $rowForName);
        $isSystemRow = $uidRow === $sysUid || strcasecmp($rawUsername, '__chat_system') === 0;
        $publicUsername = $isSystemRow ? $displayName : $rawUsername;
        $createdAt = mocker_chat_row_int($r, 'createdAt', 'createdat', 'created_at');
        $msgId = mocker_chat_row_int($r, 'id');
        $out[] = [
            'id' => $msgId,
            'userId' => $uidRow,
            'username' => $publicUsername,
            'displayName' => $displayName,
            'body' => mocker_chat_row_string($r, 'body'),
            'createdAt' => $createdAt,
            'fromManagement' => $postedBy > 0 || $uidRow === $sysUid,
        ];
    }

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

if ($method === 'POST') {
    if ($uid <= 0) {
        http_response_code(401);
        echo json_encode(
            ['ok' => false, 'error' => 'auth', 'csrfToken' => mocker_csrf_token()],
            JSON_UNESCAPED_UNICODE
        );
        exit;
    }

    mocker_require_csrf_post();

    $now = time();
    $last = isset($_SESSION['chat_last_post_at']) ? (int) $_SESSION['chat_last_post_at'] : 0;
    if ($now - $last < 3) {
        http_response_code(429);
        echo json_encode(
            [
                'ok' => false,
                'error' => 'rate',
                'retryAfter' => 3 - ($now - $last),
                'csrfToken' => mocker_csrf_token(),
            ],
            JSON_UNESCAPED_UNICODE
        );
        exit;
    }

    $input = json_decode((string) file_get_contents('php://input'), true) ?: [];
    $body = (string) ($input['body'] ?? '');
    $body = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/u', '', $body);
    $body = trim($body);
    $len = mocker_utf8_len($body);
    if ($body === '' || $len < 1) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'body', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }
    if ($len > 600) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'body_long', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }

    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;
    }

    $stMute = $pdo->prepare('SELECT muted_until FROM chat_mutes WHERE user_id = :uid LIMIT 1');
    $stMute->execute([':uid' => $uid]);
    $muteRow = $stMute->fetch(PDO::FETCH_ASSOC);
    if ($muteRow && (int) $muteRow['muted_until'] > $now) {
        http_response_code(403);
        echo json_encode(
            [
                'ok' => false,
                'error' => 'muted',
                'mutedUntil' => (int) $muteRow['muted_until'],
                'csrfToken' => mocker_csrf_token(),
            ],
            JSON_UNESCAPED_UNICODE
        );
        exit;
    }

    $stUser = $pdo->prepare('SELECT username FROM users WHERE id = :id LIMIT 1');
    $stUser->execute([':id' => $uid]);
    $urow = $stUser->fetch(PDO::FETCH_ASSOC);
    if (!$urow) {
        http_response_code(401);
        echo json_encode(['ok' => false, 'error' => 'auth', 'csrfToken' => mocker_csrf_token()], JSON_UNESCAPED_UNICODE);
        exit;
    }

    $ins = $pdo->prepare(
        'INSERT INTO chat_messages (user_id, body, created_at) VALUES (:uid, :body, :t)'
    );
    $ins->execute([
        ':uid' => $uid,
        ':body' => $body,
        ':t' => $now,
    ]);
    $mid = (int) $pdo->lastInsertId();
    $_SESSION['chat_last_post_at'] = $now;

    echo json_encode(
        [
            'ok' => true,
            'message' => [
                'id' => $mid,
                'userId' => $uid,
                'username' => (string) $urow['username'],
                'displayName' => (string) $urow['username'],
                'body' => $body,
                'createdAt' => $now,
            ],
            'csrfToken' => mocker_csrf_token(),
        ],
        JSON_UNESCAPED_UNICODE
    );
    exit;
}

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