<?php

declare(strict_types=1);

require_once __DIR__ . '/../src/config.php';
require_once __DIR__ . '/../src/settings.php';
require_once __DIR__ . '/../src/analytics.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, max-age=0');
header('X-Content-Type-Options: nosniff');

try {
    if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
        http_response_code(405);
        throw new InvalidArgumentException('Метод не поддерживается.');
    }
    $headers = function_exists('getallheaders') ? getallheaders() : [];
    $authorization = (string) ($headers['Authorization'] ?? $headers['authorization'] ?? '');
    $token = preg_match('/^Bearer\s+(.+)$/i', $authorization, $matches) ? trim($matches[1]) : '';
    $domain = (string) ($headers['X-Bitrix-Domain'] ?? $headers['x-bitrix-domain'] ?? '');
    $user = authorizeAppSettingsRequest($domain, $token);
    $userId = (string) ($user['ID'] ?? '');
    if (!ctype_digit($userId) || (int) $userId < 1) throw new RuntimeException('Нет доступа.');
    $input = json_decode((string) file_get_contents('php://input'), true, 16, JSON_THROW_ON_ERROR);
    if (!is_array($input)) throw new InvalidArgumentException('Некорректный запрос.');
    $file = dirname((string) config('CHAT_HISTORY_FILE')) . '/analytics/jobs/user_' . $userId . '.json';
    // One bounded job per user. A retry with the old cursor never counts a page twice.
    $job = updateJsonFile($file, [], static function (array $job) use ($input, $userId): array {
        if (($job['version'] ?? 0) !== 5) $job = [];
        if (($input['action'] ?? '') === 'start') {
            $inputs = analyticsInputs($input);
            $samePeriod = analyticsSamePeriod($job['inputs'] ?? [], $inputs);
            if ($samePeriod && !empty($job['completed_at']) && time() - strtotime($job['completed_at']) < 900) {
                $job['inputs'] = $inputs;
                return $job;
            }
            if ($samePeriod && $job && empty($job['completed_at']) && time() - strtotime($job['created_at']) < 86400) {
                $job['inputs'] = $inputs;
                return $job;
            }
            if ($job && time() - (strtotime((string) ($job['created_at'] ?? '')) ?: 0) < 30) {
                throw new InvalidArgumentException('Повторный расчёт доступен через 30 секунд.');
            }
            return analyticsNewJob($inputs, $userId);
        }
        if (($input['action'] ?? '') !== 'continue' || !$job || !is_string($input['job'] ?? null)
            || !hash_equals((string) $job['id'], $input['job']) || $job['user_id'] !== $userId
            || time() - strtotime($job['created_at']) > 86400) {
            throw new InvalidArgumentException('Расчёт устарел. Запустите его заново.');
        }
        $cursor = $input['cursor'] ?? null;
        if (!is_int($cursor) || $cursor < 0 || $cursor > $job['cursor']) throw new InvalidArgumentException('Некорректный шаг расчёта.');
        return $cursor === $job['cursor'] ? analyticsAdvanceJob($job) : $job;
    });
    echo json_encode(analyticsJobResponse($job), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
} catch (InvalidArgumentException | JsonException $error) {
    if (http_response_code() < 400) http_response_code(422);
    echo json_encode(['ok' => false, 'error' => $error->getMessage()], JSON_UNESCAPED_UNICODE);
} catch (Throwable $error) {
    if (http_response_code() < 400) http_response_code(isset($user) ? 503 : 403);
    error_log('Analytics error: ' . $error->getMessage());
    echo json_encode(['ok' => false, 'error' => isset($user) ? 'Не удалось прочитать данные для отчёта. Повторите расчёт позже.' : 'Нет доступа к аналитике приложения.'], JSON_UNESCAPED_UNICODE);
}
